UX Design Systems
Build consistent, maintainable design systems with tokens, components, and theming.
Design Tokens
CSS Variables
css:root { /* Colors */ --color-primary-50: #eff6ff; --color-primary-500: #3b82f6; --color-primary-900: #1e3a8a; /* Typography */ --font-sans: 'Inter', system-ui, sans-serif; --font-size-sm: 0.875rem; --font-size-base: 1rem; --font-size-lg: 1.125rem; /* Spacing */ --space-1: 0.25rem; --space-2: 0.5rem; --space-4: 1rem; --space-8: 2rem; /* Border Radius */ --radius-sm: 0.25rem; --radius-md: 0.375rem; --radius-lg: 0.5rem; --radius-full: 9999px; /* Shadows */ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); }
TypeScript Token System
typescriptexport const tokens = { colors: { primary: { 50: '#eff6ff', 500: '#3b82f6', 900: '#1e3a8a', }, gray: { 50: '#f9fafb', 500: '#6b7280', 900: '#111827', }, }, spacing: { 1: '0.25rem', 2: '0.5rem', 4: '1rem', 8: '2rem', }, fontSize: { sm: '0.875rem', base: '1rem', lg: '1.125rem', xl: '1.25rem', }, } as const; type ColorToken = keyof typeof tokens.colors; type SpaceToken = keyof typeof tokens.spacing;
Component Patterns
Button Component
tsximport { cva, type VariantProps } from 'class-variance-authority'; const buttonVariants = cva( 'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50', { variants: { variant: { primary: 'bg-primary-500 text-white hover:bg-primary-600', secondary: 'bg-gray-100 text-gray-900 hover:bg-gray-200', outline: 'border border-gray-300 bg-transparent hover:bg-gray-50', ghost: 'hover:bg-gray-100', destructive: 'bg-red-500 text-white hover:bg-red-600', }, size: { sm: 'h-8 px-3 text-sm', md: 'h-10 px-4 text-base', lg: 'h-12 px-6 text-lg', }, }, defaultVariants: { variant: 'primary', size: 'md', }, } ); interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> { isLoading?: boolean; } export function Button({ className, variant, size, isLoading, children, ...props }: ButtonProps) { return ( <button className={buttonVariants({ variant, size, className })} disabled={isLoading} {...props} > {isLoading && <Spinner className="mr-2 h-4 w-4" />} {children} </button> ); }
Dark Mode
CSS-Based Theme Switching
css:root { --bg-primary: #ffffff; --text-primary: #111827; --border-color: #e5e7eb; } [data-theme='dark'] { --bg-primary: #111827; --text-primary: #f9fafb; --border-color: #374151; }
React Theme Provider
tsximport { createContext, useContext, useEffect, useState } from 'react'; type Theme = 'light' | 'dark' | 'system'; const ThemeContext = createContext<{ theme: Theme; setTheme: (theme: Theme) => void; }>({ theme: 'system', setTheme: () => {} }); export function ThemeProvider({ children }: { children: React.ReactNode }) { const [theme, setTheme] = useState<Theme>('system'); useEffect(() => { const root = document.documentElement; if (theme === 'system') { const systemTheme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; root.setAttribute('data-theme', systemTheme); } else { root.setAttribute('data-theme', theme); } }, [theme]); return ( <ThemeContext.Provider value={{ theme, setTheme }}> {children} </ThemeContext.Provider> ); } export const useTheme = () => useContext(ThemeContext);
Resources
- Tailwind CSS: https://tailwindcss.com
- CVA (Class Variance Authority): https://cva.style

