设计与多媒体

Tailwind Design System

试用

Build scalable, themable Tailwind CSS component libraries using CVA for variants, compound components, design tokens, dark mode, and responsive grids.

它能做什么

Build production-ready component libraries with Tailwind CSS using CVA, compound components, design tokens, and theming.

技能文档

Tailwind Design System

Build production-ready component libraries with Tailwind CSS using CVA, compound components, design tokens, and theming.

WHAT

Patterns for scalable Tailwind-based design systems:

  • Class Variance Authority (CVA) for type-safe variants
  • Compound component architecture
  • CSS variable-based theming
  • Dark mode implementation
  • Responsive grid systems
  • Animation utilities

WHEN

  • Building a component library with Tailwind
  • Implementing design tokens and theming
  • Creating reusable UI components with variants
  • Setting up dark mode
  • Standardizing patterns across a codebase

KEYWORDS

tailwind, cva, design system, component library, variants, theming, dark mode, design tokens, shadcn, compound components, tailwind-merge

Related skills: tailwind-v4-shadcn for Tailwind v4 setup and migration

Installation

OpenClaw / Moltbot / Clawbot

npx clawhub@latest install tailwind-design-system

Core Setup

Utility Function

// lib/utils.ts
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

Design Token Architecture

Primitive Tokens (abstract)
    └── Semantic Tokens (purpose)
        └── Component Tokens (specific)

Example:
    slate-900 → foreground → card-title-color

Pattern 1: CVA Components

Class Variance Authority for type-safe, variant-based components:

// components/ui/button.tsx
import { cva, type VariantProps } from 'class-variance-authority'
import { forwardRef } from 'react'
import { cn } from '@/lib/utils'

const buttonVariants = cva(
  // Base styles (always applied)
  'inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default: 'bg-primary text-primary-foreground hover:bg-primary/90',
        destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
        outline: 'border border-input bg-background hover:bg-accent hover:text-accent-foreground',
        secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
        ghost: 'hover:bg-accent hover:text-accent-foreground',
        link: 'text-primary underline-offset-4 hover:underline',
      },
      size: {
        default: 'h-10 px-4 py-2',
        sm: 'h-9 rounded-md px-3',
        lg: 'h-11 rounded-md px-8',
        icon: 'h-10 w-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
)

export interface ButtonProps
  extends React.ButtonHTMLAttributes,
    VariantProps {
  asChild?: boolean
}

const Button = forwardRef(
  ({ className, variant, size, ...props }, ref) => {
    return (
      
    )
  }
)
Button.displayName = 'Button'

export { Button, buttonVariants }

Usage:

Delete
Cancel


Pattern 2: Compound Components

Composable components with shared context:

// components/ui/card.tsx
import { cn } from '@/lib/utils'
import { forwardRef } from 'react'

const Card = forwardRef>(
  ({ className, ...props }, ref) => (
    
  )
)
Card.displayName = 'Card'

const CardHeader = forwardRef>(
  ({ className, ...props }, ref) => (
    
  )
)
CardHeader.displayName = 'CardHeader'

const CardTitle = forwardRef>(
  ({ className, ...props }, ref) => (
    
  )
)
CardTitle.displayName = 'CardTitle'

const CardDescription = forwardRef>(
  ({ className, ...props }, ref) => (
    
  )
)
CardDescription.displayName = 'CardDescription'

const CardContent = forwardRef>(
  ({ className, ...props }, ref) => (
    
  )
)
CardContent.displayName = 'CardContent'

const CardFooter = forwardRef>(
  ({ className, ...props }, ref) => (
    
  )
)
CardFooter.displayName = 'CardFooter'

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

Usage:


  
    Account Settings
    Manage your account preferences
  
  
    {/* form fields */}
  
  
    Save Changes
  


Pattern 3: Form Components with Validation

// components/ui/input.tsx
import { forwardRef } from 'react'
import { cn } from '@/lib/utils'

export interface InputProps extends React.InputHTMLAttributes {
  error?: string
}

const Input = forwardRef(
  ({ className, type, error, ...props }, ref) => {
    return (
      
        
        {error && (
          
            {error}
          
        )}
      
    )
  }
)
Input.displayName = 'Input'

export { Input }

Pattern 4: Grid System

// components/ui/grid.tsx
import { cn } from '@/lib/utils'
import { cva, type VariantProps } from 'class-variance-authority'

const gridVariants = cva('grid', {
  variants: {
    cols: {
      1: 'grid-cols-1',
      2: 'grid-cols-1 sm:grid-cols-2',
      3: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-3',
      4: 'grid-cols-1 sm:grid-cols-2 lg:grid-cols-4',
    },
    gap: {
      none: 'gap-0',
      sm: 'gap-2',
      md: 'gap-4',
      lg: 'gap-6',
      xl: 'gap-8',
    },
  },
  defaultVariants: {
    cols: 3,
    gap: 'md',
  },
})

interface GridProps extends React.HTMLAttributes, VariantProps {}

export function Grid({ className, cols, gap, ...props }: GridProps) {
  return 
}

// Container component
const containerVariants = cva('mx-auto w-full px-4 sm:px-6 lg:px-8', {
  variants: {
    size: {
      sm: 'max-w-screen-sm',
      md: 'max-w-screen-md',
      lg: 'max-w-screen-lg',
      xl: 'max-w-screen-xl',
      '2xl': 'max-w-screen-2xl',
      full: 'max-w-full',
    },
  },
  defaultVariants: {
    size: 'xl',
  },
})

interface ContainerProps extends React.HTMLAttributes, VariantProps {}

export function Container({ className, size, ...props }: ContainerProps) {
  return 
}

Usage:


  
    {products.map(product => (
      
    ))}
  


Pattern 5: Dark Mode

Theme Provider

// providers/theme-provider.tsx
'use client'

import { createContext, useContext, useEffect, useState } from 'react'

type Theme = 'dark' | 'light' | 'system'

interface ThemeContextType {
  theme: Theme
  setTheme: (theme: Theme) => void
  resolvedTheme: 'dark' | 'light'
}

const ThemeContext = createContext(undefined)

export function ThemeProvider({
  children,
  defaultTheme = 'system',
  storageKey = 'theme',
}: {
  children: React.ReactNode
  defaultTheme?: Theme
  storageKey?: string
}) {
  const [theme, setTheme] = useState(defaultTheme)
  const [resolvedTheme, setResolvedTheme] = useState<'dark' | 'light'>('light')

  useEffect(() => {
    const stored = localStorage.getItem(storageKey) as Theme | null
    if (stored) setTheme(stored)
  }, [storageKey])

  useEffect(() => {
    const root = window.document.documentElement
    root.classList.remove('light', 'dark')

    const resolved = theme === 'system'
      ? window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
      : theme

    root.classList.add(resolved)
    setResolvedTheme(resolved)
  }, [theme])

  return (
     { localStorage.setItem(storageKey, t); setTheme(t) },
      resolvedTheme,
    }}>
      {children}
    
  )
}

export const useTheme = () => {
  const context = useContext(ThemeContext)
  if (!context) throw new Error('useTheme must be used within ThemeProvider')
  return context
}

Theme Toggle

import { Moon, Sun } from 'lucide-react'
import { useTheme } from '@/providers/theme-provider'
import { Button } from '@/components/ui/button'

export function ThemeToggle() {
  const { resolvedTheme, setTheme } = useTheme()

  return (
     setTheme(resolvedTheme === 'dark' ? 'light' : 'dark')}
    >
      
      
      Toggle theme
    
  )
}

Animation Utilities

// lib/animations.ts
import { cn } from './utils'

export const fadeIn = 'animate-in fade-in duration-300'
export const fadeOut = 'animate-out fade-out duration-300'
export const slideInFromTop = 'animate-in slide-in-from-top duration-300'
export const slideInFromBottom = 'animate-in slide-in-from-bottom duration-300'
export const zoomIn = 'animate-in zoom-in-95 duration-300'
export const zoomOut = 'animate-out zoom-out-95 duration-300'

// Compound animations
export const modalEnter = cn(fadeIn, zoomIn, 'duration-200')
export const modalExit = cn(fadeOut, zoomOut, 'duration-200')
export const dropdownEnter = cn(fadeIn, slideInFromTop, 'duration-150')

Best Practices

Do

  • Use CSS variables for theming (enables runtime switching)
  • Compose variants with CVA (type-safe, explicit)
  • Use semantic color names (primary not blue-500)
  • Forward refs for composition
  • Add accessibility attributes (ARIA, focus states)
  • Use tailwind-merge to handle class conflicts

Don't

  • Use arbitrary values when you can extend the theme
  • Nest @apply deeply (hurts readability)
  • Skip focus states (keyboard users need them)
  • Hardcode colors (use semantic tokens)
  • Forget to test dark mode

NEVER

  • Use hardcoded colors like bg-blue-500 for semantic purposes (use bg-primary)
  • Skip focus-visible styles on interactive elements
  • Mix arbitrary values with design tokens inconsistently
  • Forget forwardRef on reusable components
  • Use !important to override styles (fix the cascade instead)

相关技能

以 AI 机器人身份加入视频会议,提供语音、虚拟形象与屏幕共享四种模式。

作者 johnpatternai21 次安装8 星标

pdf

官方

用 Python 库和命令行工具完成 PDF 的读取、合并、拆分、生成与内容抽取。

作者 Anthropic177.6k 星标

通过组合目标文件已发布的设计系统组件、变量和样式来构建或更新完整 Figma 页面。

作者 OpenAI27.6k 星标

hatch-pet

官方

从文字、参考图或品牌线索生成 Codex 兼容的 9 状态动画宠物图集,附带 QA 联系表与 pet.json 打包。

作者 OpenAI27.6k 星标

wpank 的更多技能

浏览全部技能

Systematic code review patterns covering security, performance, maintainability, correctness, and testing — with severity levels, structured feedback guidance, review process, and anti-patterns to avoid. Use when reviewing PRs, establishing review standards, or improving review quality.

作者 wpank553 次安装20 星标

Pragmatic coding standards for writing clean, maintainable code — naming, functions, structure, anti-patterns, and pre-edit safety checks. Use when writing new code, refactoring existing code, reviewing code quality, or establishing coding standards.

作者 wpank198 次安装6 星标

Build reliable, fast E2E test suites with Playwright and Cypress. Critical user journey coverage, flaky test elimination, CI/CD integration.

作者 wpank336 次安装6 星标

Create software diagrams using Mermaid syntax. Use when users need to create, visualize, or document software through diagrams including class diagrams, sequence diagrams, flowcharts, ERDs, C4 architecture diagrams, state diagrams, git graphs, and other diagram types. Triggers include requests to diagram, visualize, model, map out, or show the flow of a system.

作者 wpank251 次安装5 星标

Provides backend architecture patterns (Clean Architecture, Hexagonal, DDD) for building maintainable, testable, and scalable systems with clear layering and...

作者 wpank152 次安装7 星标

React and Next.js performance optimization guidelines from Vercel Engineering. 57 rules across 8 categories for writing, reviewing, and refactoring React code.

作者 wpank190 次安装4 星标