Design System Validator Skill
This skill enforces design system consistency by validating CSS variable usage, responsive design patterns, and accessibility standards.
When to Activate
Activate this skill when:
- Creating a new component
- Reviewing component code
- Mapping Figma designs to code
- Validating color usage
- Checking responsive patterns
- Ensuring accessibility compliance
Validation Rules
1. CSS Variable Enforcement
Rule: NEVER use hardcoded color values
Prohibited patterns:
// ❌ WRONG - Hardcoded hex colors
className="bg-[#343E55] text-[#FFFFFF]"
// ❌ WRONG - Hardcoded RGB/HSL
className="bg-[rgb(52,62,85)] text-[hsl(0,0%,100%)]"
// ❌ WRONG - Hardcoded named colors
className="bg-white text-black"
// ❌ WRONG - Hardcoded Tailwind colors
className="bg-gray-50 text-gray-900"Required patterns:
// ✅ CORRECT - Semantic CSS variables
className="bg-primary text-primary-foreground"
className="bg-semantic-bg-primary text-semantic-text-primary"
className="border-semantic-border-layout"2. CSS Variable Mapping
Map all colors to appropriate semantic tokens:
Core Tokens (from shadcn/ui)
| Color Context | CSS Variable | Tailwind Class | Usage |
|---|---|---|---|
| Backgrounds | |||
| Page background | --background | bg-background | Main page background |
| Foreground text | --foreground | text-foreground | Primary text on background |
| Card background | --card | bg-card | Raised surfaces |
| Card text | --card-foreground | text-card-foreground | Text on cards |
| Popover background | --popover | bg-popover | Floating elements |
| Popover text | --popover-foreground | text-popover-foreground | Text on popovers |
| Actions | |||
| Primary background | --primary | bg-primary | Primary buttons |
| Primary text | --primary-foreground | text-primary-foreground | Text on primary |
| Secondary background | --secondary | bg-secondary | Secondary buttons |
| Secondary text | --secondary-foreground | text-secondary-foreground | Text on secondary |
| Muted background | --muted | bg-muted | Disabled states |
| Muted text | --muted-foreground | text-muted-foreground | Muted/disabled text |
| Accent background | --accent | bg-accent | Accent highlights |
| Accent text | --accent-foreground | text-accent-foreground | Text on accent |
| Destructive background | --destructive | bg-destructive | Error/delete actions |
| Destructive text | --destructive-foreground | text-destructive-foreground | Text on destructive |
| Borders & Inputs | |||
| Border color | --border | border-border | Standard borders |
| Input border | --input | border-input | Input field borders |
| Ring color | --ring | ring-ring | Focus rings |
Semantic Tokens (myOperator-specific)
| Context | CSS Variable | Tailwind Class | Usage |
|---|---|---|---|
| Backgrounds | |||
| Primary | --semantic-bg-primary | bg-semantic-bg-primary | Component backgrounds |
| Secondary | --semantic-bg-secondary | bg-semantic-bg-secondary | Alternative backgrounds |
| Subtle | --semantic-bg-subtle | bg-semantic-bg-subtle | Hover/selected states |
| Text | |||
| Primary | --semantic-text-primary | text-semantic-text-primary | Main text content |
| Secondary | --semantic-text-secondary | text-semantic-text-secondary | Supporting text |
| Muted | --semantic-text-muted | text-semantic-text-muted | Disabled/placeholder |
| Link | --semantic-text-link | text-semantic-text-link | Interactive links |
| Borders | |||
| Layout | --semantic-border-layout | border-semantic-border-layout | Container borders |
| Input | --semantic-border-input | border-semantic-border-input | Form field borders |
| Focus | --semantic-border-focus | border-semantic-border-focus | Focus indicators |
| States | |||
| Error primary | --semantic-error-primary | text-semantic-error-primary | Error messages |
| Error subtle | --semantic-error-subtle | bg-semantic-error-subtle | Error backgrounds |
| Success primary | --semantic-success-primary | text-semantic-success-primary | Success messages |
| Success subtle | --semantic-success-subtle | bg-semantic-success-subtle | Success backgrounds |
| Warning primary | --semantic-warning-primary | text-semantic-warning-primary | Warning messages |
| Warning subtle | --semantic-warning-subtle | bg-semantic-warning-subtle | Warning backgrounds |
| Info | |||
| Info primary | --semantic-info-primary | text-semantic-info-primary | Informational messages |
| Info subtle | --semantic-info-subtle | bg-semantic-info-subtle | Informational backgrounds |
3. Color Mapping from Figma
When extracting colors from Figma, map them to semantic tokens:
Mapping algorithm:
- Identify color purpose from context:
- Button background → bg-primary or bg-secondary - Text color → text-foreground, text-primary-foreground, or semantic text token - Border → border-border, border-input, or semantic border token - Background → bg-background, bg-card, or semantic bg token
- Match to existing tokens by usage pattern:
Figma: #343E55 (dark blue) → Used for primary button Mapping: bg-primary (primary action color) Figma: #F3F4F6 (light gray) → Used for disabled state Mapping: bg-muted (disabled/inactive state) Figma: #EF4444 (red) → Used for error text Mapping: text-destructive or text-semantic-error-primary
2b. Verify token existence via codebase grep (MANDATORY):
- Before using any CSS variable token, search
src/index.cssfor the actual variable definition - This prevents using tokens that don't exist or have different names than expected
# Verify a semantic token exists
grep "--semantic-success-primary" src/index.css
# If not found, search for alternatives
grep "success" src/index.css- Common pitfalls:
- Figma may use naming like "success/primary" but the CSS variable may be --semantic-success-primary or just --success - Info-level tokens (blue/informational) may use --semantic-info-primary — always verify - Some tokens exist in :root (light) but not [data-theme="dark"] (dark) — check both
- If a required token doesn't exist, document it and use the closest available token
- Document custom mappings: If a color doesn't match existing tokens, document it:
// Note: Figma uses #4275D6 for links // Mapped to: text-semantic-text-link className="text-semantic-text-link"
4. Responsive Design Validation
Rule: Components must be mobile-first and responsive
Required patterns:
// ✅ CORRECT - Mobile-first responsive padding
className="px-4 py-2 sm:px-6 sm:py-3 lg:px-8 lg:py-4"
// ✅ CORRECT - Responsive text sizes
className="text-sm md:text-base lg:text-lg"
// ✅ CORRECT - Responsive layout
className="flex flex-col sm:flex-row gap-2 sm:gap-4"
// ✅ CORRECT - Responsive visibility
className="hidden md:block"Breakpoint reference:
sm: 640px - Small tabletsmd: 768px - Tabletslg: 1024px - Laptopsxl: 1280px - Desktops2xl: 1536px - Large desktops
Validation checklist:
- Padding scales responsively
- Text sizes adjust for readability
- Layout adapts for small screens
- Touch targets are at least 44px on mobile
- Horizontal scrolling is avoided
5. Typography Validation
Rule: Use semantic typography tokens
// ✅ CORRECT - Semantic font sizes
className="text-sm" // 14px - Small text, captions
className="text-base" // 16px - Default body text
className="text-lg" // 18px - Large body text
className="text-xl" // 20px - Headings
className="text-2xl" // 24px - Section headers
// ✅ CORRECT - Font weights
className="font-normal" // 400 - Body text
className="font-medium" // 500 - Emphasized text
className="font-semibold" // 600 - Headings
className="font-bold" // 700 - Strong emphasis
// ✅ CORRECT - Line heights
className="leading-none" // 1 - Tight spacing
className="leading-tight" // 1.25 - Headings
className="leading-normal" // 1.5 - Body text
className="leading-relaxed" // 1.625 - Comfortable reading
// ✅ CORRECT - Letter spacing
className="tracking-tight" // -0.025em
className="tracking-normal" // 0em
className="tracking-wide" // 0.025emTypography table format for Storybook:
## Typography
| Element | Font Size | Line Height | Weight | Letter Spacing |
|---------|-----------|-------------|--------|----------------|
| Title | 16px (`text-base`) | 24px (`leading-6`) | 600 (`font-semibold`) | 0px (`tracking-[0px]`) |
| Description | 14px (`text-sm`) | 20px (`leading-relaxed`) | 400 (`font-normal`) | 0.035px (`tracking-[0.035px]`) |6. Accessibility Validation
Rule: Components must meet WCAG 2.1 AA standards
Required checks:
Color Contrast:
// ✅ CORRECT - Sufficient contrast
className="bg-primary text-primary-foreground" // Ensures contrast
className="bg-background text-foreground" // Theme-aware contrast
// ❌ WRONG - Potentially low contrast
className="bg-gray-100 text-gray-300" // May fail contrast checkFocus States:
// ✅ CORRECT - Visible focus indicator
className="focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
// ✅ CORRECT - Focus-visible for keyboard only
className="focus-visible:ring-2 focus-visible:ring-ring"Keyboard Navigation:
// ✅ CORRECT - Keyboard accessible
<button onClick={...}> // Inherently keyboard accessible
// ✅ CORRECT - Custom interactive element with keyboard support
<div role="button" tabIndex={0} onKeyDown={handleKeyPress} onClick={...}>
// ❌ WRONG - Not keyboard accessible
<div onClick={...}> // Missing role and tabIndexARIA Attributes:
// ✅ CORRECT - Proper ARIA labels
<button aria-label="Close dialog">
<input aria-invalid={hasError} aria-describedby="error-message">
<div role="alert" aria-live="polite">
// ✅ CORRECT - Form field associations
<label htmlFor="email">Email</label>
<input id="email" name="email">Validation Workflow
Step 1: Scan Component Code
Search for prohibited patterns:
# Check for hardcoded hex colors
grep -r "#[0-9A-Fa-f]\{3,6\}" src/components/ui/component.tsx
# Check for RGB/HSL values
grep -r "rgb\|hsl" src/components/ui/component.tsx
# Check for hardcoded Tailwind colors
grep -r "bg-\(gray\|red\|blue\|green\|yellow\)-[0-9]" src/components/ui/component.tsxStep 2: Map to Semantic Tokens
For each color found, provide mapping:
Found: bg-[#343E55]
Context: Primary button background
Suggested mapping: bg-primary
Found: text-[#FFFFFF]
Context: Text on primary button
Suggested mapping: text-primary-foreground
Found: border-[#E4E4E4]
Context: Container border
Suggested mapping: border-semantic-border-layoutStep 3: Validate Responsive Design
Check for responsive classes:
// Check padding is responsive
✓ Found: px-4 sm:px-6 lg:px-8
✓ Found: py-2 sm:py-3
// Check text sizing is responsive
✓ Found: text-sm md:text-base
// Check layout is responsive
✓ Found: flex-col sm:flex-rowStep 4: Validate Accessibility
// Check focus states
✓ Found: focus:ring-2 focus:ring-ring
// Check ARIA labels
✓ Found: aria-label="Close"
// Check keyboard support
✓ Found: onKeyDown handler for custom interactive elementStep 5: Generate Validation Report
# Design System Validation Report
## CSS Variables
✅ All colors use semantic tokens
- bg-primary, text-primary-foreground
- border-semantic-border-layout
- text-semantic-text-muted
## Responsive Design
✅ Mobile-first breakpoints used
- Padding: px-4 sm:px-6 lg:px-8
- Text: text-sm md:text-base
- Layout: flex-col sm:flex-row
## Typography
✅ Semantic typography tokens
- Font sizes: text-sm, text-base
- Weights: font-normal, font-semibold
- Line heights: leading-normal, leading-relaxed
## Accessibility
✅ WCAG 2.1 AA compliant
- Focus states: focus:ring-2
- ARIA labels: aria-label present
- Keyboard: onKeyDown handlers
## Issues Found
❌ Hardcoded color at line 45: bg-[#F3F4F6]
Suggested fix: bg-muted
## Recommendations
- Replace bg-[#F3F4F6] with bg-muted
- Add responsive padding to container
- Consider adding aria-describedby for error statesColor Mapping Examples
Example 1: Button Component
Figma Design:
- Default: #F3F4F6 background, #333333 text
- Primary: #343E55 background, #FFFFFF text
- Destructive: #EF4444 background, #FFFFFF text
CSS Variable Mapping:
const buttonVariants = cva(
"inline-flex items-center justify-center",
{
variants: {
variant: {
default: "bg-secondary text-secondary-foreground", // #F3F4F6 → bg-secondary
primary: "bg-primary text-primary-foreground", // #343E55 → bg-primary
destructive: "bg-destructive text-destructive-foreground", // #EF4444 → bg-destructive
},
},
}
)Example 2: Alert Component
Figma Design:
- Error: #FEE2E2 background, #B42318 text, #EF4444 border
- Success: #DCFCE7 background, #15803D text, #22C55E border
- Warning: #FEF3C7 background, #92400E text, #F59E0B border
CSS Variable Mapping:
const alertVariants = cva(
"rounded-lg border p-4",
{
variants: {
variant: {
destructive: "bg-semantic-error-subtle text-semantic-error-primary border-destructive",
success: "bg-semantic-success-subtle text-semantic-success-primary border-success",
warning: "bg-semantic-warning-subtle text-semantic-warning-primary border-warning",
},
},
}
)Example 3: Form Input
Figma Design:
- Border: #E4E4E4 (normal), #4275D6 (focus), #B42318 (error)
- Background: #FFFFFF
- Text: #333333
- Placeholder: #9CA3AF
CSS Variable Mapping:
const inputVariants = cva(
"flex h-10 w-full rounded-md px-3 py-2",
"bg-background text-foreground", // Background & text
"border border-input", // Normal border
"placeholder:text-muted-foreground", // Placeholder
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", // Focus
"disabled:cursor-not-allowed disabled:opacity-50",
{
variants: {
state: {
default: "border-input",
error: "border-semantic-error-primary", // Error border
success: "border-semantic-success-primary",
},
},
}
)Best Practices
- Always use semantic tokens - Enables theme switching (dark mode)
- Document color mappings - Help future maintainers understand choices
- Validate against Figma - Ensure visual accuracy while using tokens
- Test in light/dark themes - Verify color contrast in both modes
- Mobile-first responsive - Start with mobile, enhance for larger screens
- Accessible by default - Build accessibility in, don't bolt it on
Error Messages
When validation fails, provide specific, actionable feedback:
❌ Hardcoded color detected at line 45
Found:
className="bg-[#343E55] text-white"
Issue:
- bg-[#343E55]: Hardcoded hex color
- text-white: Hardcoded color name
Fix:
className="bg-primary text-primary-foreground"
Reasoning:
- #343E55 is the primary brand color → use bg-primary
- white on primary needs high contrast → use text-primary-foreground
- Enables automatic theme switching (dark mode)This skill ensures design system consistency, theme compatibility, and accessibility compliance across all components.