Class names
Joins class names and resolves Tailwind conflicts, last one wins, knowing the theme's own tokens.
@zenoxai/ui/lib/utils Markdownrounded-md border py-1 text-sm border-primary bg-primary-soft text-primary-soft-foreground px-3function ClassNamesDemo() {
const [selected, setSelected] = React.useState(true)
const className = cn(
"rounded-md border border-border px-2 py-1 text-sm",
selected && "border-primary bg-primary-soft text-primary-soft-foreground",
"px-3"
)
return (
<div className="flex flex-col items-start gap-3">
<div className="flex items-center gap-2">
<Switch
id="class-names-selected"
checked={selected}
onCheckedChange={setSelected}
/>
<Label htmlFor="class-names-selected">Selected</Label>
</div>
<span className={className}>Critical</span>
<code className="font-mono text-sm wrap-anywhere text-text-secondary">
{className}
</code>
</div>
)
}Usage
import { cn } from "@zenoxai/ui/lib/utils"
<span className={cn("px-2 text-sm", selected && "bg-primary-soft", className)} />
Use cn for every className built from more than one source: a component’s own classes, a
condition and the caller’s className. The last class wins a conflict, so the caller can
override a padding or a color.
A bare twMerge does not know the tokens this theme adds, such as text-md and
text-dense-xs, and drops one of two classes it cannot tell apart. cn registers them.
It is a plain function, with no React and no DOM: it runs in a Server Component too.
API reference
Generated from the TypeScript source and its JSDoc.
cn
cn(...inputs: ClassValue[]): stringcn joins class names and resolves Tailwind conflicts, last one wins: cn("px-2", condition && "px-4", className). Use it for every className that is built from more than one source.
| Parameter | Type |
|---|---|
...inputsoptional | ClassValue[]Class names, and falsy values that are skipped, as in clsx. |
- Returns
string - One class string, with the conflicts resolved.