Claude
Skills
Sign in
Back

tailwindcss-advanced-components

Included with Lifetime
$97 forever

Tailwind CSS advanced component patterns with CVA (class-variance-authority) and variant management. PROACTIVELY activate for: (1) building reusable component variants with CVA, (2) compound variants for complex states, (3) tailwind-merge for safe class composition, (4) clsx/cn utility for conditional classes, (5) Headless UI / Radix UI primitives styled with Tailwind, (6) shadcn/ui patterns, (7) component slot patterns (asChild), (8) polymorphic components, (9) prop-driven design tokens. Provides: CVA setup recipes, cn utility implementation, compound-variant patterns, shadcn/ui-style component templates, and asChild slot examples.

Design

What this skill does


# Tailwind CSS Advanced Component Patterns

## Component Variants with CVA

### Class Variance Authority Integration

```bash
npm install class-variance-authority
```

```typescript
// components/Button.tsx
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';

const buttonVariants = cva(
  // Base styles
  'inline-flex items-center justify-center rounded-lg font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default: 'bg-brand-500 text-white hover:bg-brand-600 focus-visible:ring-brand-500',
        secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200 focus-visible:ring-gray-500',
        outline: 'border border-gray-300 bg-transparent hover:bg-gray-100 focus-visible:ring-gray-500',
        ghost: 'hover:bg-gray-100 focus-visible:ring-gray-500',
        destructive: 'bg-red-500 text-white hover:bg-red-600 focus-visible:ring-red-500',
        link: 'text-brand-500 underline-offset-4 hover:underline',
      },
      size: {
        sm: 'h-8 px-3 text-sm',
        md: 'h-10 px-4 text-sm',
        lg: 'h-12 px-6 text-base',
        xl: 'h-14 px-8 text-lg',
        icon: 'h-10 w-10',
      },
      fullWidth: {
        true: 'w-full',
      },
    },
    compoundVariants: [
      {
        variant: 'outline',
        size: 'sm',
        className: 'border',
      },
      {
        variant: 'outline',
        size: ['md', 'lg', 'xl'],
        className: 'border-2',
      },
    ],
    defaultVariants: {
      variant: 'default',
      size: 'md',
    },
  }
);

export interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
}

export function Button({
  className,
  variant,
  size,
  fullWidth,
  asChild = false,
  ...props
}: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant, size, fullWidth, className }))}
      {...props}
    />
  );
}
```

### Usage

```tsx
<Button>Default</Button>
<Button variant="secondary" size="lg">Large Secondary</Button>
<Button variant="destructive" fullWidth>Delete</Button>
<Button variant="ghost" size="icon"><IconMenu /></Button>
```

## Compound Components Pattern

### Context-Based Component System

```tsx
// components/Card/index.tsx
import { createContext, useContext, forwardRef } from 'react';
import { cn } from '@/lib/utils';

// Context for shared state
const CardContext = createContext<{ variant?: 'default' | 'elevated' | 'outline' }>({});

// Root component
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
  variant?: 'default' | 'elevated' | 'outline';
}

const Card = forwardRef<HTMLDivElement, CardProps>(
  ({ className, variant = 'default', children, ...props }, ref) => {
    const variants = {
      default: 'bg-white border border-gray-200',
      elevated: 'bg-white shadow-lg',
      outline: 'bg-transparent border-2 border-gray-300',
    };

    return (
      <CardContext.Provider value={{ variant }}>
        <div
          ref={ref}
          className={cn(
            'rounded-xl',
            variants[variant],
            className
          )}
          {...props}
        >
          {children}
        </div>
      </CardContext.Provider>
    );
  }
);

// Sub-components
const CardHeader = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, ...props }, ref) => (
    <div
      ref={ref}
      className={cn('flex flex-col gap-1.5 p-6 pb-0', className)}
      {...props}
    />
  )
);

const CardTitle = forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(
  ({ className, ...props }, ref) => (
    <h3
      ref={ref}
      className={cn('text-xl font-semibold leading-none tracking-tight', className)}
      {...props}
    />
  )
);

const CardDescription = forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
  ({ className, ...props }, ref) => (
    <p
      ref={ref}
      className={cn('text-sm text-gray-500', className)}
      {...props}
    />
  )
);

const CardContent = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, ...props }, ref) => (
    <div ref={ref} className={cn('p-6', className)} {...props} />
  )
);

const CardFooter = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
  ({ className, ...props }, ref) => (
    <div
      ref={ref}
      className={cn('flex items-center p-6 pt-0', className)}
      {...props}
    />
  )
);

// Named exports
Card.displayName = 'Card';
CardHeader.displayName = 'CardHeader';
CardTitle.displayName = 'CardTitle';
CardDescription.displayName = 'CardDescription';
CardContent.displayName = 'CardContent';
CardFooter.displayName = 'CardFooter';

export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter };
```

### Usage

```tsx
<Card variant="elevated">
  <CardHeader>
    <CardTitle>Account Settings</CardTitle>
    <CardDescription>Manage your account preferences</CardDescription>
  </CardHeader>
  <CardContent>
    <form>...</form>
  </CardContent>
  <CardFooter className="justify-between">
    <Button variant="ghost">Cancel</Button>
    <Button>Save Changes</Button>
  </CardFooter>
</Card>
```

## Data Attribute Variants

### CSS-Based State Management

```css
/* Define data attribute variants */
@custom-variant data-state-open (&[data-state="open"]);
@custom-variant data-state-closed (&[data-state="closed"]);
@custom-variant data-side-top (&[data-side="top"]);
@custom-variant data-side-bottom (&[data-side="bottom"]);
@custom-variant data-side-left (&[data-side="left"]);
@custom-variant data-side-right (&[data-side="right"]);
@custom-variant data-highlighted (&[data-highlighted]);
@custom-variant data-disabled (&[data-disabled]);
```

```tsx
// Dropdown component using data attributes
function DropdownContent({ children, ...props }) {
  return (
    <div
      data-state={isOpen ? 'open' : 'closed'}
      data-side={side}
      className="
        absolute z-50 min-w-[8rem] overflow-hidden rounded-md
        border border-gray-200 bg-white p-1 shadow-lg

        data-state-open:animate-in
        data-state-open:fade-in-0
        data-state-open:zoom-in-95

        data-state-closed:animate-out
        data-state-closed:fade-out-0
        data-state-closed:zoom-out-95

        data-side-top:slide-in-from-bottom-2
        data-side-bottom:slide-in-from-top-2
        data-side-left:slide-in-from-right-2
        data-side-right:slide-in-from-left-2
      "
      {...props}
    >
      {children}
    </div>
  );
}

function DropdownItem({ children, disabled, ...props }) {
  return (
    <div
      data-highlighted={isHighlighted || undefined}
      data-disabled={disabled || undefined}
      className="
        relative flex cursor-pointer select-none items-center
        rounded-sm px-2 py-1.5 text-sm outline-none

        data-highlighted:bg-gray-100
        data-disabled:pointer-events-none
        data-disabled:opacity-50
      "
      {...props}
    >
      {children}
    </div>
  );
}
```

## Group and Peer Patterns

### Complex State Propagation

```html
<!-- Group pattern: Parent hover affects children -->
<div class="group relative overflow-hidden rounded-xl">
  <img
    src="image.jpg"
    class="transition-transform duration-300 group-hover:scale-110"
  />
  <div class="
    absolute inset-0 bg-gradient-to-t from-black/80 to-transparent
    opacity-0 transition-opacity group-hover:opacity-100
  ">
    <div class="
      absolute bottom-0 left-0 right-0 p-6
      translate-y-4 transition-transform group-hover:translate-y-0
    ">
      <h3 class="text-xl font-bold text-white">Title</h3>
      <p class="text-gray-200">Description</p>
    </div>
  </div>
</div>

<!-- Named groups for nested components -->
<div class="group/card">
  <div class="group/header">
    <button class="group-hover/

Related in Design