AgentSkillsCN

theme-system

通过 next-themes/Tailwind 实现暗黑模式、设计令牌、色彩体系与字体排版的统一管理。 触发条件:“暗黑模式”、“配色方案”、“设计令牌”、“主题切换”、“FOUC 问题”。

SKILL.md
--- frontmatter
name: theme-system
description: |
  Implement dark mode, design tokens, color systems, typography with next-themes/Tailwind.
  Triggers: "dark mode", "color palette", "design tokens", "theme", "FOUC".

Theme System

The Reality of Dark Mode

Dark mode isn't optional:

  • User preferences split roughly 50/50 (varies by industry)
  • 4,605 ADA web accessibility lawsuits filed in 2024
  • European Accessibility Act enforceable since June 28, 2025
  • Pure black backgrounds cause eye strain in research studies

Before Theming (Analyze First)

If adding dark mode to existing code:

  1. Audit current colors: grep -r "bg-" . | grep -v "dark:" — find unhardened colors
  2. Map to semantic tokens: bg-white--surface-default; text-gray-900--text-primary
  3. Preserve brand colors: Primary/accent colors should shift, not replace
  4. Check contrast in both modes: A color that passes WCAG in light may fail in dark

Never assume a blank slate. Check what exists first.

Reference Loading

CRITICAL for Any Dark Mode Work

code
**MANDATORY - READ ENTIRE FILE BEFORE WRITING CODE**:
../../references/theming/dark-mode-antipatterns.md

Do NOT write dark mode code until you have read this file.

By Task

TaskMANDATORY Read FirstDo NOT Load
Color palettetheming/color-psychology.md, design-direction/index.md (then industry file)theming/typography-*.md
Design tokenstheming/palette-architecture.mdanimation/ files
Dark mode (CSS)theming/dark-mode-css.md, theming/dark-mode-antipatterns.mdseo/ files
Dark mode (Tailwind)theming/dark-mode-tailwind.md, theming/dark-mode-antipatterns.mdcopywriting/ files
Dark mode (Next.js)theming/dark-mode-nextjs.md, theming/dark-mode-antipatterns.mdpatterns/ files
Typographytheming/typography-pairing.md, theming/typography-scale.mdtheming/dark-mode-*.md

WCAG Contrast Requirements

The Formula

code
Contrast Ratio = (L1 + 0.05) / (L2 + 0.05)

Where:
- L1 = relative luminance of lighter color
- L2 = relative luminance of darker color
- Relative luminance = 0.2126×R + 0.7152×G + 0.0722×B
  (after gamma correction)

Required Ratios

ContentWCAG AAWCAG AAANotes
Normal text (< 18px)4.5:17:1Most body copy
Large text (≥ 18px or 14px bold)3:14.5:1Headings
UI components3:1Buttons, form borders
Non-text graphics3:1Icons, charts

AAA compensates for ~20/80 vision loss (W3C)

Quick Reference: Safe Color Combinations

BackgroundMinimum Text (AA)Safe TextNever Use
White #fffgray-600gray-700+gray-400 or lighter
Gray-100 #f3f4f6gray-600gray-700+gray-500 or lighter
Gray-900 #111827gray-400gray-300+gray-500 or darker
#121212 (dark mode)gray-400gray-300+gray-500 or darker
Blue-600 #2563ebwhite onlywhiteAny gray

Tool: Check before shipping with npx @contrast-check or WebAIM Contrast Checker

Dark Mode Anti-Patterns (Research-Backed)

Anti-PatternWhy It FailsResearchFix
Pure black #000000Eye strain, OLED "black smear", harsh contrastStudies show dark gray is more comfortable#121212 or #171717
Dark shadows on dark bgShadows disappear, UI feels flatUse elevation (lighter surfaces) or glowing shadows
Same saturation colorsVibrant colors feel "radioactive" on darkResearch on visual comfortDesaturate 10-20% for dark mode
No FOUC preventionFlash of wrong theme on loadBlocking script or next-themes
White text on blackHalation for users with astigmatismVision researchOff-white #e5e5e5 on dark gray
Ignoring form inputsInputs invisible or unreadableExplicitly style ALL form elements
Skipping interactive statesHover/focus look wrong in one modeTest EVERY state in BOTH modes

The Astigmatism Problem

~33% of adults have some degree of astigmatism. Bright text on dark backgrounds can cause "halation" — text appears to glow or blur. Mitigation:

  • Use slightly off-white text: #e5e5e5 or gray-200 instead of pure white
  • Slightly heavier font weight in dark mode (some systems do this automatically)

Color Psychology (Industry-Specific)

ColorBest ForWhyAvoid ForWhy
BlueFinance, SaaS, HealthcareTrust, calm, securityFoodSuppresses appetite
GreenHealth, Finance, EcoGrowth, money, natureLuxury, GamingFeels budget, not exciting
PurpleAI/Tech, Premium, CreativeInnovation, luxuryHealthcare, BudgetToo mystical, too expensive
Orange/RedCTAs, Food, EntertainmentUrgency, appetite, energyHealthcare, FinanceSignals danger/error
Black/WhiteLuxury, Editorial, FashionSophistication, timelessnessBudget brandsFeels too premium
Earth TonesD2C, Organic, OutdoorNatural, authenticTech, Speed-focusedFeels slow, traditional

CTA Button Color Research (2,588 A/B tests):

  • Blue buttons won 31% of tests
  • Green won 22%, Red won 16%
  • Red CTAs outperformed green by 20% on average (CXL)

Token Architecture

Three-tier system for maintainability:

css
/* TIER 1: Primitive (never use directly in components) */
:root {
  --blue-500: hsl(217, 91%, 60%);
  --gray-50: hsl(210, 20%, 98%);
  --gray-900: hsl(222, 47%, 11%);
}

/* TIER 2: Semantic (use for general styling) */
:root {
  --color-surface: var(--gray-50);
  --color-surface-elevated: white;
  --color-text-primary: var(--gray-900);
  --color-text-secondary: hsl(215, 16%, 47%);
  --color-action: var(--blue-500);
  --color-border: hsl(214, 32%, 91%);
}

:root.dark {
  --color-surface: #121212;
  --color-surface-elevated: #1e1e1e;
  --color-text-primary: #e5e5e5;
  --color-text-secondary: #a3a3a3;
  --color-action: hsl(217, 91%, 65%); /* slightly lighter */
  --color-border: hsl(215, 14%, 25%);
}

/* TIER 3: Component (specific usage) */
.btn-primary {
  background: var(--color-action);
  color: white;
}

.card {
  background: var(--color-surface-elevated);
  border: 1px solid var(--color-border);
}

Standard Semantic Token Names

surface-default, surface-elevated, surface-sunken, text-primary, text-secondary, text-muted, text-inverse, action-primary, action-secondary, status-success, status-warning, status-error, border-default, border-strong

Typography by Industry

IndustryRecommendedCharacteristicsAvoid
SaaS/TechInter, Geist, SF ProClean, highly legible, modernDecorative fonts
FinanceSource Sans 3, IBM PlexProfessional, trustworthyPlayful fonts
HealthcareNunito, Source SansFriendly but clearHeavy serifs
LuxuryPlayfair Display, CormorantElegant, distinctiveGeneric sans
Creative/AgencySpace Grotesk, Clash DisplayBold, memorableSafe/boring fonts
EditorialGeorgia, CharterReadable at lengthGeometric sans

Implementation Approach Decision Tree

code
Need dark mode?
├── Next.js project?
│   └── Use next-themes (FOUC prevention built-in)
│       npm install next-themes
│       Add ThemeProvider with attribute="class"
│
├── Vite/React SPA?
│   └── Use blocking script + localStorage
│       Add script to <head> before any content
│       Script must run synchronously
│
└── Static/vanilla?
    └── CSS media query + JS toggle
        @media (prefers-color-scheme: dark)
        Optional: localStorage for user preference

Output Checklist

Before delivering theme code, verify:

  • No #000000 pure black backgrounds
  • #121212 or darker gray for dark surfaces
  • All text passes WCAG AA contrast (4.5:1 normal, 3:1 large)
  • Form inputs explicitly styled for both modes
  • Interactive states (hover, focus, disabled) work in both modes
  • FOUC prevention implemented (if applicable)
  • Tokens follow three-tier architecture
  • Saturated colors desaturated 10-20% for dark mode

MANDATORY PIPELINE (DO NOT SKIP)

This skill is part of a multi-step pipeline. You MUST follow these steps:

PHASE 1: Pre-Implementation (MANDATORY)

Before writing ANY theme/dark mode code:

  1. CRITICAL - Read anti-patterns first:

    code
    READ: ../../references/theming/dark-mode-antipatterns.md
    

    DO NOT PROCEED without reading this file.

  2. Load implementation guide (by framework):

    code
    Next.js → READ: ../../references/theming/dark-mode-nextjs.md
    Tailwind → READ: ../../references/theming/dark-mode-tailwind.md
    CSS → READ: ../../references/theming/dark-mode-css.md
    
  3. Load design context:

    code
    READ: ../../references/theming/color-psychology.md
    READ: ../../references/theming/palette-architecture.md
    READ: ../../references/design-direction/index.md
    
  4. If creating typography system:

    code
    READ: ../../references/theming/typography-pairing.md
    READ: ../../references/theming/typography-scale.md
    

PHASE 2: Analyze Existing Code

Before adding dark mode to existing code:

  1. Run: grep -r "bg-" . | grep -v "dark:" to find unhardened colors
  2. Map existing colors to semantic tokens
  3. Identify brand colors to preserve
  4. Check current contrast ratios

PHASE 3: Implementation

Apply theming following:

  • Three-tier token architecture (Primitive → Semantic → Component)
  • WCAG contrast requirements (4.5:1 text, 3:1 UI)
  • Anti-pattern avoidance (no pure black, proper shadows, desaturated colors)
  • FOUC prevention (next-themes or blocking script)

PHASE 4: Post-Implementation (MANDATORY)

After implementing, you MUST:

  1. Run dark-mode-checker agent:

    "Let me validate the dark mode implementation..."

    Launch using Task tool with dark-mode-checker agent:

    • Background colors (no pure black)
    • Shadow handling
    • Color saturation
    • FOUC prevention
    • Form element styling
  2. Verify output checklist (from above):

    • No #000000 backgrounds
    • #121212 or darker gray for surfaces
    • WCAG AA contrast passes
    • Form inputs styled both modes
    • Interactive states work both modes
    • FOUC prevention implemented
    • 3-tier token architecture
    • Saturated colors desaturated
  3. If score <80, fix issues and re-validate

PHASE 5: Completion

Only complete when:

  • dark-mode-antipatterns.md was read
  • Framework-specific guide was read
  • dark-mode-checker agent passes (≥80)
  • No pure black backgrounds
  • FOUC prevention implemented
  • All form inputs styled

INTEGRATION WITH OTHER SKILLS

When called FROM component-builder:

  • You're adding theming to built components
  • Run dark-mode-checker before returning
  • Fix any issues found

When called FROM design-audit (fix mode):

  • You're fixing identified theme issues
  • Address specific issues from audit
  • Re-run dark-mode-checker to verify

When called STANDALONE:

  • Run full pipeline above
  • Suggest design-audit for complete validation