# UI Design Systems — Capture & Documentation Protocol

**Purpose:** Systematically capture, document, and reference external UI design systems for rapid project adoption.

**Applies to:** shadcn/ui, Radix, Tailwind UI, Material Design, Ant Design, Chakra, or any component library with documented tokens.

---

## When to Run This Skill

- Starting a new project and need to pick a design system
- Evaluating multiple variants of a system (shadcn base colors, etc.)
- Onboarding team to an existing design system
- Creating reference documentation for handoff
- Building a component library and need token documentation patterns

---

## Capture Protocol

### Step 1: Identify Variants

Most design systems have multiple variants accessible via URL parameters:

| System | URL Pattern | Variants |
|--------|-------------|----------|
| shadcn/ui | `?base=[color]` | base, stone, zinc, slate, gray |
| Tailwind UI | Color config | slate, gray, zinc, neutral, stone |
| Radix | Theme switching | Light/Dark + accent colors |

**Action:** List all variant URLs before capturing.

### Step 2: Systematic Screenshot + Token Extraction

For each variant:
1. Navigate to variant URL
2. Screenshot full page (visual reference)
3. Extract all CSS custom properties / tokens visible
4. Document: colors, typography, spacing, radius, shadows

**Key tokens to capture:**
```css
--background      /* Page background */
--foreground      /* Primary text */
--primary         /* Main action color */
--secondary       /* Supporting color */
--muted           /* Subtle backgrounds */
--accent          /* Highlights, hover states */
--border          /* Input/card borders */
--input           /* Form field borders */
--ring            /* Focus states */
--radius          /* Default border-radius */
```

### Step 3: Component Pattern Documentation

Document the 4 standard button variants:
```
Primary:   Solid fill, highest contrast
Secondary: Subtle fill, supporting action
Outline:   Border only, ghost appearance
Ghost:     Transparent, hover state only
```

Document spacing scale (if custom):
```
xs: 0.5rem (8px)
sm: 0.75rem (12px)
md: 1rem (16px)
lg: 1.5rem (24px)
xl: 2rem (32px)
```

---

## Documentation Format

### Required Structure

```markdown
# [System Name] — Design System Reference

## [Variant 1]: [Name]
**URL:** [Direct link]

### Visual Character
[2-3 words describing mood/aesthetic]

### Color Tokens
```css
--background: [HSL value]    /* [usage note] */
--foreground: [HSL value]    /* [usage note] */
...
```

### Typography
- **Heading:** [Font family]
- **Body:** [Font family]
- **Weights:** [400/500/600/700]

### Buttons
| Variant | Style |
|---------|-------|
| Primary | [description] |
...

---

## Quick Reference: Choosing a Variant

| Variant | Best For | Mood |
|---------|----------|------|
| [Name] | [Use case] | [Adjective] |
...

## Installation
```bash
[Exact command with flags]
```
```

---

## Color Token Standards

### HSL Format (Preferred)
```css
--token: H S% L%    /* Human-readable, animatable */
```

Example:
```css
--background: 0 0% 100%        /* Pure white */
--primary: 222 47% 11%         /* Dark slate blue */
```

### Hex Fallback
If system uses hex, document both:
```css
--primary: #0f172a        /* Dark slate */
/* HSL: 222 47% 11% */
```

### Chart/Data Colors
Always capture the 5-chart palette:
```css
--chart-1: [darkest]      /* Primary data */
--chart-2: [medium-dark]  /* Secondary */
--chart-3: [medium]       /* Tertiary */
--chart-4: [light]        /* Background lines */
--chart-5: [lightest]      /* Subtle fills */
```

---

## Decision Framework: Which Variant?

### For Content/Lifestyle Sites
→ **Warm variants** (stone, vega, neutral with warm undertones)
- High readability for long-form text
- Approachable, organic feel
- Good for: blogs, editorial, consumer apps

### For Tech/Developer Tools  
→ **Cool variants** (zinc, slate, gray)
- Professional, precise aesthetic
- Traditional "software" look
- Good for: dev tools, dashboards, B2B SaaS

### For Enterprise/B2B
→ **Slate or neutral**
- Conservative, trustworthy
- Matches existing corporate branding
- Good for: internal tools, admin panels

### For Modern Consumer Apps
→ **Nova or high-contrast neutrals**
- Clean, contemporary
- Maximum flexibility with accent colors
- Good for: startups, modern SaaS

---

## Output Location

Save to: `labnotes/skills/[system-name]-design-system/SKILL.md`

Example:
- `labnotes/skills/shadcn-design-system/SKILL.md`
- `labnotes/skills/radix-primitives/SKILL.md`

Commit with: `feat(skills): add [system] design system reference ([variants])`

---

## Integration with ByteRover

After capture, curate the patterns:

```bash
brv curate "[System] design system: [key pattern 1], [key pattern 2], [key pattern 3]"
```

Example:
```bash
brv curate "shadcn design system capture: URL-based variant navigation, HSL token documentation, quick-reference style selector"
```

---

## Related Skills

- `frontend-slides` — Presentation deck builder (uses captured tokens)
- `unslop` — Clean up documentation text
- `build-stream-writer` — Publish design system findings

---

## Example: Complete shadcn/ui Capture

See working example at: `labnotes/skills/shadcn-design-systems/SKILL.md`

This demonstrates the full protocol applied to 5 shadcn variants (Nova, Vega, Zinc, Slate, Stone) with:
- URL-based variant navigation
- Complete HSL token extraction
- Quick-reference style selector
- Installation command integration

---

## Quick Reference Card

| Task | Command/Pattern |
|------|-----------------|
| Capture shadcn variants | `?base=stone`, `?base=zinc`, etc. |
| Standard install | `npx shadcn@latest init --yes --template next --base-color [base]` |
| Document colors | HSL format with usage comments |
| Choose warm variant | stone, vega, warm-neutral |
| Choose cool variant | zinc, slate, cool-neutral |
| Create skill file | `labnotes/skills/[name]-design-system/SKILL.md` |

---

## Edge Case Handling & Prevention Guide

### 1. Color Contrast Failures

**The Problem:** Primary button text fails WCAG AA on certain backgrounds.

**Prevention:**
```css
/* Always verify contrast ratios */
/* Use: https://webaim.org/resources/contrastchecker/ */

/* Minimum ratios required:
   - Normal text: 4.5:1
   - Large text (18pt+): 3:1
   - UI components: 3:1
*/
```

**Quick Check:**
- Place primary button on both `--background` and `--muted` backgrounds
- If either fails, override `--primary-foreground` or adjust button shadow

**Edge Case:** "Primary on accent" — When primary buttons appear on colored cards:
```css
.card-accent .btn-primary {
  /* Force consistent appearance */
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  border: 2px solid hsl(var(--primary-foreground) / 0.1);
}
```

### 2. Typography Scale Breakdown

**The Problem:** Design system font sizes don't align with your content needs.

**Detection:**
- Heading hierarchy looks "off" (h1 too big/small vs body)
- Mobile headings overflow containers
- Long-form text feels cramped or too loose

**Prevention Strategy:**
```css
/* Document the system's base assumptions */
/* shadcn assumes: 1rem = 16px, body = 14-16px */

/* Before adopting, check your needs: */
/* Blog/CMS → Need larger body (16-18px) */
/* Dashboard → Smaller body (13-14px) acceptable */
/* Marketing → Flexible, emphasis on headlines */
```

**Override Protocol (when needed):**
```css
/* Never override individual elements */
/* Override the base scale instead */
:root {
  --font-size-base: 18px;  /* Adjust system-wide */
}

/* Or use CSS transform for one-off adjustments */
.headline-hero {
  font-size: calc(var(--font-size-4xl) * 1.2);
}
```

### 3. Spacing "Magic Numbers"

**The Problem:** Hardcoded values appear instead of token usage.

**Prevention:**
```css
/* ❌ Anti-pattern: */
.card { padding: 24px; }

/* ✅ System-compliant: */
.card { padding: var(--spacing-lg); /* 1.5rem = 24px */ }
```

**Edge Case: "In-between" spacing**
When design calls for 20px but system has 16px (`md`) and 24px (`lg`):
```css
/* Option 1: Use closest token (preferred) */
.card { padding: var(--spacing-lg); } /* 24px, slightly more airy */

/* Option 2: Compose tokens */
.card { padding: var(--spacing-md) var(--spacing-lg); } /* 16px 24px */

/* Option 3: Calculate from base (document the exception) */
.card-custom {
  /* 20px = 1.25rem. Document why this breaks the scale. */
  padding: 1.25rem;
}
```

### 4. Dark Mode Transition Issues

**The Problem:** Flickering, flash of wrong theme, or CSS variable conflicts.

**Prevention:**
```html
<!-- Always set theme before render -->
<script>
  // In <head>, before any CSS loads
  const theme = localStorage.getItem('theme') || 'light';
  document.documentElement.classList.add(theme);
</script>
```

**Edge Case: "System preference mismatch"**
```css
/* User wants light mode but OS is dark */
/* Respect explicit choice over system */

/* Override system detection when user has preference */
html[data-theme="light"] {
  color-scheme: light;
}

html[data-theme="dark"] {
  color-scheme: dark;
}
```

**Variable Collision Prevention:**
```css
/* Namespace your overrides */
:root {
  /* System variables - don't touch */
  --background: 0 0% 100%;
  
  /* Your extensions - prefixed */
  --app-sidebar-width: 280px;
  --app-header-height: 64px;
}
```

### 5. Component Override Traps

**The Problem:** "I'll just tweak this one button" → 47 overrides later, unmaintainable chaos.

**Decision Tree for Overrides:**

```
Need to change a component?
│
├─ Is this a global change? (all buttons everywhere)
│  └─ YES → Override the design system token
│     └─ Example: Change --primary for brand color
│
├─ Is this a variant need? (new button type)
│  └─ YES → Extend the system
│     └─ Create .btn-destructive, .btn-success
│
├─ Is this one-off? (single instance)
│  └─ YES → Use composition
│     └─ Wrap in .hero-section and style the wrapper
│
└─ Is this fixing a bug?
   └─ YES → Override locally, file issue upstream
```

**Prevention:** Always ask "Am I extending or hacking?"

### 6. Chart Color Accessibility

**The Problem:** `--chart-1` through `--chart-5` look distinct to you but indistinguishable to colorblind users.

**Prevention Strategy:**
```css
/* Always pair color with other visual encoding */
/* Pattern: color + pattern/texture + label */

.chart-bar {
  /* Never rely on color alone */
  border: 2px solid currentColor;
  background: linear-gradient(45deg, 
    currentColor 25%, 
    transparent 25%, 
    transparent 50%, 
    currentColor 50%
  );
}

/* Or use distinct patterns */
.chart-1 { fill: url(#pattern-dots); }
.chart-2 { fill: url(#pattern-lines); }
```

**Required Check:**
- Test with Deuteranopia simulator (most common colorblindness)
- Ensure 3:1 contrast between adjacent chart colors
- Add data labels (values visible without color interpretation)

### 7. Responsive Token Breakdown

**The Problem:** `--spacing-xl` is 32px on desktop but overwhelming on mobile.

**Prevention:**
```css
/* Fluid spacing scales */
:root {
  /* Fixed pixel values scale poorly */
  --spacing-xl: 32px;  /* Too big on phone, too small on 4K */
  
  /* Fluid units adapt */
  --spacing-xl: clamp(1.5rem, 4vw, 2.5rem);
  /* Min: 24px, Ideal: 4% viewport, Max: 40px */
}
```

**Edge Case: "Touch target minimums"**
```css
/* WCAG requires 44x44px minimum touch targets */
/* Design system may use smaller for visual density */

/* Prevention: Audit all interactive elements */
.btn-sm {
  /* System says 32px height */
  height: 32px;
  
  /* Your override for accessibility */
  min-height: 44px;
  min-width: 44px;
}
```

### 8. Font Loading Failures

**The Problem:** "Inter" flashes as Times New Roman while loading.

**Prevention:**
```css
/* Always specify system font stack as fallback */
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

/* Use font-display: swap for fast initial render */
@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter.woff2') format('woff2');
  font-display: swap;  /* Show fallback immediately, swap when loaded */
}
```

**Edge Case: "Font subset for performance"**
```css
/* If design system uses extended character sets (Cyrillic, etc.) */
/* But you only need Latin */

@font-face {
  font-family: 'Inter';
  src: url('/fonts/Inter-Latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F;
  /* Only loads for Latin characters - saves ~60KB */
}
```

### 9. CSS Variable Performance

**The Problem:** Hundreds of CSS variables cause jank on older devices.

**Prevention:**
```css
/* Consolidate related tokens */
/* ❌ Overly granular: */
--btn-padding-x: 1rem;
--btn-padding-y: 0.5rem;
--btn-font-size: 0.875rem;

/* ✅ Composed: */
--btn-base: 0.875rem 1rem 0.5rem;  /* size x y - parse with JS if needed */
```

**When to worry:**
- >200 CSS custom properties on a single page
- Animating CSS variables directly (use transform instead)
- Variables in hot paths (scrolling, mousemove)

### 10. Migration from Existing Systems

**The Problem:** Switching from Bootstrap/Material to new system causes visual regression chaos.

**Prevention Strategy:**

**Phase 1: Token Mapping (Week 1)**
```css
/* Create bridge file: design-system-bridge.css */
/* Map old classes to new tokens */

.btn-primary {  /* Bootstrap class */
  /* Map to new system */
  background: hsl(var(--primary));
  color: hsl(var(--primary-foreground));
  border-radius: var(--radius);
}
```

**Phase 2: Gradual Adoption (Weeks 2-4)**
- New pages use new system
- Old pages use bridge file
- Touch old pages only when editing for other reasons

**Phase 3: Cleanup (Week 5+)**
- Remove bridge file
- Verify no legacy classes remain (`grep -r "btn-primary" --include="*.html"`)

---

## Troubleshooting Quick Reference

| Symptom | Likely Cause | Fix |
|---------|--------------|-----|
| Flash of unstyled content | Theme script runs too late | Move to `<head>` |
| Colors look different in Figma vs browser | Color profile mismatch | Use sRGB hex values |
| Button text not centered | Line-height vs height mismatch | Use flex centering |
| Spacing feels "off" | Mixing rem and px | Standardize on rem |
| Charts unreadable in grayscale | Color-only encoding | Add patterns/textures |
| Mobile looks cramped | Desktop-first spacing tokens | Use clamp() for fluidity |
| Fonts flash/change after load | No fallback stack | Add system fonts |
| Override not applying | Specificity wars | Use higher specificity or !important (last resort) |
| Dark mode flickers | System preference race condition | Store preference, respect it |

---

## Accessibility Checklist

Before shipping any design system implementation:

- [ ] **Color Contrast:** All text meets WCAG AA (4.5:1 normal, 3:1 large)
- [ ] **Focus States:** `--ring` is visible on all interactive elements
- [ ] **Touch Targets:** Minimum 44x44px for buttons, links, inputs
- [ ] **Reduced Motion:** Honor `prefers-reduced-motion` for animations
- [ ] **Screen Readers:** Test with NVDA/VoiceOver (heading hierarchy, landmarks)
- [ ] **Keyboard Navigation:** Tab through entire flow without getting trapped
- [ ] **Colorblind Safety:** Charts/data use patterns/textures beyond color
- [ ] **Zoom Support:** 200% zoom doesn't break layout
- [ ] **Font Size:** 200% text size doesn't clip or overlap

---

## When to Override vs. Extend vs. Replace

### Override the Design System When:
- Fixing an accessibility bug (contrast, touch targets)
- Brand color doesn't match default primary
- Typography scale misaligned with content type

### Extend the Design System When:
- Need a new component variant (destructive button, success state)
- Adding app-specific tokens (sidebar width, header height)
- Creating composite components (search bar = input + button + icon)

### Replace the Design System When:
- More than 30% of components need overrides
- Performance requirements exceed system capabilities
- Design direction fundamentally incompatible (e.g., brutalism vs. minimalism)

**Decision Rule:** If you're fighting the system daily, it might be the wrong system.

---

**Maintained by:** PromptEngines Lab  
**Last updated:** March 23, 2026