Files
gh-shaunrfox-okshaun-claude…/skills/panda-token-architecture.md
2025-11-30 08:56:16 +08:00

694 lines
16 KiB
Markdown

---
name: panda-token-architecture
description: Design token systems, semantic tokens, theme structures, and responsive design tokens following best practices
---
# Panda CSS Token Architecture
## When to Use This Skill
Use this skill when:
- Designing a design system's token architecture
- Organizing color palettes, spacing, typography, and other design tokens
- Setting up theme switching (light/dark modes)
- Creating semantic token layers for intent-based naming
- Establishing responsive design token patterns
For implementing these tokens in recipes or components, use **panda-recipe-patterns** or **panda-component-impl** skills.
## Token Architecture Principles
### Two-Layer Token System
**Layer 1: Base Tokens** - Raw design values
- Color palettes with numeric scales
- Sizing and spacing scales
- Typography scales
- Static values that rarely change
**Layer 2: Semantic Tokens** - Context-aware aliases
- Theme-dependent (light/dark mode)
- Intent-based naming (success, error, brand)
- References to base tokens
- Changes based on context/theme
**Why**: Separation enables theme switching without redefining entire palettes.
## Base Tokens
Create: `src/styles/tokens.ts`
### Color Palettes
**Pattern**: Use numeric scales (0-100 or 1-90) for lightness/darkness:
```typescript
import { defineTokens } from '@pandacss/dev'
export const tokens = defineTokens({
colors: {
// Grayscale: 0 = lightest, 100 = darkest
slate: {
0: { value: '#FFFFFF' },
5: { value: '#F8F9FA' },
10: { value: '#F1F3F5' },
20: { value: '#E9ECEF' },
30: { value: '#DEE2E6' },
40: { value: '#CED4DA' },
50: { value: '#ADB5BD' },
60: { value: '#868E96' },
70: { value: '#495057' },
80: { value: '#343A40' },
90: { value: '#212529' },
100: { value: '#000000' }
},
// Brand colors with tints/shades
blue: {
5: { value: '#E7F5FF' },
10: { value: '#D0EBFF' },
20: { value: '#A5D8FF' },
30: { value: '#74C0FC' },
40: { value: '#4DABF7' },
50: { value: '#339AF0' }, // Base brand blue
60: { value: '#228BE6' },
70: { value: '#1C7ED6' },
80: { value: '#1971C2' },
90: { value: '#1864AB' }
},
// Semantic palette colors
green: { /* success shades */ },
red: { /* error shades */ },
yellow: { /* warning shades */ },
cyan: { /* info shades */ }
}
})
```
**Naming Convention**:
- 0-100 scale: 0 = lightest, 100 = darkest
- Or 1-90 scale: 1 = lightest, 90 = darkest
- Choose one convention and stick to it
### Spacing & Sizing
**Pattern**: Unified scale for both spacing and sizing:
```typescript
const sizes = {
// Utility sizes
0: { value: '0' },
auto: { value: 'auto' },
full: { value: '100%' },
min: { value: 'min-content' },
max: { value: 'max-content' },
fit: { value: 'fit-content' },
prose: { value: '65ch' },
// Numeric scale in rem (16px base)
1: { value: '0.0625rem' }, // 1px
2: { value: '0.125rem' }, // 2px
4: { value: '0.25rem' }, // 4px
6: { value: '0.375rem' }, // 6px
8: { value: '0.5rem' }, // 8px
12: { value: '0.75rem' }, // 12px
16: { value: '1rem' }, // 16px
20: { value: '1.25rem' }, // 20px
24: { value: '1.5rem' }, // 24px
32: { value: '2rem' }, // 32px
40: { value: '2.5rem' }, // 40px
48: { value: '3rem' }, // 48px
64: { value: '4rem' }, // 64px
80: { value: '5rem' }, // 80px
96: { value: '6rem' }, // 96px
// ... extend as needed
}
export const tokens = defineTokens({
sizes,
spacing: sizes // Reuse same scale for spacing
})
```
**Why**: Unified scale ensures consistency between width/height and padding/margin.
### Container Sizes
**Pattern**: Named breakpoint containers:
```typescript
export const tokens = defineTokens({
sizes: {
// ... numeric sizes above ...
// Named container sizes
'2xs': { value: '16rem' }, // 256px
xs: { value: '20rem' }, // 320px
sm: { value: '24rem' }, // 384px
md: { value: '28rem' }, // 448px
lg: { value: '32rem' }, // 512px
xl: { value: '36rem' }, // 576px
'2xl': { value: '42rem' }, // 672px
'3xl': { value: '48rem' }, // 768px
'4xl': { value: '56rem' }, // 896px
'5xl': { value: '64rem' }, // 1024px
'6xl': { value: '72rem' }, // 1152px
'7xl': { value: '80rem' }, // 1280px
'8xl': { value: '90rem' } // 1440px
}
})
```
### Typography
**Pattern**: Separate font families, weights, sizes, and line heights:
```typescript
export const tokens = defineTokens({
fonts: {
body: { value: 'Inter, -apple-system, sans-serif' },
heading: { value: 'Inter, -apple-system, sans-serif' },
mono: { value: 'JetBrains Mono, Consolas, monospace' }
},
fontWeights: {
thin: { value: '100' },
light: { value: '300' },
normal: { value: '400' },
medium: { value: '500' },
semibold: { value: '600' },
bold: { value: '700' },
extrabold: { value: '800' }
},
fontSizes: {
'2xs': { value: '0.625rem' }, // 10px
xs: { value: '0.75rem' }, // 12px
sm: { value: '0.875rem' }, // 14px
md: { value: '1rem' }, // 16px
lg: { value: '1.125rem' }, // 18px
xl: { value: '1.25rem' }, // 20px
'2xl': { value: '1.5rem' }, // 24px
'3xl': { value: '1.875rem' }, // 30px
'4xl': { value: '2.25rem' }, // 36px
'5xl': { value: '3rem' }, // 48px
'6xl': { value: '3.75rem' }, // 60px
'7xl': { value: '4.5rem' } // 72px
},
lineHeights: {
none: { value: '1' },
tight: { value: '1.25' },
snug: { value: '1.375' },
normal: { value: '1.5' },
relaxed: { value: '1.625' },
loose: { value: '2' }
}
})
```
### Other Design Tokens
```typescript
export const tokens = defineTokens({
radii: {
none: { value: '0' },
sm: { value: '0.125rem' }, // 2px
base: { value: '0.25rem' }, // 4px
md: { value: '0.375rem' }, // 6px
lg: { value: '0.5rem' }, // 8px
xl: { value: '0.75rem' }, // 12px
'2xl': { value: '1rem' }, // 16px
full: { value: '9999px' }
},
shadows: {
xs: { value: '0 1px 2px 0 rgb(0 0 0 / 0.05)' },
sm: { value: '0 1px 3px 0 rgb(0 0 0 / 0.1)' },
md: { value: '0 4px 6px -1px rgb(0 0 0 / 0.1)' },
lg: { value: '0 10px 15px -3px rgb(0 0 0 / 0.1)' },
xl: { value: '0 20px 25px -5px rgb(0 0 0 / 0.1)' },
inner: { value: 'inset 0 2px 4px 0 rgb(0 0 0 / 0.05)' }
},
easings: {
default: { value: 'cubic-bezier(0.4, 0, 0.2, 1)' },
linear: { value: 'linear' },
in: { value: 'cubic-bezier(0.4, 0, 1, 1)' },
out: { value: 'cubic-bezier(0, 0, 0.2, 1)' },
inOut: { value: 'cubic-bezier(0.4, 0, 0.2, 1)' }
},
durations: {
fast: { value: '150ms' },
normal: { value: '250ms' },
slow: { value: '350ms' },
slower: { value: '500ms' }
}
})
```
## Semantic Tokens
Create: `src/styles/semanticTokens.ts`
### Purpose
Semantic tokens provide:
- Theme-aware values (light/dark mode)
- Intent-based naming (success, error, warning)
- Contextual meaning (background, foreground, border)
- Easier token updates without touching components
### Pattern: Theme-Aware Colors
```typescript
import { defineSemanticTokens } from '@pandacss/dev'
export const semanticTokens = defineSemanticTokens({
colors: {
// Background colors
bg: {
canvas: {
value: { base: '{colors.slate.0}', _dark: '{colors.slate.90}' }
},
surface: {
value: { base: '{colors.slate.5}', _dark: '{colors.slate.80}' }
},
overlay: {
value: { base: '{colors.slate.10}', _dark: '{colors.slate.70}' }
}
},
// Foreground/text colors
fg: {
default: {
value: { base: '{colors.slate.90}', _dark: '{colors.slate.10}' }
},
muted: {
value: { base: '{colors.slate.60}', _dark: '{colors.slate.40}' }
},
subtle: {
value: { base: '{colors.slate.50}', _dark: '{colors.slate.50}' }
}
},
// Border colors
border: {
default: {
value: { base: '{colors.slate.20}', _dark: '{colors.slate.70}' }
},
muted: {
value: { base: '{colors.slate.10}', _dark: '{colors.slate.80}' }
}
},
// Intent-based colors
success: {
default: {
value: { base: '{colors.green.40}', _dark: '{colors.green.30}' }
},
emphasis: {
value: { base: '{colors.green.50}', _dark: '{colors.green.40}' }
},
muted: {
value: { base: '{colors.green.10}', _dark: '{colors.green.80}' }
}
},
error: {
default: {
value: { base: '{colors.red.40}', _dark: '{colors.red.30}' }
},
emphasis: {
value: { base: '{colors.red.50}', _dark: '{colors.red.40}' }
},
muted: {
value: { base: '{colors.red.10}', _dark: '{colors.red.80}' }
}
},
warning: {
default: {
value: { base: '{colors.yellow.40}', _dark: '{colors.yellow.30}' }
},
emphasis: {
value: { base: '{colors.yellow.50}', _dark: '{colors.yellow.40}' }
},
muted: {
value: { base: '{colors.yellow.10}', _dark: '{colors.yellow.80}' }
}
},
// Brand colors
brand: {
default: {
value: { base: '{colors.blue.50}', _dark: '{colors.blue.40}' }
},
emphasis: {
value: { base: '{colors.blue.60}', _dark: '{colors.blue.30}' }
},
muted: {
value: { base: '{colors.blue.10}', _dark: '{colors.blue.80}' }
}
}
}
})
```
### Token Reference Syntax
Reference base tokens using `{category.name.shade}`:
```typescript
value: { base: '{colors.blue.50}', _dark: '{colors.blue.40}' }
// ^-- Reference to base token
```
**Why**: References enable token changes to cascade through semantic layer.
### Nesting Semantic Tokens
Create hierarchies for better organization:
```typescript
export const semanticTokens = defineSemanticTokens({
colors: {
button: {
primary: {
bg: {
value: { base: '{colors.brand.default}', _dark: '{colors.brand.default}' }
},
fg: {
value: { base: '{colors.slate.0}', _dark: '{colors.slate.0}' }
},
border: {
value: { base: '{colors.brand.emphasis}', _dark: '{colors.brand.emphasis}' }
}
},
secondary: {
bg: {
value: { base: '{colors.bg.surface}', _dark: '{colors.bg.surface}' }
},
fg: {
value: { base: '{colors.fg.default}', _dark: '{colors.fg.default}' }
}
}
}
}
})
```
Usage in recipes:
```typescript
bg: 'button.primary.bg',
color: 'button.primary.fg',
borderColor: 'button.primary.border'
```
## Text Styles
**Pattern**: Define complete typography presets:
```typescript
import { defineTextStyles } from '@pandacss/dev'
export const textStyles = defineTextStyles({
// Display text
display: {
lg: {
value: {
fontSize: '5xl',
fontWeight: 'bold',
lineHeight: 'tight',
letterSpacing: '-0.02em'
}
},
md: {
value: {
fontSize: '4xl',
fontWeight: 'bold',
lineHeight: 'tight'
}
}
},
// Headings
heading: {
lg: {
value: {
fontSize: '3xl',
fontWeight: 'semibold',
lineHeight: 'tight'
}
},
md: {
value: {
fontSize: '2xl',
fontWeight: 'semibold',
lineHeight: 'snug'
}
},
sm: {
value: {
fontSize: 'xl',
fontWeight: 'semibold',
lineHeight: 'snug'
}
}
},
// Body text
body: {
lg: {
value: {
fontSize: 'lg',
fontWeight: 'normal',
lineHeight: 'normal'
}
},
md: {
value: {
fontSize: 'md',
fontWeight: 'normal',
lineHeight: 'normal'
}
},
sm: {
value: {
fontSize: 'sm',
fontWeight: 'normal',
lineHeight: 'normal'
}
}
}
})
```
Usage:
```typescript
// In recipes or components
textStyle: 'heading.lg'
textStyle: 'body.md'
```
## Responsive Token Patterns
### Breakpoint Tokens
Define in config (not as tokens):
```typescript
// In panda.config.ts
export default defineConfig({
theme: {
extend: {
breakpoints: {
sm: '640px',
md: '768px',
lg: '1024px',
xl: '1280px',
'2xl': '1536px'
}
}
}
})
```
Usage with responsive object syntax:
```typescript
fontSize: { base: 'sm', md: 'md', lg: 'lg' }
px: { base: '16', md: '20', lg: '24' }
```
### Container Query Tokens
For component-based responsive design:
```typescript
// In panda.config.ts
export default defineConfig({
theme: {
extend: {
containerSizes: {
sm: '384px',
md: '448px',
lg: '512px',
xl: '576px'
}
}
}
})
```
## Integration with panda.config.ts
Import and extend theme:
```typescript
import { defineConfig } from '@pandacss/dev'
import { tokens } from './src/styles/tokens'
import { semanticTokens } from './src/styles/semanticTokens'
import { textStyles } from './src/styles/textStyles'
export default defineConfig({
// ... other config ...
theme: {
extend: {
tokens,
semanticTokens,
textStyles
}
}
})
```
## Best Practices Checklist
Create TodoWrite items when organizing tokens:
- [ ] Separate base tokens from semantic tokens (different files)
- [ ] Use consistent numeric scales (0-100 or 1-90, pick one)
- [ ] Create semantic tokens for all theme-dependent values
- [ ] Use intent-based naming (success, error, warning, not green, red, yellow)
- [ ] Unify spacing and sizing scales
- [ ] Define text styles for common typography patterns
- [ ] Reference base tokens in semantic tokens (don't duplicate values)
- [ ] Document token purpose and usage in comments
- [ ] Test tokens in both light and dark themes
- [ ] Validate strictTokens mode catches hard-coded values
## Common Pitfalls
### Avoid: Duplicating Values
```typescript
// BAD: Duplicates color value
semanticTokens: {
colors: {
success: {
value: { base: '#22C55E', _dark: '#4ADE80' }
}
}
}
// GOOD: References base token
semanticTokens: {
colors: {
success: {
value: { base: '{colors.green.40}', _dark: '{colors.green.30}' }
}
}
}
```
### Avoid: Too Many Token Layers
Keep it simple: Base → Semantic → Components (2-3 layers max)
```typescript
// BAD: Too many indirection levels
semantic alias component variant state
// GOOD: Clear, direct references
base semantic component
```
### Avoid: Mixing Concerns
```typescript
// BAD: Mixing spacing into colors
tokens: {
colors: {
buttonPadding: { value: '12px' } // Wrong category!
}
}
// GOOD: Correct categorization
tokens: {
spacing: {
buttonPadding: { value: '12' }
}
}
```
## Accessing Official Panda CSS Docs
For token-specific documentation:
1. **Resolve library ID**: `mcp__MCP_DOCKER__resolve-library-id` with `libraryName: "panda-css"`
2. **Fetch docs**: `mcp__MCP_DOCKER__get-library-docs` with `topic: "tokens"` or `topic: "semantic-tokens"`
## Next Steps
After organizing tokens:
1. **Create recipes**: Use **panda-recipe-patterns** skill to build component styles
2. **Implement components**: Use **panda-component-impl** skill for React components
3. **Validate design system**: Ensure all components use tokens (strictTokens catches violations)
## Working Examples
Reference these files in the `examples/` directory for production-tested token patterns:
**Base Tokens (Primitives):**
- `examples/tokens.ts`
- - Color scales (10-100) for all hues
```typescript
lime: {
"10": { value: "#EFFFD6" },
"50": { value: "#82B536" },
"100": { value: "#28311B" }
}
```
- - Unified spacing/sizing numeric scale
- - Font families, sizes, weights, line heights
- - Durations, easings, keyframes
- - Borders, radii, opacity, aspect ratios
**Semantic Tokens:**
- `examples/semanticTokens.ts`
- - Theme-aware color system
```typescript
background: {
accent: {
blue: {
bolder: {
value: { base: "{colors.blue.70}", _dark: "{colors.blue.40}" }
}
}
}
}
```
- - Shadow and depth tokens
- - Semantic utility tokens
**Preset Integration:**
- `examples/preset.ts` - Complete preset showing how to integrate primitives and semantics using `definePreset`, `defineTokens`, and `defineSemanticTokens`
- `examples/textStyles.ts` - Typography presets combining font tokens