--- name: ui-design description: Expert UI design and visual design guidance for design systems, typography, color theory, layout, spacing, iconography, and component visual design. Use when designing interfaces, creating visual hierarchies, choosing colors, defining typography scales, creating design tokens, working with Figma, or building cohesive visual systems. Includes brand application and design-to-dev handoff. --- # UI Design Expert ## Core UI Design Principles When designing user interfaces, always follow these principles: 1. **Visual Hierarchy**: Guide attention through size, weight, color, contrast 2. **Consistency**: Use systematic patterns for predictability 3. **White Space**: Breathing room improves comprehension 4. **Contrast**: Ensure readability and focus 5. **Alignment**: Create order and visual connections 6. **Repetition**: Reinforce brand and structure --- ## Design System Foundation ### Design Tokens (Variables) **Purpose**: Single source of truth for design decisions **Token Categories**: ```css /* Color Tokens */ --color-primary: #0066cc; --color-secondary: #6c757d; --color-success: #28a745; --color-warning: #ffc107; --color-danger: #dc3545; --color-text: #212529; --color-background: #ffffff; /* Spacing Scale (8px base) */ --space-2: 0.125rem; /* 2px */ --space-4: 0.25rem; /* 4px */ --space-8: 0.5rem; /* 8px */ --space-12: 0.75rem; /* 12px */ --space-16: 1rem; /* 16px */ --space-24: 1.5rem; /* 24px */ --space-32: 2rem; /* 32px */ --space-48: 3rem; /* 48px */ --space-64: 4rem; /* 64px */ /* Typography Scale (Modular 1.25 ratio) */ --font-size-xs: 0.75rem; /* 12px */ --font-size-sm: 0.875rem; /* 14px */ --font-size-base: 1rem; /* 16px */ --font-size-lg: 1.25rem; /* 20px */ --font-size-xl: 1.5rem; /* 24px */ --font-size-2xl: 2rem; /* 32px */ --font-size-3xl: 2.5rem; /* 40px */ --font-size-4xl: 3rem; /* 48px */ --font-size-display: clamp(5rem, 10vw + 3rem, 8rem); /* 80-128px */ /* Font Weights */ --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; /* Line Heights */ --line-height-tight: 1.2; --line-height-normal: 1.5; --line-height-relaxed: 1.75; /* Border Radius */ --radius-sm: 0.25rem; /* 4px */ --radius-md: 0.5rem; /* 8px */ --radius-lg: 1rem; /* 16px */ --radius-full: 9999px; /* Circle */ /* Shadows */ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1); --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1); /* Z-Index Scale */ --z-dropdown: 1000; --z-sticky: 1020; --z-fixed: 1030; --z-modal-backdrop: 1040; --z-modal: 1050; --z-popover: 1060; --z-tooltip: 1070; ``` --- ## Color System ### Color Theory for UI **60-30-10 Rule**: - **60%**: Dominant color (backgrounds, large areas) - **30%**: Secondary color (sections, panels) - **10%**: Accent color (CTAs, highlights) ### Semantic Color Palette ``` Primary (Brand): ├── primary-50: #e6f2ff (lightest - backgrounds) ├── primary-100: #b3d9ff ├── primary-200: #80c0ff ├── primary-300: #4da7ff ├── primary-400: #1a8eff ├── primary-500: #0066cc ← Base ├── primary-600: #0052a3 ├── primary-700: #003d7a ├── primary-800: #002952 └── primary-900: #001429 (darkest - text on light bg) Success (Green): ├── Positive actions ├── Confirmation states └── Valid inputs Warning (Yellow/Orange): ├── Caution states ├── Important notices └── Pending actions Danger (Red): ├── Destructive actions ├── Error states └── Invalid inputs Neutral (Gray): ├── Text hierarchy ├── Borders └── Disabled states ``` ### Color Accessibility (WCAG) **Contrast Ratios**: - **AA Standard**: 4.5:1 for normal text, 3:1 for large text (18px+) - **AAA Enhanced**: 7:1 for normal text, 4.5:1 for large text **Test Colors**: ```bash # Use WebAIM Contrast Checker https://webaim.org/resources/contrastchecker/ # Or test in code npm install wcag-color ``` **Example**: ``` ✅ PASS: #0066cc text on #ffffff background (7.5:1) ❌ FAIL: #80c0ff text on #ffffff background (2.1:1) ``` ### Dark Mode Strategy **Approach**: Invert semantic colors, not direct colors ```css /* Light Mode */ :root { --color-background: #ffffff; --color-surface: #f8f9fa; --color-text: #212529; --color-text-secondary: #6c757d; --color-border: #dee2e6; } /* Dark Mode */ [data-theme="dark"] { --color-background: #1a1a1a; --color-surface: #2d2d2d; --color-text: #f8f9fa; --color-text-secondary: #adb5bd; --color-border: #495057; /* Reduce saturation for less eye strain */ --color-primary: #4da7ff; /* Lighter than light mode */ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.5); /* Deeper shadows */ } ``` --- ## Typography ### Type Scale (Modular Scale) **Formula**: `base × ratio^n` **Common Ratios**: - **1.125** (Major Second): Subtle, dense - **1.25** (Major Third): Balanced ← Recommended - **1.333** (Perfect Fourth): Dynamic - **1.5** (Perfect Fifth): Dramatic **Digitaltableteur Scale** (1.25 ratio): ``` Display: 80-128px (clamp) H1: 48px H2: 40px H3: 32px H4: 24px H5: 20px Body: 16px Small: 14px Caption: 12px ``` ### Font Pairing **Recommended Combinations**: 1. **Serif + Sans-Serif** (Classic) - Headings: Playfair Display (serif) - Body: Inter (sans-serif) 2. **Geometric + Humanist** (Modern) - Headings: Montserrat (geometric) - Body: Open Sans (humanist) 3. **Monospace + Sans** (Technical) - Code: Fira Code (monospace) - UI: Roboto (sans-serif) **Digitaltableteur Stack**: ```css --font-title: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --font-body: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --font-mono: 'Fira Code', 'Courier New', monospace; ``` ### Typographic Hierarchy ```css /* Display (Hero Headlines) */ .display { font-size: var(--font-size-display); line-height: var(--line-height-tight); font-weight: var(--font-weight-bold); letter-spacing: -0.02em; /* Tighter for large sizes */ } /* H1 (Page Title) */ h1 { font-size: var(--font-size-4xl); line-height: var(--line-height-tight); font-weight: var(--font-weight-bold); } /* H2 (Section Title) */ h2 { font-size: var(--font-size-3xl); line-height: var(--line-height-normal); font-weight: var(--font-weight-semibold); } /* Body (Paragraph) */ p { font-size: var(--font-size-base); line-height: var(--line-height-relaxed); font-weight: var(--font-weight-normal); max-width: 65ch; /* Optimal reading width */ } /* Small (Caption, Meta) */ small { font-size: var(--font-size-sm); line-height: var(--line-height-normal); color: var(--color-text-secondary); } ``` ### Readability Guidelines - **Line Length**: 45-75 characters (optimal: 65ch) - **Line Height**: 1.5× font size for body text - **Paragraph Spacing**: 1.5× line height - **Letter Spacing**: -0.02em for large text, 0em for body --- ## Layout & Spacing ### Grid System **12-Column Grid** (flexible): ```css .container { max-width: 1200px; margin-inline: auto; padding-inline: var(--space-16); } .grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--space-24); } /* 3-column layout */ .col-4 { grid-column: span 4; } /* Responsive */ @media (max-width: 768px) { .grid { grid-template-columns: 1fr; } .col-4 { grid-column: span 1; } } ``` ### Spacing System (8px Base) **Concept**: All spacing uses multiples of 8px for visual consistency ``` 2px: Micro (icon padding) 4px: Tiny (inline spacing) 8px: Small (tight elements) 12px: Compact (related items) 16px: Base (default spacing) 24px: Medium (section padding) 32px: Large (cards, panels) 48px: XL (major sections) 64px: XXL (hero sections) ``` **Application**: ```css /* Component Internal Spacing */ .card { padding: var(--space-24); /* 24px */ } /* Component External Spacing */ .card + .card { margin-block-start: var(--space-16); /* 16px gap */ } /* Section Spacing */ .section { padding-block: var(--space-64); /* 64px top/bottom */ } ``` ### Whitespace Principles **Law of Proximity**: Related items closer, unrelated farther ``` Bad Example: ┌─────────────┐ │ Title │ ← 8px gap │ Subtitle │ ← 8px gap │ Author │ ← 8px gap (too uniform) │ Date │ └─────────────┘ Good Example: ┌─────────────┐ │ Title │ ← 4px gap (related) │ Subtitle │ ← 24px gap (separate group) │ Author │ ← 4px gap (related) │ Date │ └─────────────┘ ``` --- ## Component Visual Design ### Button Anatomy ``` ┌────────────────────────────┐ │ [Icon] Label [Icon] │ ← Text: 14-16px, weight: 500-600 │ ↑ ↑ ↑ │ │ 8px 12px 8px │ ← Spacing └────────────────────────────┘ ↑ ↑ 12px padding 12px padding Height: 40-48px (min 44px for touch) Border-radius: 8px ``` **Button Hierarchy**: ```css /* Primary (High emphasis) */ .btn-primary { background-color: var(--color-primary); color: white; font-weight: 600; box-shadow: var(--shadow-sm); } .btn-primary:hover { background-color: var(--color-primary-600); box-shadow: var(--shadow-md); transform: translateY(-1px); } /* Secondary (Medium emphasis) */ .btn-secondary { background-color: transparent; color: var(--color-primary); border: 2px solid var(--color-primary); } /* Tertiary (Low emphasis) */ .btn-tertiary { background-color: transparent; color: var(--color-primary); text-decoration: underline; } ``` ### Card Design ```css .card { /* Structure */ background-color: var(--color-surface); border-radius: var(--radius-lg); padding: var(--space-24); /* Depth */ box-shadow: var(--shadow-md); /* Interaction */ transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1), box-shadow 0.3s ease; } .card:hover { transform: scale(1.02); box-shadow: var(--shadow-xl); } /* Card Anatomy */ .card-header { margin-block-end: var(--space-16); } .card-title { font-size: var(--font-size-xl); font-weight: var(--font-weight-semibold); color: var(--color-text); } .card-content { font-size: var(--font-size-base); line-height: var(--line-height-relaxed); color: var(--color-text-secondary); } .card-footer { margin-block-start: var(--space-24); padding-block-start: var(--space-16); border-block-start: 1px solid var(--color-border); } ``` ### Form Input Design ```css .input { /* Size */ min-height: 48px; padding: 12px 16px; /* Typography */ font-size: var(--font-size-base); line-height: 1.5; /* Visual */ background-color: var(--color-background); border: 2px solid var(--color-border); border-radius: var(--radius-md); /* Interaction */ transition: all 0.2s ease; } .input:focus { outline: none; border-color: var(--color-primary); box-shadow: 0 0 0 4px rgba(0, 102, 204, 0.1); /* Focus ring */ } .input:invalid { border-color: var(--color-danger); } .input:disabled { background-color: var(--color-surface); color: var(--color-text-secondary); cursor: not-allowed; } /* Label */ .label { display: block; font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); color: var(--color-text); margin-block-end: var(--space-8); } /* Helper Text */ .help-text { font-size: var(--font-size-sm); color: var(--color-text-secondary); margin-block-start: var(--space-4); } /* Error Message */ .error-message { font-size: var(--font-size-sm); color: var(--color-danger); margin-block-start: var(--space-4); display: flex; align-items: center; gap: var(--space-4); } ``` --- ## Iconography ### Icon System Guidelines **Size Scale**: ``` 16px: Inline with text 20px: Buttons, inputs 24px: Navigation, cards 32px: Feature highlights 48px: Empty states, placeholders ``` **Style**: - **Stroke width**: 2px (consistent across set) - **Corner radius**: 2px (rounded, friendly) - **Grid**: 24×24px with 2px padding **Usage**: ```tsx import { MagnifyingGlass, User, XCircle } from '@phosphor-icons/react'; // Default size (24px) // Custom size // With color ``` **Accessibility**: ```tsx // Decorative icon (hidden from screen readers)