AgentSkillsCN

Design System Validator

在组件开发过程中,优先使用 CSS 变量替代硬编码颜色,验证语义化标记,检查响应式设计模式,并强化设计系统的统一性。当您创建或验证组件时,此技能便能助您一臂之力。

SKILL.md
--- frontmatter
name: Design System Validator
description: Ensures CSS variables are used instead of hardcoded colors, validates semantic tokens, checks responsive design patterns, and enforces design system consistency. Activate when creating or validating components.
version: 1.0.0

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:

tsx
// ❌ 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:

tsx
// ✅ 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 ContextCSS VariableTailwind ClassUsage
Backgrounds
Page background--backgroundbg-backgroundMain page background
Foreground text--foregroundtext-foregroundPrimary text on background
Card background--cardbg-cardRaised surfaces
Card text--card-foregroundtext-card-foregroundText on cards
Popover background--popoverbg-popoverFloating elements
Popover text--popover-foregroundtext-popover-foregroundText on popovers
Actions
Primary background--primarybg-primaryPrimary buttons
Primary text--primary-foregroundtext-primary-foregroundText on primary
Secondary background--secondarybg-secondarySecondary buttons
Secondary text--secondary-foregroundtext-secondary-foregroundText on secondary
Muted background--mutedbg-mutedDisabled states
Muted text--muted-foregroundtext-muted-foregroundMuted/disabled text
Accent background--accentbg-accentAccent highlights
Accent text--accent-foregroundtext-accent-foregroundText on accent
Destructive background--destructivebg-destructiveError/delete actions
Destructive text--destructive-foregroundtext-destructive-foregroundText on destructive
Borders & Inputs
Border color--borderborder-borderStandard borders
Input border--inputborder-inputInput field borders
Ring color--ringring-ringFocus rings

Semantic Tokens (myOperator-specific)

ContextCSS VariableTailwind ClassUsage
Backgrounds
Primary--semantic-bg-primarybg-semantic-bg-primaryComponent backgrounds
Secondary--semantic-bg-secondarybg-semantic-bg-secondaryAlternative backgrounds
Subtle--semantic-bg-subtlebg-semantic-bg-subtleHover/selected states
Text
Primary--semantic-text-primarytext-semantic-text-primaryMain text content
Secondary--semantic-text-secondarytext-semantic-text-secondarySupporting text
Muted--semantic-text-mutedtext-semantic-text-mutedDisabled/placeholder
Link--semantic-text-linktext-semantic-text-linkInteractive links
Borders
Layout--semantic-border-layoutborder-semantic-border-layoutContainer borders
Input--semantic-border-inputborder-semantic-border-inputForm field borders
Focus--semantic-border-focusborder-semantic-border-focusFocus indicators
States
Error primary--semantic-error-primarytext-semantic-error-primaryError messages
Error subtle--semantic-error-subtlebg-semantic-error-subtleError backgrounds
Success primary--semantic-success-primarytext-semantic-success-primarySuccess messages
Success subtle--semantic-success-subtlebg-semantic-success-subtleSuccess backgrounds
Warning primary--semantic-warning-primarytext-semantic-warning-primaryWarning messages
Warning subtle--semantic-warning-subtlebg-semantic-warning-subtleWarning backgrounds
Info
Info primary--semantic-info-primarytext-semantic-info-primaryInformational messages
Info subtle--semantic-info-subtlebg-semantic-info-subtleInformational backgrounds

3. Color Mapping from Figma

When extracting colors from Figma, map them to semantic tokens:

Mapping algorithm:

  1. 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
  2. Match to existing tokens by usage pattern:

    code
    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.css for the actual variable definition
  • This prevents using tokens that don't exist or have different names than expected
bash
# 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
  1. Document custom mappings: If a color doesn't match existing tokens, document it:
    tsx
    // 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:

tsx
// ✅ 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 tablets
  • md: 768px - Tablets
  • lg: 1024px - Laptops
  • xl: 1280px - Desktops
  • 2xl: 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

tsx
// ✅ 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.025em

Typography table format for Storybook:

markdown
## 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:

tsx
// ✅ 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 check

Focus States:

tsx
// ✅ 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:

tsx
// ✅ 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 tabIndex

ARIA Attributes:

tsx
// ✅ 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:

bash
# 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.tsx

Step 2: Map to Semantic Tokens

For each color found, provide mapping:

code
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-layout

Step 3: Validate Responsive Design

Check for responsive classes:

tsx
// 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-row

Step 4: Validate Accessibility

tsx
// 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 element

Step 5: Generate Validation Report

markdown
# 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 states

Color 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:

tsx
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:

tsx
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:

tsx
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

  1. Always use semantic tokens - Enables theme switching (dark mode)
  2. Document color mappings - Help future maintainers understand choices
  3. Validate against Figma - Ensure visual accuracy while using tokens
  4. Test in light/dark themes - Verify color contrast in both modes
  5. Mobile-first responsive - Start with mobile, enhance for larger screens
  6. Accessible by default - Build accessibility in, don't bolt it on

Error Messages

When validation fails, provide specific, actionable feedback:

code
❌ 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.