refactor: move nested skills to root + add ui-ux-pro-max + ConsentOS
- Extract 9 nested skills from website-creator/ to root skills/ - Remove duplicate seo-analyzers, seo-geo, seo-multi-channel from website-creator - Add new ui-ux-pro-max skill with full UI/UX data - Update install-skills.sh to sync properly - Remove .DS_Store artifacts Moved skills: - api-and-interface-design - banner-design - brand - design-system - design - frontend-ui-engineering - slides - spec-driven-development - ui-styling
This commit is contained in:
236
skills/design-system/references/component-specs.md
Normal file
236
skills/design-system/references/component-specs.md
Normal file
@@ -0,0 +1,236 @@
|
||||
# Component Specifications
|
||||
|
||||
Detailed specs for core components with states and variants.
|
||||
|
||||
## Button
|
||||
|
||||
### Variants
|
||||
|
||||
| Variant | Background | Text | Border | Use Case |
|
||||
|---------|------------|------|--------|----------|
|
||||
| default | primary | white | none | Primary actions |
|
||||
| secondary | gray-100 | gray-900 | none | Secondary actions |
|
||||
| outline | transparent | foreground | border | Tertiary actions |
|
||||
| ghost | transparent | foreground | none | Subtle actions |
|
||||
| link | transparent | primary | none | Navigation |
|
||||
| destructive | red-600 | white | none | Dangerous actions |
|
||||
|
||||
### Sizes
|
||||
|
||||
| Size | Height | Padding X | Padding Y | Font Size | Icon Size |
|
||||
|------|--------|-----------|-----------|-----------|-----------|
|
||||
| sm | 32px | 12px | 6px | 14px | 16px |
|
||||
| default | 40px | 16px | 8px | 14px | 18px |
|
||||
| lg | 48px | 24px | 12px | 16px | 20px |
|
||||
| icon | 40px | 0 | 0 | - | 18px |
|
||||
|
||||
### States
|
||||
|
||||
| State | Background | Text | Opacity | Cursor |
|
||||
|-------|------------|------|---------|--------|
|
||||
| default | token | token | 1 | pointer |
|
||||
| hover | darker | token | 1 | pointer |
|
||||
| active | darkest | token | 1 | pointer |
|
||||
| focus | token | token | 1 | pointer |
|
||||
| disabled | muted | muted-fg | 0.5 | not-allowed |
|
||||
| loading | token | token | 0.7 | wait |
|
||||
|
||||
### Anatomy
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ [icon] Label Text [icon] │
|
||||
└─────────────────────────────────────┘
|
||||
↑ ↑
|
||||
leading icon trailing icon
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
### Variants
|
||||
|
||||
| Variant | Description |
|
||||
|---------|-------------|
|
||||
| default | Standard text input |
|
||||
| textarea | Multi-line text |
|
||||
| select | Dropdown selection |
|
||||
| checkbox | Boolean toggle |
|
||||
| radio | Single selection |
|
||||
| switch | Toggle switch |
|
||||
|
||||
### Sizes
|
||||
|
||||
| Size | Height | Padding | Font Size |
|
||||
|------|--------|---------|-----------|
|
||||
| sm | 32px | 8px 12px | 14px |
|
||||
| default | 40px | 8px 12px | 14px |
|
||||
| lg | 48px | 12px 16px | 16px |
|
||||
|
||||
### States
|
||||
|
||||
| State | Border | Background | Ring |
|
||||
|-------|--------|------------|------|
|
||||
| default | gray-300 | white | none |
|
||||
| hover | gray-400 | white | none |
|
||||
| focus | primary | white | primary/20% |
|
||||
| error | red-500 | white | red/20% |
|
||||
| disabled | gray-200 | gray-100 | none |
|
||||
|
||||
### Anatomy
|
||||
|
||||
```
|
||||
Label (optional)
|
||||
┌─────────────────────────────────────┐
|
||||
│ [icon] Placeholder/Value [action] │
|
||||
└─────────────────────────────────────┘
|
||||
Helper text or error message
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Card
|
||||
|
||||
### Variants
|
||||
|
||||
| Variant | Shadow | Border | Use Case |
|
||||
|---------|--------|--------|----------|
|
||||
| default | sm | 1px | Standard card |
|
||||
| elevated | lg | none | Prominent content |
|
||||
| outline | none | 1px | Subtle container |
|
||||
| interactive | sm→md | 1px | Clickable card |
|
||||
|
||||
### Anatomy
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ Card Header │
|
||||
│ Title │
|
||||
│ Description │
|
||||
├─────────────────────────────────────┤
|
||||
│ Card Content │
|
||||
│ Main content area │
|
||||
│ │
|
||||
├─────────────────────────────────────┤
|
||||
│ Card Footer │
|
||||
│ Actions │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Spacing
|
||||
|
||||
| Area | Padding |
|
||||
|------|---------|
|
||||
| header | 24px 24px 0 |
|
||||
| content | 24px |
|
||||
| footer | 0 24px 24px |
|
||||
| gap | 16px |
|
||||
|
||||
---
|
||||
|
||||
## Badge
|
||||
|
||||
### Variants
|
||||
|
||||
| Variant | Background | Text |
|
||||
|---------|------------|------|
|
||||
| default | primary | white |
|
||||
| secondary | gray-100 | gray-900 |
|
||||
| outline | transparent | foreground |
|
||||
| destructive | red-600 | white |
|
||||
| success | green-600 | white |
|
||||
| warning | yellow-500 | gray-900 |
|
||||
|
||||
### Sizes
|
||||
|
||||
| Size | Padding | Font Size | Height |
|
||||
|------|---------|-----------|--------|
|
||||
| sm | 4px 8px | 11px | 20px |
|
||||
| default | 4px 10px | 12px | 24px |
|
||||
| lg | 6px 12px | 14px | 28px |
|
||||
|
||||
---
|
||||
|
||||
## Alert
|
||||
|
||||
### Variants
|
||||
|
||||
| Variant | Icon | Background | Border |
|
||||
|---------|------|------------|--------|
|
||||
| default | info | gray-50 | gray-200 |
|
||||
| destructive | alert | red-50 | red-200 |
|
||||
| success | check | green-50 | green-200 |
|
||||
| warning | warning | yellow-50 | yellow-200 |
|
||||
|
||||
### Anatomy
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────┐
|
||||
│ [icon] Title [×]│
|
||||
│ Description text │
|
||||
└─────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dialog
|
||||
|
||||
### Sizes
|
||||
|
||||
| Size | Max Width | Use Case |
|
||||
|------|-----------|----------|
|
||||
| sm | 384px | Simple confirmations |
|
||||
| default | 512px | Standard dialogs |
|
||||
| lg | 640px | Complex forms |
|
||||
| xl | 768px | Data-heavy dialogs |
|
||||
| full | 100% - 32px | Full-screen on mobile |
|
||||
|
||||
### Anatomy
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────┐
|
||||
│ Dialog Header [×]│
|
||||
│ Title │
|
||||
│ Description │
|
||||
├───────────────────────────────────────┤
|
||||
│ Dialog Content │
|
||||
│ Scrollable if needed │
|
||||
│ │
|
||||
├───────────────────────────────────────┤
|
||||
│ Dialog Footer │
|
||||
│ [Cancel] [Confirm]│
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Table
|
||||
|
||||
### Row States
|
||||
|
||||
| State | Background | Use Case |
|
||||
|-------|------------|----------|
|
||||
| default | white | Normal row |
|
||||
| hover | gray-50 | Mouse over |
|
||||
| selected | primary/10% | Selected row |
|
||||
| striped | gray-50/white | Alternating |
|
||||
|
||||
### Cell Alignment
|
||||
|
||||
| Content Type | Alignment |
|
||||
|--------------|-----------|
|
||||
| Text | Left |
|
||||
| Numbers | Right |
|
||||
| Status/Badge | Center |
|
||||
| Actions | Right |
|
||||
|
||||
### Spacing
|
||||
|
||||
| Element | Value |
|
||||
|---------|-------|
|
||||
| cell padding | 12px 16px |
|
||||
| header padding | 12px 16px |
|
||||
| row height (compact) | 40px |
|
||||
| row height (default) | 48px |
|
||||
| row height (comfortable) | 56px |
|
||||
214
skills/design-system/references/component-tokens.md
Normal file
214
skills/design-system/references/component-tokens.md
Normal file
@@ -0,0 +1,214 @@
|
||||
# Component Tokens
|
||||
|
||||
Component-specific tokens referencing semantic layer.
|
||||
|
||||
## Button Tokens
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Default (Primary) */
|
||||
--button-bg: var(--color-primary);
|
||||
--button-fg: var(--color-primary-foreground);
|
||||
--button-hover-bg: var(--color-primary-hover);
|
||||
--button-active-bg: var(--color-primary-active);
|
||||
|
||||
/* Secondary */
|
||||
--button-secondary-bg: var(--color-secondary);
|
||||
--button-secondary-fg: var(--color-secondary-foreground);
|
||||
--button-secondary-hover-bg: var(--color-secondary-hover);
|
||||
|
||||
/* Outline */
|
||||
--button-outline-border: var(--color-border);
|
||||
--button-outline-fg: var(--color-foreground);
|
||||
--button-outline-hover-bg: var(--color-accent);
|
||||
|
||||
/* Ghost */
|
||||
--button-ghost-fg: var(--color-foreground);
|
||||
--button-ghost-hover-bg: var(--color-accent);
|
||||
|
||||
/* Destructive */
|
||||
--button-destructive-bg: var(--color-destructive);
|
||||
--button-destructive-fg: var(--color-destructive-foreground);
|
||||
--button-destructive-hover-bg: var(--color-destructive-hover);
|
||||
|
||||
/* Sizing */
|
||||
--button-padding-x: var(--space-4);
|
||||
--button-padding-y: var(--space-2);
|
||||
--button-padding-x-sm: var(--space-3);
|
||||
--button-padding-y-sm: var(--space-1-5);
|
||||
--button-padding-x-lg: var(--space-6);
|
||||
--button-padding-y-lg: var(--space-3);
|
||||
|
||||
/* Shape */
|
||||
--button-radius: var(--radius-md);
|
||||
--button-font-size: var(--font-size-sm);
|
||||
--button-font-weight: var(--font-weight-medium);
|
||||
}
|
||||
```
|
||||
|
||||
## Input Tokens
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Background & Border */
|
||||
--input-bg: var(--color-background);
|
||||
--input-border: var(--color-input);
|
||||
--input-fg: var(--color-foreground);
|
||||
|
||||
/* Placeholder */
|
||||
--input-placeholder: var(--color-muted-foreground);
|
||||
|
||||
/* Focus */
|
||||
--input-focus-border: var(--color-ring);
|
||||
--input-focus-ring: var(--color-ring);
|
||||
|
||||
/* Error */
|
||||
--input-error-border: var(--color-error);
|
||||
--input-error-fg: var(--color-error);
|
||||
|
||||
/* Disabled */
|
||||
--input-disabled-bg: var(--color-muted);
|
||||
--input-disabled-fg: var(--color-muted-foreground);
|
||||
|
||||
/* Sizing */
|
||||
--input-padding-x: var(--space-3);
|
||||
--input-padding-y: var(--space-2);
|
||||
--input-radius: var(--radius-md);
|
||||
--input-font-size: var(--font-size-sm);
|
||||
}
|
||||
```
|
||||
|
||||
## Card Tokens
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Background & Border */
|
||||
--card-bg: var(--color-card);
|
||||
--card-fg: var(--color-card-foreground);
|
||||
--card-border: var(--color-border);
|
||||
|
||||
/* Shadow */
|
||||
--card-shadow: var(--shadow-default);
|
||||
--card-shadow-hover: var(--shadow-md);
|
||||
|
||||
/* Spacing */
|
||||
--card-padding: var(--space-6);
|
||||
--card-padding-sm: var(--space-4);
|
||||
--card-gap: var(--space-4);
|
||||
|
||||
/* Shape */
|
||||
--card-radius: var(--radius-lg);
|
||||
}
|
||||
```
|
||||
|
||||
## Badge Tokens
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Default */
|
||||
--badge-bg: var(--color-primary);
|
||||
--badge-fg: var(--color-primary-foreground);
|
||||
|
||||
/* Secondary */
|
||||
--badge-secondary-bg: var(--color-secondary);
|
||||
--badge-secondary-fg: var(--color-secondary-foreground);
|
||||
|
||||
/* Outline */
|
||||
--badge-outline-border: var(--color-border);
|
||||
--badge-outline-fg: var(--color-foreground);
|
||||
|
||||
/* Destructive */
|
||||
--badge-destructive-bg: var(--color-destructive);
|
||||
--badge-destructive-fg: var(--color-destructive-foreground);
|
||||
|
||||
/* Sizing */
|
||||
--badge-padding-x: var(--space-2-5);
|
||||
--badge-padding-y: var(--space-0-5);
|
||||
--badge-radius: var(--radius-full);
|
||||
--badge-font-size: var(--font-size-xs);
|
||||
}
|
||||
```
|
||||
|
||||
## Alert Tokens
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Default */
|
||||
--alert-bg: var(--color-background);
|
||||
--alert-fg: var(--color-foreground);
|
||||
--alert-border: var(--color-border);
|
||||
|
||||
/* Destructive */
|
||||
--alert-destructive-bg: var(--color-destructive);
|
||||
--alert-destructive-fg: var(--color-destructive-foreground);
|
||||
|
||||
/* Spacing */
|
||||
--alert-padding: var(--space-4);
|
||||
--alert-radius: var(--radius-lg);
|
||||
}
|
||||
```
|
||||
|
||||
## Dialog/Modal Tokens
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Overlay */
|
||||
--dialog-overlay-bg: rgb(0 0 0 / 0.5);
|
||||
|
||||
/* Content */
|
||||
--dialog-bg: var(--color-background);
|
||||
--dialog-fg: var(--color-foreground);
|
||||
--dialog-border: var(--color-border);
|
||||
--dialog-shadow: var(--shadow-lg);
|
||||
|
||||
/* Spacing */
|
||||
--dialog-padding: var(--space-6);
|
||||
--dialog-radius: var(--radius-lg);
|
||||
--dialog-max-width: 32rem;
|
||||
}
|
||||
```
|
||||
|
||||
## Table Tokens
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Header */
|
||||
--table-header-bg: var(--color-muted);
|
||||
--table-header-fg: var(--color-muted-foreground);
|
||||
|
||||
/* Body */
|
||||
--table-row-bg: var(--color-background);
|
||||
--table-row-hover-bg: var(--color-muted);
|
||||
--table-row-fg: var(--color-foreground);
|
||||
|
||||
/* Border */
|
||||
--table-border: var(--color-border);
|
||||
|
||||
/* Spacing */
|
||||
--table-cell-padding-x: var(--space-4);
|
||||
--table-cell-padding-y: var(--space-3);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage Example
|
||||
|
||||
```css
|
||||
.button {
|
||||
background: var(--button-bg);
|
||||
color: var(--button-fg);
|
||||
padding: var(--button-padding-y) var(--button-padding-x);
|
||||
border-radius: var(--button-radius);
|
||||
font-size: var(--button-font-size);
|
||||
font-weight: var(--button-font-weight);
|
||||
transition: background var(--duration-fast);
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background: var(--button-hover-bg);
|
||||
}
|
||||
|
||||
.button.secondary {
|
||||
background: var(--button-secondary-bg);
|
||||
color: var(--button-secondary-fg);
|
||||
}
|
||||
```
|
||||
203
skills/design-system/references/primitive-tokens.md
Normal file
203
skills/design-system/references/primitive-tokens.md
Normal file
@@ -0,0 +1,203 @@
|
||||
# Primitive Tokens
|
||||
|
||||
Raw design values - foundation of the design system.
|
||||
|
||||
## Color Scales
|
||||
|
||||
### Gray Scale
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-gray-50: #F9FAFB;
|
||||
--color-gray-100: #F3F4F6;
|
||||
--color-gray-200: #E5E7EB;
|
||||
--color-gray-300: #D1D5DB;
|
||||
--color-gray-400: #9CA3AF;
|
||||
--color-gray-500: #6B7280;
|
||||
--color-gray-600: #4B5563;
|
||||
--color-gray-700: #374151;
|
||||
--color-gray-800: #1F2937;
|
||||
--color-gray-900: #111827;
|
||||
--color-gray-950: #030712;
|
||||
}
|
||||
```
|
||||
|
||||
### Primary Colors (Blue)
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-blue-50: #EFF6FF;
|
||||
--color-blue-100: #DBEAFE;
|
||||
--color-blue-200: #BFDBFE;
|
||||
--color-blue-300: #93C5FD;
|
||||
--color-blue-400: #60A5FA;
|
||||
--color-blue-500: #3B82F6;
|
||||
--color-blue-600: #2563EB;
|
||||
--color-blue-700: #1D4ED8;
|
||||
--color-blue-800: #1E40AF;
|
||||
--color-blue-900: #1E3A8A;
|
||||
}
|
||||
```
|
||||
|
||||
### Status Colors
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Success - Green */
|
||||
--color-green-500: #22C55E;
|
||||
--color-green-600: #16A34A;
|
||||
|
||||
/* Warning - Yellow */
|
||||
--color-yellow-500: #EAB308;
|
||||
--color-yellow-600: #CA8A04;
|
||||
|
||||
/* Error - Red */
|
||||
--color-red-500: #EF4444;
|
||||
--color-red-600: #DC2626;
|
||||
|
||||
/* Info - Blue */
|
||||
--color-info: var(--color-blue-500);
|
||||
}
|
||||
```
|
||||
|
||||
## Spacing Scale
|
||||
|
||||
4px base unit system.
|
||||
|
||||
```css
|
||||
:root {
|
||||
--space-0: 0;
|
||||
--space-px: 1px;
|
||||
--space-0-5: 0.125rem; /* 2px */
|
||||
--space-1: 0.25rem; /* 4px */
|
||||
--space-1-5: 0.375rem; /* 6px */
|
||||
--space-2: 0.5rem; /* 8px */
|
||||
--space-2-5: 0.625rem; /* 10px */
|
||||
--space-3: 0.75rem; /* 12px */
|
||||
--space-3-5: 0.875rem; /* 14px */
|
||||
--space-4: 1rem; /* 16px */
|
||||
--space-5: 1.25rem; /* 20px */
|
||||
--space-6: 1.5rem; /* 24px */
|
||||
--space-7: 1.75rem; /* 28px */
|
||||
--space-8: 2rem; /* 32px */
|
||||
--space-9: 2.25rem; /* 36px */
|
||||
--space-10: 2.5rem; /* 40px */
|
||||
--space-12: 3rem; /* 48px */
|
||||
--space-14: 3.5rem; /* 56px */
|
||||
--space-16: 4rem; /* 64px */
|
||||
--space-20: 5rem; /* 80px */
|
||||
--space-24: 6rem; /* 96px */
|
||||
}
|
||||
```
|
||||
|
||||
## Typography Scale
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Font Sizes */
|
||||
--font-size-xs: 0.75rem; /* 12px */
|
||||
--font-size-sm: 0.875rem; /* 14px */
|
||||
--font-size-base: 1rem; /* 16px */
|
||||
--font-size-lg: 1.125rem; /* 18px */
|
||||
--font-size-xl: 1.25rem; /* 20px */
|
||||
--font-size-2xl: 1.5rem; /* 24px */
|
||||
--font-size-3xl: 1.875rem; /* 30px */
|
||||
--font-size-4xl: 2.25rem; /* 36px */
|
||||
--font-size-5xl: 3rem; /* 48px */
|
||||
|
||||
/* Line Heights */
|
||||
--leading-none: 1;
|
||||
--leading-tight: 1.25;
|
||||
--leading-snug: 1.375;
|
||||
--leading-normal: 1.5;
|
||||
--leading-relaxed: 1.625;
|
||||
--leading-loose: 2;
|
||||
|
||||
/* Font Weights */
|
||||
--font-weight-normal: 400;
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
|
||||
/* Letter Spacing */
|
||||
--tracking-tighter: -0.05em;
|
||||
--tracking-tight: -0.025em;
|
||||
--tracking-normal: 0;
|
||||
--tracking-wide: 0.025em;
|
||||
--tracking-wider: 0.05em;
|
||||
}
|
||||
```
|
||||
|
||||
## Border Radius
|
||||
|
||||
```css
|
||||
:root {
|
||||
--radius-none: 0;
|
||||
--radius-sm: 0.125rem; /* 2px */
|
||||
--radius-default: 0.25rem; /* 4px */
|
||||
--radius-md: 0.375rem; /* 6px */
|
||||
--radius-lg: 0.5rem; /* 8px */
|
||||
--radius-xl: 0.75rem; /* 12px */
|
||||
--radius-2xl: 1rem; /* 16px */
|
||||
--radius-3xl: 1.5rem; /* 24px */
|
||||
--radius-full: 9999px;
|
||||
}
|
||||
```
|
||||
|
||||
## Shadows
|
||||
|
||||
```css
|
||||
:root {
|
||||
--shadow-none: none;
|
||||
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
||||
--shadow-default: 0 1px 3px 0 rgb(0 0 0 / 0.1),
|
||||
0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1),
|
||||
0 2px 4px -2px rgb(0 0 0 / 0.1);
|
||||
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1),
|
||||
0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1),
|
||||
0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
||||
--shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05);
|
||||
}
|
||||
```
|
||||
|
||||
## Motion / Duration
|
||||
|
||||
```css
|
||||
:root {
|
||||
--duration-75: 75ms;
|
||||
--duration-100: 100ms;
|
||||
--duration-150: 150ms;
|
||||
--duration-200: 200ms;
|
||||
--duration-300: 300ms;
|
||||
--duration-500: 500ms;
|
||||
--duration-700: 700ms;
|
||||
--duration-1000: 1000ms;
|
||||
|
||||
/* Semantic durations */
|
||||
--duration-fast: var(--duration-150);
|
||||
--duration-normal: var(--duration-200);
|
||||
--duration-slow: var(--duration-300);
|
||||
}
|
||||
```
|
||||
|
||||
## Z-Index Scale
|
||||
|
||||
```css
|
||||
:root {
|
||||
--z-auto: auto;
|
||||
--z-0: 0;
|
||||
--z-10: 10;
|
||||
--z-20: 20;
|
||||
--z-30: 30;
|
||||
--z-40: 40;
|
||||
--z-50: 50;
|
||||
--z-dropdown: 1000;
|
||||
--z-sticky: 1100;
|
||||
--z-modal: 1200;
|
||||
--z-popover: 1300;
|
||||
--z-tooltip: 1400;
|
||||
}
|
||||
```
|
||||
215
skills/design-system/references/semantic-tokens.md
Normal file
215
skills/design-system/references/semantic-tokens.md
Normal file
@@ -0,0 +1,215 @@
|
||||
# Semantic Tokens
|
||||
|
||||
Purpose-based aliases referencing primitive tokens.
|
||||
|
||||
## Color Semantics
|
||||
|
||||
### Background & Foreground
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Page background */
|
||||
--color-background: var(--color-gray-50);
|
||||
--color-foreground: var(--color-gray-900);
|
||||
|
||||
/* Card/surface background */
|
||||
--color-card: white;
|
||||
--color-card-foreground: var(--color-gray-900);
|
||||
|
||||
/* Popover/dropdown */
|
||||
--color-popover: white;
|
||||
--color-popover-foreground: var(--color-gray-900);
|
||||
}
|
||||
```
|
||||
|
||||
### Primary
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-primary: var(--color-blue-600);
|
||||
--color-primary-hover: var(--color-blue-700);
|
||||
--color-primary-active: var(--color-blue-800);
|
||||
--color-primary-foreground: white;
|
||||
}
|
||||
```
|
||||
|
||||
### Secondary
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-secondary: var(--color-gray-100);
|
||||
--color-secondary-hover: var(--color-gray-200);
|
||||
--color-secondary-foreground: var(--color-gray-900);
|
||||
}
|
||||
```
|
||||
|
||||
### Muted
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-muted: var(--color-gray-100);
|
||||
--color-muted-foreground: var(--color-gray-500);
|
||||
}
|
||||
```
|
||||
|
||||
### Accent
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-accent: var(--color-gray-100);
|
||||
--color-accent-foreground: var(--color-gray-900);
|
||||
}
|
||||
```
|
||||
|
||||
### Destructive
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-destructive: var(--color-red-600);
|
||||
--color-destructive-hover: var(--color-red-700);
|
||||
--color-destructive-foreground: white;
|
||||
}
|
||||
```
|
||||
|
||||
### Status Colors
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-success: var(--color-green-600);
|
||||
--color-success-foreground: white;
|
||||
|
||||
--color-warning: var(--color-yellow-500);
|
||||
--color-warning-foreground: var(--color-gray-900);
|
||||
|
||||
--color-error: var(--color-red-600);
|
||||
--color-error-foreground: white;
|
||||
|
||||
--color-info: var(--color-blue-500);
|
||||
--color-info-foreground: white;
|
||||
}
|
||||
```
|
||||
|
||||
### Border & Ring
|
||||
|
||||
```css
|
||||
:root {
|
||||
--color-border: var(--color-gray-200);
|
||||
--color-input: var(--color-gray-200);
|
||||
--color-ring: var(--color-blue-500);
|
||||
}
|
||||
```
|
||||
|
||||
## Spacing Semantics
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Component internal spacing */
|
||||
--spacing-component-xs: var(--space-1);
|
||||
--spacing-component-sm: var(--space-2);
|
||||
--spacing-component: var(--space-3);
|
||||
--spacing-component-lg: var(--space-4);
|
||||
|
||||
/* Section spacing */
|
||||
--spacing-section-sm: var(--space-8);
|
||||
--spacing-section: var(--space-12);
|
||||
--spacing-section-lg: var(--space-16);
|
||||
|
||||
/* Page margins */
|
||||
--spacing-page-x: var(--space-4);
|
||||
--spacing-page-y: var(--space-6);
|
||||
}
|
||||
```
|
||||
|
||||
## Typography Semantics
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Headings */
|
||||
--font-heading: var(--font-size-2xl);
|
||||
--font-heading-lg: var(--font-size-3xl);
|
||||
--font-heading-xl: var(--font-size-4xl);
|
||||
|
||||
/* Body */
|
||||
--font-body: var(--font-size-base);
|
||||
--font-body-sm: var(--font-size-sm);
|
||||
--font-body-lg: var(--font-size-lg);
|
||||
|
||||
/* Labels & Captions */
|
||||
--font-label: var(--font-size-sm);
|
||||
--font-caption: var(--font-size-xs);
|
||||
}
|
||||
```
|
||||
|
||||
## Interactive States
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Focus ring */
|
||||
--ring-width: 2px;
|
||||
--ring-offset: 2px;
|
||||
--ring-color: var(--color-ring);
|
||||
|
||||
/* Opacity for disabled */
|
||||
--opacity-disabled: 0.5;
|
||||
|
||||
/* Transitions */
|
||||
--transition-colors: color, background-color, border-color;
|
||||
--transition-transform: transform;
|
||||
--transition-all: all;
|
||||
}
|
||||
```
|
||||
|
||||
## Dark Mode Overrides
|
||||
|
||||
```css
|
||||
.dark {
|
||||
--color-background: var(--color-gray-950);
|
||||
--color-foreground: var(--color-gray-50);
|
||||
|
||||
--color-card: var(--color-gray-900);
|
||||
--color-card-foreground: var(--color-gray-50);
|
||||
|
||||
--color-popover: var(--color-gray-900);
|
||||
--color-popover-foreground: var(--color-gray-50);
|
||||
|
||||
--color-muted: var(--color-gray-800);
|
||||
--color-muted-foreground: var(--color-gray-400);
|
||||
|
||||
--color-secondary: var(--color-gray-800);
|
||||
--color-secondary-foreground: var(--color-gray-50);
|
||||
|
||||
--color-accent: var(--color-gray-800);
|
||||
--color-accent-foreground: var(--color-gray-50);
|
||||
|
||||
--color-border: var(--color-gray-800);
|
||||
--color-input: var(--color-gray-800);
|
||||
}
|
||||
```
|
||||
|
||||
## Usage Patterns
|
||||
|
||||
### Applying Semantic Tokens
|
||||
|
||||
```css
|
||||
/* Good - uses semantic tokens */
|
||||
.card {
|
||||
background: var(--color-card);
|
||||
color: var(--color-card-foreground);
|
||||
border: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
/* Bad - uses primitive tokens directly */
|
||||
.card {
|
||||
background: var(--color-gray-50);
|
||||
color: var(--color-gray-900);
|
||||
}
|
||||
```
|
||||
|
||||
### Theme Switching
|
||||
|
||||
Semantic tokens enable instant theme switching:
|
||||
|
||||
```js
|
||||
// Toggle dark mode
|
||||
document.documentElement.classList.toggle('dark');
|
||||
```
|
||||
241
skills/design-system/references/states-and-variants.md
Normal file
241
skills/design-system/references/states-and-variants.md
Normal file
@@ -0,0 +1,241 @@
|
||||
# States and Variants
|
||||
|
||||
Component state definitions and variant patterns.
|
||||
|
||||
## Interactive States
|
||||
|
||||
### State Definitions
|
||||
|
||||
| State | Trigger | Visual Change |
|
||||
|-------|---------|---------------|
|
||||
| default | None | Base appearance |
|
||||
| hover | Mouse over | Slight color shift |
|
||||
| focus | Tab/click | Focus ring |
|
||||
| active | Mouse down | Darkest color |
|
||||
| disabled | disabled attr | Reduced opacity |
|
||||
| loading | Async action | Spinner + opacity |
|
||||
|
||||
### State Priority
|
||||
|
||||
When multiple states apply, priority (highest to lowest):
|
||||
|
||||
1. disabled
|
||||
2. loading
|
||||
3. active
|
||||
4. focus
|
||||
5. hover
|
||||
6. default
|
||||
|
||||
### State Transitions
|
||||
|
||||
```css
|
||||
/* Standard transition for interactive elements */
|
||||
.interactive {
|
||||
transition-property: color, background-color, border-color, box-shadow;
|
||||
transition-duration: var(--duration-fast);
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
```
|
||||
|
||||
| Transition | Duration | Easing |
|
||||
|------------|----------|--------|
|
||||
| Color changes | 150ms | ease-in-out |
|
||||
| Background | 150ms | ease-in-out |
|
||||
| Transform | 200ms | ease-out |
|
||||
| Opacity | 150ms | ease |
|
||||
| Shadow | 200ms | ease-out |
|
||||
|
||||
## Focus States
|
||||
|
||||
### Focus Ring Spec
|
||||
|
||||
```css
|
||||
/* Standard focus ring */
|
||||
.focusable:focus-visible {
|
||||
outline: none;
|
||||
box-shadow: 0 0 0 var(--ring-offset) var(--color-background),
|
||||
0 0 0 calc(var(--ring-offset) + var(--ring-width)) var(--ring-color);
|
||||
}
|
||||
```
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| Ring width | 2px |
|
||||
| Ring offset | 2px |
|
||||
| Ring color | primary (blue-500) |
|
||||
| Offset color | background |
|
||||
|
||||
### Focus Within
|
||||
|
||||
```css
|
||||
/* Container focus when child is focused */
|
||||
.container:focus-within {
|
||||
border-color: var(--color-ring);
|
||||
}
|
||||
```
|
||||
|
||||
## Disabled States
|
||||
|
||||
### Visual Treatment
|
||||
|
||||
```css
|
||||
.disabled {
|
||||
opacity: var(--opacity-disabled); /* 0.5 */
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
```
|
||||
|
||||
| Property | Disabled Value |
|
||||
|----------|----------------|
|
||||
| Opacity | 50% |
|
||||
| Pointer events | none |
|
||||
| Cursor | not-allowed |
|
||||
| Background | muted |
|
||||
| Color | muted-foreground |
|
||||
|
||||
### Accessibility
|
||||
|
||||
- Use `aria-disabled="true"` for semantic disabled
|
||||
- Use `disabled` attribute for form elements
|
||||
- Maintain sufficient contrast (3:1 minimum)
|
||||
|
||||
## Loading States
|
||||
|
||||
### Spinner Placement
|
||||
|
||||
| Component | Spinner Position |
|
||||
|-----------|------------------|
|
||||
| Button | Replace icon or center |
|
||||
| Input | Trailing position |
|
||||
| Card | Center overlay |
|
||||
| Page | Center of viewport |
|
||||
|
||||
### Loading Treatment
|
||||
|
||||
```css
|
||||
.loading {
|
||||
position: relative;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.loading::after {
|
||||
content: '';
|
||||
/* spinner styles */
|
||||
}
|
||||
|
||||
.loading > * {
|
||||
opacity: 0.7;
|
||||
}
|
||||
```
|
||||
|
||||
## Error States
|
||||
|
||||
### Visual Indicators
|
||||
|
||||
```css
|
||||
.error {
|
||||
border-color: var(--color-error);
|
||||
color: var(--color-error);
|
||||
}
|
||||
|
||||
.error:focus-visible {
|
||||
box-shadow: 0 0 0 2px var(--color-background),
|
||||
0 0 0 4px var(--color-error);
|
||||
}
|
||||
```
|
||||
|
||||
| Element | Error Treatment |
|
||||
|---------|-----------------|
|
||||
| Input border | red-500 |
|
||||
| Input focus ring | red/20% |
|
||||
| Helper text | red-600 |
|
||||
| Icon | red-500 |
|
||||
|
||||
### Error Messages
|
||||
|
||||
- Position below input
|
||||
- Use error color
|
||||
- Include icon for accessibility
|
||||
- Clear on valid input
|
||||
|
||||
## Variant Patterns
|
||||
|
||||
### Color Variants
|
||||
|
||||
```css
|
||||
/* Pattern for color variants */
|
||||
.component {
|
||||
--component-bg: var(--color-primary);
|
||||
--component-fg: var(--color-primary-foreground);
|
||||
background: var(--component-bg);
|
||||
color: var(--component-fg);
|
||||
}
|
||||
|
||||
.component.secondary {
|
||||
--component-bg: var(--color-secondary);
|
||||
--component-fg: var(--color-secondary-foreground);
|
||||
}
|
||||
|
||||
.component.destructive {
|
||||
--component-bg: var(--color-destructive);
|
||||
--component-fg: var(--color-destructive-foreground);
|
||||
}
|
||||
```
|
||||
|
||||
### Size Variants
|
||||
|
||||
```css
|
||||
/* Pattern for size variants */
|
||||
.component {
|
||||
--component-height: 40px;
|
||||
--component-padding: var(--space-4);
|
||||
--component-font: var(--font-size-sm);
|
||||
}
|
||||
|
||||
.component.sm {
|
||||
--component-height: 32px;
|
||||
--component-padding: var(--space-3);
|
||||
--component-font: var(--font-size-xs);
|
||||
}
|
||||
|
||||
.component.lg {
|
||||
--component-height: 48px;
|
||||
--component-padding: var(--space-6);
|
||||
--component-font: var(--font-size-base);
|
||||
}
|
||||
```
|
||||
|
||||
## Accessibility Requirements
|
||||
|
||||
### Color Contrast
|
||||
|
||||
| Element | Minimum Ratio |
|
||||
|---------|---------------|
|
||||
| Normal text | 4.5:1 |
|
||||
| Large text (18px+) | 3:1 |
|
||||
| UI components | 3:1 |
|
||||
| Focus indicator | 3:1 |
|
||||
|
||||
### State Indicators
|
||||
|
||||
- Never rely on color alone
|
||||
- Use icons, text, or patterns
|
||||
- Ensure focus is visible
|
||||
- Provide loading announcements
|
||||
|
||||
### ARIA States
|
||||
|
||||
```html
|
||||
<!-- Disabled -->
|
||||
<button disabled aria-disabled="true">Submit</button>
|
||||
|
||||
<!-- Loading -->
|
||||
<button aria-busy="true" aria-describedby="loading-text">
|
||||
<span id="loading-text" class="sr-only">Loading...</span>
|
||||
</button>
|
||||
|
||||
<!-- Error -->
|
||||
<input aria-invalid="true" aria-describedby="error-msg">
|
||||
<span id="error-msg" role="alert">Error message</span>
|
||||
```
|
||||
251
skills/design-system/references/tailwind-integration.md
Normal file
251
skills/design-system/references/tailwind-integration.md
Normal file
@@ -0,0 +1,251 @@
|
||||
# Tailwind Integration
|
||||
|
||||
Map design system tokens to Tailwind CSS configuration.
|
||||
|
||||
## CSS Variables Setup
|
||||
|
||||
### Base Layer
|
||||
|
||||
```css
|
||||
/* globals.css */
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
/* Primitives */
|
||||
--color-blue-600: 37 99 235; /* HSL: 217 91% 60% */
|
||||
|
||||
/* Semantic */
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222 47% 11%;
|
||||
--primary: 217 91% 60%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
--secondary: 220 14% 96%;
|
||||
--secondary-foreground: 222 47% 11%;
|
||||
--muted: 220 14% 96%;
|
||||
--muted-foreground: 220 9% 46%;
|
||||
--accent: 220 14% 96%;
|
||||
--accent-foreground: 222 47% 11%;
|
||||
--destructive: 0 84% 60%;
|
||||
--destructive-foreground: 0 0% 100%;
|
||||
--border: 220 13% 91%;
|
||||
--input: 220 13% 91%;
|
||||
--ring: 217 91% 60%;
|
||||
--radius: 0.5rem;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: 222 47% 4%;
|
||||
--foreground: 210 40% 98%;
|
||||
--primary: 217 91% 60%;
|
||||
--primary-foreground: 0 0% 100%;
|
||||
--secondary: 217 33% 17%;
|
||||
--secondary-foreground: 210 40% 98%;
|
||||
--muted: 217 33% 17%;
|
||||
--muted-foreground: 215 20% 65%;
|
||||
--accent: 217 33% 17%;
|
||||
--accent-foreground: 210 40% 98%;
|
||||
--destructive: 0 62% 30%;
|
||||
--destructive-foreground: 0 0% 100%;
|
||||
--border: 217 33% 17%;
|
||||
--input: 217 33% 17%;
|
||||
--ring: 217 91% 60%;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Tailwind Config
|
||||
|
||||
### tailwind.config.ts
|
||||
|
||||
```typescript
|
||||
import type { Config } from 'tailwindcss'
|
||||
|
||||
const config: Config = {
|
||||
darkMode: ['class'],
|
||||
content: ['./src/**/*.{ts,tsx}'],
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
background: 'hsl(var(--background))',
|
||||
foreground: 'hsl(var(--foreground))',
|
||||
primary: {
|
||||
DEFAULT: 'hsl(var(--primary))',
|
||||
foreground: 'hsl(var(--primary-foreground))',
|
||||
},
|
||||
secondary: {
|
||||
DEFAULT: 'hsl(var(--secondary))',
|
||||
foreground: 'hsl(var(--secondary-foreground))',
|
||||
},
|
||||
muted: {
|
||||
DEFAULT: 'hsl(var(--muted))',
|
||||
foreground: 'hsl(var(--muted-foreground))',
|
||||
},
|
||||
accent: {
|
||||
DEFAULT: 'hsl(var(--accent))',
|
||||
foreground: 'hsl(var(--accent-foreground))',
|
||||
},
|
||||
destructive: {
|
||||
DEFAULT: 'hsl(var(--destructive))',
|
||||
foreground: 'hsl(var(--destructive-foreground))',
|
||||
},
|
||||
border: 'hsl(var(--border))',
|
||||
input: 'hsl(var(--input))',
|
||||
ring: 'hsl(var(--ring))',
|
||||
card: {
|
||||
DEFAULT: 'hsl(var(--card))',
|
||||
foreground: 'hsl(var(--card-foreground))',
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: 'var(--radius)',
|
||||
md: 'calc(var(--radius) - 2px)',
|
||||
sm: 'calc(var(--radius) - 4px)',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
export default config
|
||||
```
|
||||
|
||||
## HSL Format Benefits
|
||||
|
||||
Using HSL without function allows opacity modifiers:
|
||||
|
||||
```tsx
|
||||
// With HSL format (space-separated)
|
||||
<div className="bg-primary/50"> // 50% opacity
|
||||
<div className="text-primary/80"> // 80% opacity
|
||||
|
||||
// CSS output
|
||||
background-color: hsl(217 91% 60% / 0.5);
|
||||
```
|
||||
|
||||
## Component Classes
|
||||
|
||||
### Button Example
|
||||
|
||||
```css
|
||||
@layer components {
|
||||
.btn {
|
||||
@apply inline-flex items-center justify-center
|
||||
rounded-md font-medium
|
||||
transition-colors
|
||||
focus-visible:outline-none focus-visible:ring-2
|
||||
focus-visible:ring-ring focus-visible:ring-offset-2
|
||||
disabled:pointer-events-none disabled:opacity-50;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
@apply bg-primary text-primary-foreground
|
||||
hover:bg-primary/90;
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
@apply bg-secondary text-secondary-foreground
|
||||
hover:bg-secondary/80;
|
||||
}
|
||||
|
||||
.btn-outline {
|
||||
@apply border border-input bg-background
|
||||
hover:bg-accent hover:text-accent-foreground;
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
@apply hover:bg-accent hover:text-accent-foreground;
|
||||
}
|
||||
|
||||
.btn-destructive {
|
||||
@apply bg-destructive text-destructive-foreground
|
||||
hover:bg-destructive/90;
|
||||
}
|
||||
|
||||
/* Sizes */
|
||||
.btn-sm { @apply h-8 px-3 text-xs; }
|
||||
.btn-md { @apply h-10 px-4 text-sm; }
|
||||
.btn-lg { @apply h-12 px-6 text-base; }
|
||||
}
|
||||
```
|
||||
|
||||
## Spacing Integration
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
theme: {
|
||||
extend: {
|
||||
spacing: {
|
||||
// Map to CSS variables if needed
|
||||
'section': 'var(--spacing-section)',
|
||||
'component': 'var(--spacing-component)',
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Animation Tokens
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
theme: {
|
||||
extend: {
|
||||
transitionDuration: {
|
||||
fast: '150ms',
|
||||
normal: '200ms',
|
||||
slow: '300ms',
|
||||
},
|
||||
keyframes: {
|
||||
'accordion-down': {
|
||||
from: { height: '0' },
|
||||
to: { height: 'var(--radix-accordion-content-height)' },
|
||||
},
|
||||
'accordion-up': {
|
||||
from: { height: 'var(--radix-accordion-content-height)' },
|
||||
to: { height: '0' },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
'accordion-down': 'accordion-down 0.2s ease-out',
|
||||
'accordion-up': 'accordion-up 0.2s ease-out',
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Dark Mode Toggle
|
||||
|
||||
```typescript
|
||||
// Toggle dark mode
|
||||
function toggleDarkMode() {
|
||||
document.documentElement.classList.toggle('dark')
|
||||
}
|
||||
|
||||
// System preference
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
document.documentElement.classList.add('dark')
|
||||
}
|
||||
```
|
||||
|
||||
## shadcn/ui Alignment
|
||||
|
||||
This configuration aligns with shadcn/ui conventions:
|
||||
|
||||
- Same CSS variable naming
|
||||
- Same HSL format
|
||||
- Same color scale structure
|
||||
- Compatible with `npx shadcn@latest add` commands
|
||||
|
||||
### Using with shadcn/ui
|
||||
|
||||
```bash
|
||||
# Initialize (uses same token structure)
|
||||
npx shadcn@latest init
|
||||
|
||||
# Add components (styled with these tokens)
|
||||
npx shadcn@latest add button card input
|
||||
```
|
||||
|
||||
Components will automatically use your design system tokens.
|
||||
224
skills/design-system/references/token-architecture.md
Normal file
224
skills/design-system/references/token-architecture.md
Normal file
@@ -0,0 +1,224 @@
|
||||
# Token Architecture
|
||||
|
||||
Three-layer token system for scalable, themeable design systems.
|
||||
|
||||
## Layer Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Component Tokens │ Per-component overrides
|
||||
│ --button-bg, --card-padding │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Semantic Tokens │ Purpose-based aliases
|
||||
│ --color-primary, --spacing-section │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Primitive Tokens │ Raw design values
|
||||
│ --color-blue-600, --space-4 │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Why Three Layers?
|
||||
|
||||
| Layer | Purpose | When to Change |
|
||||
|-------|---------|----------------|
|
||||
| Primitive | Base values (colors, sizes) | Rarely - foundational |
|
||||
| Semantic | Meaning assignment | Theme switching |
|
||||
| Component | Component customization | Per-component needs |
|
||||
|
||||
## Layer 1: Primitive Tokens
|
||||
|
||||
Raw design values without semantic meaning.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Colors */
|
||||
--color-gray-50: #F9FAFB;
|
||||
--color-gray-900: #111827;
|
||||
--color-blue-500: #3B82F6;
|
||||
--color-blue-600: #2563EB;
|
||||
|
||||
/* Spacing (4px base) */
|
||||
--space-1: 0.25rem; /* 4px */
|
||||
--space-2: 0.5rem; /* 8px */
|
||||
--space-4: 1rem; /* 16px */
|
||||
--space-6: 1.5rem; /* 24px */
|
||||
|
||||
/* Typography */
|
||||
--font-size-sm: 0.875rem;
|
||||
--font-size-base: 1rem;
|
||||
--font-size-lg: 1.125rem;
|
||||
|
||||
/* Radius */
|
||||
--radius-sm: 0.25rem;
|
||||
--radius-default: 0.5rem;
|
||||
--radius-lg: 0.75rem;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05);
|
||||
--shadow-default: 0 1px 3px rgb(0 0 0 / 0.1);
|
||||
}
|
||||
```
|
||||
|
||||
## Layer 2: Semantic Tokens
|
||||
|
||||
Purpose-based aliases that reference primitives.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Background */
|
||||
--color-background: var(--color-gray-50);
|
||||
--color-foreground: var(--color-gray-900);
|
||||
|
||||
/* Primary */
|
||||
--color-primary: var(--color-blue-600);
|
||||
--color-primary-hover: var(--color-blue-700);
|
||||
|
||||
/* Secondary */
|
||||
--color-secondary: var(--color-gray-100);
|
||||
--color-secondary-foreground: var(--color-gray-900);
|
||||
|
||||
/* Muted */
|
||||
--color-muted: var(--color-gray-100);
|
||||
--color-muted-foreground: var(--color-gray-500);
|
||||
|
||||
/* Destructive */
|
||||
--color-destructive: var(--color-red-600);
|
||||
--color-destructive-foreground: white;
|
||||
|
||||
/* Spacing */
|
||||
--spacing-component: var(--space-4);
|
||||
--spacing-section: var(--space-6);
|
||||
}
|
||||
```
|
||||
|
||||
## Layer 3: Component Tokens
|
||||
|
||||
Component-specific tokens referencing semantic layer.
|
||||
|
||||
```css
|
||||
:root {
|
||||
/* Button */
|
||||
--button-bg: var(--color-primary);
|
||||
--button-fg: white;
|
||||
--button-hover-bg: var(--color-primary-hover);
|
||||
--button-padding-x: var(--space-4);
|
||||
--button-padding-y: var(--space-2);
|
||||
--button-radius: var(--radius-default);
|
||||
|
||||
/* Input */
|
||||
--input-bg: var(--color-background);
|
||||
--input-border: var(--color-gray-300);
|
||||
--input-focus-ring: var(--color-primary);
|
||||
--input-padding: var(--space-2) var(--space-3);
|
||||
|
||||
/* Card */
|
||||
--card-bg: var(--color-background);
|
||||
--card-border: var(--color-gray-200);
|
||||
--card-padding: var(--space-4);
|
||||
--card-radius: var(--radius-lg);
|
||||
--card-shadow: var(--shadow-default);
|
||||
}
|
||||
```
|
||||
|
||||
## Dark Mode
|
||||
|
||||
Override semantic tokens for dark theme:
|
||||
|
||||
```css
|
||||
.dark {
|
||||
--color-background: var(--color-gray-900);
|
||||
--color-foreground: var(--color-gray-50);
|
||||
--color-muted: var(--color-gray-800);
|
||||
--color-muted-foreground: var(--color-gray-400);
|
||||
--color-secondary: var(--color-gray-800);
|
||||
}
|
||||
```
|
||||
|
||||
## Naming Convention
|
||||
|
||||
```
|
||||
--{category}-{item}-{variant}-{state}
|
||||
|
||||
Examples:
|
||||
--color-primary # category-item
|
||||
--color-primary-hover # category-item-state
|
||||
--button-bg-hover # component-property-state
|
||||
--space-section-sm # category-semantic-variant
|
||||
```
|
||||
|
||||
## Categories
|
||||
|
||||
| Category | Examples |
|
||||
|----------|----------|
|
||||
| color | primary, secondary, muted, destructive |
|
||||
| space | 1, 2, 4, 8, section, component |
|
||||
| font-size | xs, sm, base, lg, xl |
|
||||
| radius | sm, default, lg, full |
|
||||
| shadow | sm, default, lg |
|
||||
| duration | fast, normal, slow |
|
||||
|
||||
## File Organization
|
||||
|
||||
```
|
||||
tokens/
|
||||
├── primitives.css # Raw values
|
||||
├── semantic.css # Purpose aliases
|
||||
├── components.css # Component tokens
|
||||
└── index.css # Imports all
|
||||
```
|
||||
|
||||
Or single file with layer comments:
|
||||
|
||||
```css
|
||||
/* === PRIMITIVES === */
|
||||
:root { ... }
|
||||
|
||||
/* === SEMANTIC === */
|
||||
:root { ... }
|
||||
|
||||
/* === COMPONENTS === */
|
||||
:root { ... }
|
||||
|
||||
/* === DARK MODE === */
|
||||
.dark { ... }
|
||||
```
|
||||
|
||||
## Migration from Flat Tokens
|
||||
|
||||
Before (flat):
|
||||
```css
|
||||
--button-primary-bg: #2563EB;
|
||||
--button-secondary-bg: #F3F4F6;
|
||||
```
|
||||
|
||||
After (three-layer):
|
||||
```css
|
||||
/* Primitive */
|
||||
--color-blue-600: #2563EB;
|
||||
--color-gray-100: #F3F4F6;
|
||||
|
||||
/* Semantic */
|
||||
--color-primary: var(--color-blue-600);
|
||||
--color-secondary: var(--color-gray-100);
|
||||
|
||||
/* Component */
|
||||
--button-bg: var(--color-primary);
|
||||
--button-secondary-bg: var(--color-secondary);
|
||||
```
|
||||
|
||||
## W3C DTCG Alignment
|
||||
|
||||
Token JSON format (W3C Design Tokens Community Group):
|
||||
|
||||
```json
|
||||
{
|
||||
"color": {
|
||||
"blue": {
|
||||
"600": {
|
||||
"$value": "#2563EB",
|
||||
"$type": "color"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user