一键导入
client-classnames
Use when adding or changing conditional class names in apps/client.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Use when adding or changing conditional class names in apps/client.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Use when adding, changing, extracting, or reusing client components, including Storybook stories and controls.
Use when adding or changing forms in apps/client.
Use when changing GitHub OAuth, session cookies, SessionGuard, logout, or authenticated API request identity.
Use when adding or changing routes in apps/client.
Use when adding or changing client state, React Query data flow, immutable context values, or Zustand stores.
Use when styling apps/client with Tailwind CSS v4.
| name | client-classnames |
| description | Use when adding or changing conditional class names in apps/client. |
Generated from ai/registry.json. Do not edit manually.
Canonical skill: ../../../ai/skills/client-classnames.md.
Referenced context:
../../../ai/rules/client-styling-rules.md../../../ai/examples/good-client-component.mdThis file is compiled from canonical AI knowledge files. Edit canonical files under ai, then run npm run ai:sync.
ai/skills/client-classnames.mdUse this skill when adding or changing conditional class names in apps/client.
Compose conditional Tailwind class names consistently without adding local helper variants.
ai/rules/client-styling-rules.mdai/examples/good-client-component.mdcls only when conditional classes or caller-provided className need composition.classnames is imported as cls.classNames, cn, or wrapper helper is added without repeated need.npm --workspace @capture-flag/client run build.ai/rules/client-styling-rules.mdRules for Tailwind CSS v4 and class composition in apps/client.
@tailwindcss/vite and @import "tailwindcss".styles.css with CSS custom properties and @theme inline when they are true app-wide tokens.classnames package for conditional class composition.classnames as cls with import cls from "classnames";.cls("base", { "active": isActive }).cls when appending or composing conditional class sets.classNames, cn, or wrapper helpers without a concrete repeated need.styles.css when component utility classes can express the behavior.npm --workspace @capture-flag/client run build after styling changes.ai/examples/good-client-component.mdSource: apps/client/src/components/Button.tsx (sha256: 7e1bcb1c45c5d1a5610f108be5028ce68d34ded2c394d326428eca08702a992d)
Source: apps/client/src/components/Panel.tsx (sha256: c0dfcd9d6984e9741af7abe91c60ad8bcb30e4d8f18c3c1456bdea5882d2472f)
Why this is canonical:
classnames as cls for optional classes.Canonical shared component patterns from apps/client/src/components.
import cls from "classnames";
import type { ComponentPropsWithoutRef } from "react";
type ButtonVariant = "primary" | "secondary" | "danger" | "ghost";
const baseButtonClassName =
"inline-flex h-9 shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md px-4 py-2 text-sm font-medium shadow-xs outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4";
const buttonClassNames: Record<ButtonVariant, string> = {
danger:
"border border-transparent bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20",
ghost:
"border border-transparent bg-transparent text-foreground shadow-none hover:bg-accent hover:text-accent-foreground",
primary: "border border-transparent bg-primary text-primary-foreground hover:bg-primary/90",
secondary:
"border border-border bg-background text-foreground hover:bg-accent hover:text-accent-foreground",
};
type ButtonProps = ComponentPropsWithoutRef<"button"> & {
variant?: ButtonVariant;
};
export function Button({ className, variant = "primary", ...props }: ButtonProps) {
return (
<button className={cls(baseButtonClassName, buttonClassNames[variant], className)} {...props} />
);
}
This accepts native button props, keeps variants explicit, and uses cls for optional classes.
export function Panel({ children, className, showTitle = true, title, wide = false }: PanelProps) {
return (
<section
className={cls("grid gap-4 text-foreground", className, {
"lg:col-span-2": wide,
})}
>
{showTitle ? <h2 className="text-xl font-semibold tracking-tight">{title}</h2> : null}
{children}
</section>
);
}
This keeps layout composition explicit through children, accepts optional native composition through className, and preserves product visual language.