cn()
The cn() function is a utility for merging and deduplicating class names with Tailwind CSS. It combines clsx for conditional class names with tailwind-merge for intelligent merging of Tailwind classes.
Function Signature
function cn(...inputs: ClassValue[]): string
Variable number of class values to merge. Accepts strings, objects, arrays, or any valid clsx input.
A merged and deduplicated class name string.
Features
- Conditional Classes: Use objects or arrays for conditional class application
- Tailwind Merge: Automatically resolves conflicting Tailwind classes
- Type-Safe: Full TypeScript support with
ClassValue type
- Flexible Input: Accepts multiple argument formats
Usage Examples
Basic Usage
import { cn } from 'stride-ds';
// Simple merge
const className = cn('text-base', 'font-medium');
// Result: "text-base font-medium"
Conditional Classes
const className = cn(
'button',
isActive && 'active',
isDisabled && 'disabled'
);
// Result: "button active" (if isActive is true)
Tailwind Conflict Resolution
const className = cn('px-2 py-1', 'p-4');
// Result: "p-4" (later padding value wins)
const className = cn('text-sm', 'text-base');
// Result: "text-base" (later font size wins)
With Objects
const className = cn({
'bg-blue-500': isPrimary,
'bg-gray-500': !isPrimary,
'opacity-50': isDisabled
});
Component Props Pattern
interface ButtonProps {
variant: 'primary' | 'secondary';
className?: string;
}
const Button = ({ variant, className }: ButtonProps) => {
return (
<button
className={cn(
'base-button-styles',
variant === 'primary' && 'primary-styles',
variant === 'secondary' && 'secondary-styles',
className // User overrides
)}
/>
);
};
With CVA (Class Variance Authority)
import { cva } from 'class-variance-authority';
import { cn } from 'stride-ds';
const buttonVariants = cva('button-base', {
variants: {
variant: {
primary: 'bg-blue-500',
secondary: 'bg-gray-500'
},
size: {
sm: 'text-sm px-2',
lg: 'text-lg px-4'
}
}
});
const Button = ({ variant, size, className }) => (
<button className={cn(buttonVariants({ variant, size }), className)} />
);
Integration
The cn() utility integrates seamlessly with:
- clsx: For conditional class name construction
- tailwind-merge: For resolving Tailwind CSS class conflicts
- class-variance-authority: For variant-based component styling
- React Aria Components: For accessible component class management
Implementation
import { type ClassValue, clsx } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Why Use cn()?
- Avoids Class Conflicts: Automatically resolves Tailwind utility conflicts
- Cleaner Code: Simplifies conditional class logic
- Type Safety: Full TypeScript support
- Performance: Optimized for production use
- Standard Pattern: Widely adopted in the React ecosystem