
Design System Lead
- 239 installs
- 451 repo stars
- Updated July 21, 2026
- borghei/claude-skills
design-system-lead is a design skill that defines tokens, components, accessibility rules, and contribution guidelines so developers keeping multiple product surfaces visually and behaviorally consistent at scale.
About
design-system-lead is an agent skill from borghei/claude-skills that guides creation and governance of design systems across multiple product surfaces. The skill covers design token architecture, component API contracts, accessibility rule enforcement, and contribution guidelines for growing teams. Developers reach for design-system-lead when a codebase spans web dashboards, mobile shells, or extension UIs that drift visually without shared standards. Output includes token schemas, component specifications, a11y checklists, and contributor workflows that keep behavior and appearance aligned. The skill fits React, Storybook, and monorepo frontend workflows where consistency errors compound across squads. It addresses scale problems that single-page design skills like gradient or corporate cannot solve alone.
- Design token architecture
- Reusable component specs
- Accessibility and states
- Versioning and contribution rules
- Cross-platform parity guidance
Design System Lead by the numbers
- 239 all-time installs (skills.sh)
- Ranked #894 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/borghei/claude-skills --skill design-system-leadAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 239 |
|---|---|
| repo stars | ★ 451 |
| Last updated | July 21, 2026 |
| Repository | borghei/claude-skills ↗ |
How do you build a design system for multiple products?
Define tokens, components, accessibility rules, and contribution guidelines so multiple product surfaces stay visually and behaviorally consistent at scale.
Who is it for?
Lead developers or design engineers scaling UI consistency across web, mobile, and extension surfaces in a monorepo.
Skip if: Single-page landing page theming or one-off campaign styling that does not need shared component governance.
When should I use this skill?
A developer asks to define design tokens, write component contribution guidelines, or enforce accessibility rules across product surfaces.
What you get
Design token schema, component specifications, accessibility rule set, and contribution guidelines document.
- Design token schema
- Contribution guidelines
- Accessibility rule set
Files
Design System Lead
The agent operates as a senior design system lead, delivering scalable component libraries, token architectures, governance processes, and adoption strategies for cross-functional product teams.
Clarify First
Before generating the design system, confirm these inputs. If any is unknown or vague, ASK — do not assume:
- [ ] Brand color and any existing tokens — the primitive values to build from (drives the three-tier token architecture)
- [ ] Current maturity level — Emerging, Defined, Managed, or Optimized (decides whether you establish foundations or optimize governance)
- [ ] Target platforms — web (CSS/SCSS), iOS, Android (drives token export formats and Style Dictionary config)
Stop rule: ask only the 2-3 that most change the output. If the user says "just draft it," proceed and list your assumptions at the top of the artifact.
Workflow
1. Assess maturity - Evaluate current design system maturity (Emerging, Defined, Managed, or Optimized). Audit existing patterns, inconsistencies, and custom components. Checkpoint: maturity level is documented with evidence. 2. Define token architecture - Build a three-tier token structure: primitive (raw values), semantic (purpose-based aliases), and component (scoped to specific UI elements). Checkpoint: every semantic token references a primitive; no hardcoded values remain. 3. Build component library - Design and implement components starting with primitives (Button, Input, Icon), then composites (Card, Modal, Dropdown), then patterns (Forms, Navigation, Tables). Checkpoint: each component has variants, sizes, states, props table, and accessibility requirements. 4. Document everything - Create usage guidelines, code examples, do/don't rules, and accessibility notes for every component. Checkpoint: documentation covers installation, basic usage, all variants, and at least one accessibility note. 5. Establish governance - Define the RFC-to-release contribution process. Set versioning strategy (SemVer). Checkpoint: contribution process is published and reviewed by both design and engineering leads. 6. Measure adoption - Track coverage (% of products using DS), consistency (token compliance rate), efficiency (time to build), and quality (a11y score, bug reports). Checkpoint: adoption dashboard is updated monthly.
Design System Maturity Model
| Level | Characteristics | Focus |
|---|---|---|
| 1: Emerging | Ad-hoc styles, no standards | Establish foundations |
| 2: Defined | Documented guidelines | Component library |
| 3: Managed | Shared component library | Adoption, governance |
| 4: Optimized | Automated, measured | Continuous improvement |
Token Architecture
Three-tier token system (primitive -> semantic -> component):
{
"color": {
"primitive": {
"blue": {
"50": {"value": "#eff6ff"},
"500": {"value": "#3b82f6"},
"600": {"value": "#2563eb"},
"900": {"value": "#1e3a8a"}
}
},
"semantic": {
"primary": {"value": "{color.primitive.blue.600}"},
"primary-hover": {"value": "{color.primitive.blue.700}"},
"background": {"value": "{color.primitive.gray.50}"},
"text": {"value": "{color.primitive.gray.900}"}
},
"component": {
"button-primary-bg": {"value": "{color.semantic.primary}"},
"button-primary-text": {"value": "#ffffff"}
}
},
"spacing": {
"primitive": {"1": {"value": "4px"}, "2": {"value": "8px"}, "4": {"value": "16px"}, "8": {"value": "32px"}},
"semantic": {"component-padding": {"value": "{spacing.primitive.4}"}, "section-gap": {"value": "{spacing.primitive.8}"}}
},
"typography": {
"fontFamily": {"sans": {"value": "Inter, system-ui, sans-serif"}, "mono": {"value": "JetBrains Mono, monospace"}},
"fontSize": {"sm": {"value": "14px"}, "base": {"value": "16px"}, "lg": {"value": "18px"}, "xl": {"value": "20px"}}
}
}Example: Cross-Platform Token Generation
// style-dictionary.config.js
module.exports = {
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [{ destination: 'variables.css', format: 'css/variables' }]
},
scss: {
transformGroup: 'scss',
buildPath: 'dist/scss/',
files: [{ destination: '_variables.scss', format: 'scss/variables' }]
},
ios: {
transformGroup: 'ios',
buildPath: 'dist/ios/',
files: [{ destination: 'StyleDictionaryColor.swift', format: 'ios-swift/class.swift' }]
},
android: {
transformGroup: 'android',
buildPath: 'dist/android/',
files: [{ destination: 'colors.xml', format: 'android/colors' }]
}
}
};Component Library Structure
design-system/
+-- foundations/ (colors, typography, spacing, elevation, motion, grid)
+-- components/
| +-- primitives/ (Button, Input, Icon)
| +-- composites/ (Card, Modal, Dropdown)
| +-- patterns/ (Forms, Navigation, Tables)
+-- layouts/ (page templates, content layouts)
+-- documentation/ (getting-started, design guidelines, code guidelines)
+-- assets/ (icons, illustrations, logos)Component Specification: Button
## Variants
- Primary: main action
- Secondary: supporting action
- Tertiary: low-emphasis action
- Destructive: dangerous/irreversible action
## Sizes
- Small: 32px height, 8px/12px padding
- Medium: 40px height (default), 10px/16px padding
- Large: 48px height, 12px/24px padding
## States
Default -> Hover -> Active -> Focus -> Disabled -> Loading
## Props
| Prop | Type | Default | Description |
|-----------|-------------|-----------|------------------|
| variant | string | 'primary' | Visual style |
| size | string | 'medium' | Button size |
| disabled | boolean | false | Disabled state |
| loading | boolean | false | Loading state |
| leftIcon | ReactNode | - | Leading icon |
| onClick | function | - | Click handler |
## Accessibility
- Minimum touch target: 44x44px
- Visible focus ring on keyboard navigation
- aria-label required for icon-only buttons
- aria-busy="true" when loadingExample: Button Implementation (React + CVA)
import { cva, type VariantProps } from 'class-variance-authority';
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
primary: 'bg-primary text-primary-foreground hover:bg-primary/90',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
},
size: {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4 text-sm',
lg: 'h-12 px-6 text-base',
},
},
defaultVariants: { variant: 'primary', size: 'md' },
}
);Governance: Contribution Process
1. REQUEST - Create RFC describing problem and proposed component/change
2. REVIEW - Design review + engineering review + accessibility review
3. BUILD - Figma component + code implementation + unit tests + visual regression
4. DOCUMENT - API docs + usage guidelines + Storybook stories
5. RELEASE - SemVer bump + changelog + announcementVersioning Strategy
| Change Type | Version Bump | Examples |
|---|---|---|
| Breaking | MAJOR | Component API change, token rename |
| New feature | MINOR | New component, new variant, new token |
| Bug fix | PATCH | Style fix, docs update, perf improvement |
Adoption Metrics Dashboard
Design System Health
Adoption: 82% (12/15 products)
Component Usage: 78% (45 components)
Token Compliance: 95%
Overrides: 23 (down from 38)
Efficiency
Avg time to build new feature: 3.2 days (was 5.1)
Custom components created this quarter: 4 (was 12)Scripts
# Token generator
python scripts/token_gen.py --source tokens.json --output dist/
# Component scaffolder
python scripts/component_scaffold.py --name DatePicker --category composite
# Adoption analyzer
python scripts/adoption_analyzer.py --repos repos.yaml
# Visual regression test
python scripts/visual_regression.py --baseline main --compare feature/new-buttonReference Materials
references/token_architecture.md- Token system designreferences/component_patterns.md- Component best practicesreferences/governance.md- Contribution guidelinesreferences/figma_setup.md- Figma library management
---
Tool Reference
token_gen.py
Generates a three-tier design token system (primitive, semantic, component) from a brand color. Supports CSS, SCSS, and JSON output. Includes WCAG contrast ratio checking.
| Flag | Type | Default | Description |
|---|---|---|---|
--color, -c | string | #0066CC | Brand color in hex |
--format, -f | choice | summary | Output format: json, css, scss, summary |
--tiers, -t | choice | all | Token tiers: all, primitive, semantic, component |
--output, -o | string | (stdout) | Output directory for generated files |
--json | flag | False | Shortcut for --format json |
python scripts/token_gen.py --color "#0066CC"
python scripts/token_gen.py --color "#0066CC" --format css --output dist/
python scripts/token_gen.py --color "#8B4513" --tiers primitive --jsoncomponent_scaffold.py
Generates component documentation scaffolds with props tables, variants, states, accessibility requirements, anatomy, usage guidelines, and code examples.
| Flag | Type | Default | Description |
|---|---|---|---|
--name, -n | string | (required) | Component name in PascalCase |
--category, -c | choice | (required) | Category: primitive, composite, pattern |
--variants, -v | string | (category default) | Comma-separated variant names |
--sizes, -s | string | sm,md,lg | Comma-separated size names |
--json | flag | False | Output as JSON |
python scripts/component_scaffold.py --name Button --category primitive
python scripts/component_scaffold.py --name DataTable --category pattern --variants "default,compact,striped"
python scripts/component_scaffold.py --name Modal --category composite --jsonadoption_analyzer.py
Analyzes design system adoption across products by evaluating component coverage, token compliance, custom overrides, and accessibility scores. Produces a health dashboard with per-product and portfolio-level analysis.
| Flag | Type | Default | Description |
|---|---|---|---|
input | positional | (required) | CSV file with adoption data or "sample" |
--threshold, -t | int | 75 | Health score threshold for flagging |
--json | flag | False | Output as JSON |
CSV columns: product, total_components, ds_components, total_tokens, ds_tokens, custom_overrides, a11y_score, last_audit
python scripts/adoption_analyzer.py sample
python scripts/adoption_analyzer.py adoption_data.csv
python scripts/adoption_analyzer.py adoption_data.csv --threshold 80 --json---
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
| Token overrides in production | Teams bypassing design system | Run adoption_analyzer monthly; add lint rules for hardcoded values |
| Inconsistent component behavior across products | Version drift | Enforce SemVer; automate DS dependency updates in CI |
| Low adoption in older products | Migration cost perceived as too high | Prioritize high-traffic pages; create migration guides per product |
| Token naming conflicts | No naming convention enforced | Adopt CTI (Category-Type-Item) naming; document in governance |
| Component API breaking changes | Insufficient versioning discipline | Use codemods for migration; deprecation period of 2 minor versions |
| Designers and developers out of sync | Figma/code token drift | Use Tokens Studio plugin; sync on every release |
| Contribution bottleneck | RFC review queue backed up | Set SLA for reviews (48h); rotate reviewers weekly |
---
Success Criteria
| Criterion | Target | How to Measure |
|---|---|---|
| Component coverage | >80% across all products | adoption_analyzer component coverage metric |
| Token compliance | >90% (no hardcoded values) | adoption_analyzer token compliance metric |
| Custom overrides | Trending downward quarter-over-quarter | Track total overrides in adoption report |
| Time to build new feature | 30%+ reduction vs pre-DS baseline | Compare sprint velocity before/after DS adoption |
| Accessibility score | >85% across all products | adoption_analyzer a11y score |
| Contribution rate | 2+ external contributions per quarter | Track merged RFCs from non-core-team members |
| Design-dev handoff time | <1 day for standard components | Measure time from design approval to code PR |
---
Scope & Limitations
In scope:
- Three-tier token architecture design and generation
- Component library structure and documentation scaffolding
- Adoption tracking and health reporting
- Cross-platform token export (CSS, SCSS, JSON)
- Governance process definition
- WCAG contrast ratio validation
Out of scope:
- Visual regression testing execution (use Chromatic, Percy, or BackstopJS)
- Figma plugin development (use Tokens Studio for token sync)
- Runtime theme switching implementation (framework-specific)
- Icon library creation and SVG optimization
- Motion design and animation library
- Component implementation code (scaffold generates docs, not runtime code)
---
Integration Points
| Tool / Platform | Integration Method | Use Case |
|---|---|---|
| Figma / Tokens Studio | Import token_gen JSON output | Sync design tokens between design and code |
| Style Dictionary | Use token_gen JSON as source | Build multi-platform tokens (iOS, Android, web) |
| Storybook | component_scaffold output as stories template | Auto-generate component documentation |
| Chromatic / Percy | Pair with component_scaffold test checklist | Visual regression testing pipeline |
| CI/CD | adoption_analyzer --json in pipeline | Automated adoption health checks on PRs |
| Tailwind / CSS-in-JS | token_gen CSS/JSON export | Theme configuration from design tokens |
#!/usr/bin/env python3
"""
Design System Adoption Analyzer
Analyzes design system adoption across products by scanning for
design token usage, custom overrides, and component coverage.
Reads a configuration CSV/JSON listing products and their metrics,
then produces an adoption health dashboard.
Uses ONLY Python standard library.
Usage:
python adoption_analyzer.py report.csv
python adoption_analyzer.py sample
python adoption_analyzer.py report.csv --json
python adoption_analyzer.py report.csv --threshold 80
"""
import argparse
import csv
import json
import sys
from datetime import datetime
from typing import Dict, List
def load_adoption_csv(filepath: str) -> List[Dict]:
"""Load adoption data from CSV.
Expected columns:
product: Product/app name
total_components: Total UI components in the product
ds_components: Components using design system
total_tokens: Total style values in the product
ds_tokens: Style values using design system tokens
custom_overrides: Number of custom overrides/deviations
a11y_score: Accessibility score (0-100)
last_audit: Date of last audit (YYYY-MM-DD)
"""
rows = []
with open(filepath, "r") as f:
reader = csv.DictReader(f)
for row in reader:
rows.append({
"product": row.get("product", "Unknown"),
"total_components": int(row.get("total_components", 0)),
"ds_components": int(row.get("ds_components", 0)),
"total_tokens": int(row.get("total_tokens", 0)),
"ds_tokens": int(row.get("ds_tokens", 0)),
"custom_overrides": int(row.get("custom_overrides", 0)),
"a11y_score": float(row.get("a11y_score", 0)),
"last_audit": row.get("last_audit", "N/A"),
})
return rows
def create_sample_csv(filepath: str):
"""Create sample adoption data for testing."""
header = ["product", "total_components", "ds_components", "total_tokens", "ds_tokens", "custom_overrides", "a11y_score", "last_audit"]
rows = [
["Web App", "120", "98", "450", "420", "12", "92", "2026-03-01"],
["Mobile App", "85", "72", "320", "285", "18", "88", "2026-02-15"],
["Admin Dashboard", "65", "60", "250", "245", "3", "95", "2026-03-10"],
["Marketing Site", "45", "30", "200", "140", "25", "78", "2026-01-20"],
["Developer Portal", "55", "48", "180", "165", "8", "90", "2026-02-28"],
["Onboarding Flow", "30", "28", "120", "118", "2", "96", "2026-03-15"],
]
with open(filepath, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(header)
writer.writerows(rows)
print(f"Sample CSV created at: {filepath}")
def analyze_product(product: Dict) -> Dict:
"""Analyze adoption metrics for a single product."""
total_comp = product["total_components"] or 1
total_tok = product["total_tokens"] or 1
component_coverage = round((product["ds_components"] / total_comp) * 100, 1)
token_compliance = round((product["ds_tokens"] / total_tok) * 100, 1)
override_rate = round((product["custom_overrides"] / total_comp) * 100, 1)
# Health score: weighted average
health_score = round(
component_coverage * 0.30
+ token_compliance * 0.30
+ product["a11y_score"] * 0.20
+ max(0, 100 - override_rate * 5) * 0.20,
1,
)
# Status
if health_score >= 90:
status = "EXCELLENT"
elif health_score >= 75:
status = "GOOD"
elif health_score >= 60:
status = "NEEDS ATTENTION"
else:
status = "AT RISK"
# Recommendations
recommendations = []
if component_coverage < 80:
gap = product["total_components"] - product["ds_components"]
recommendations.append(f"Migrate {gap} custom components to design system")
if token_compliance < 90:
gap = product["total_tokens"] - product["ds_tokens"]
recommendations.append(f"Replace {gap} hardcoded values with design tokens")
if product["custom_overrides"] > 10:
recommendations.append(f"Audit {product['custom_overrides']} custom overrides for potential DS contribution")
if product["a11y_score"] < 85:
recommendations.append(f"Improve accessibility score from {product['a11y_score']}% to 85%+ target")
return {
"product": product["product"],
"component_coverage": component_coverage,
"token_compliance": token_compliance,
"override_rate": override_rate,
"a11y_score": product["a11y_score"],
"health_score": health_score,
"status": status,
"recommendations": recommendations,
"last_audit": product["last_audit"],
}
def analyze_portfolio(products: List[Dict]) -> Dict:
"""Analyze adoption across the entire portfolio."""
analyses = [analyze_product(p) for p in products]
total_products = len(analyses)
adopted_count = sum(1 for a in analyses if a["component_coverage"] >= 50)
avg_coverage = round(sum(a["component_coverage"] for a in analyses) / total_products, 1) if total_products else 0
avg_compliance = round(sum(a["token_compliance"] for a in analyses) / total_products, 1) if total_products else 0
avg_health = round(sum(a["health_score"] for a in analyses) / total_products, 1) if total_products else 0
avg_a11y = round(sum(a["a11y_score"] for a in analyses) / total_products, 1) if total_products else 0
total_overrides = sum(p["custom_overrides"] for p in products)
status_counts = {}
for a in analyses:
status_counts[a["status"]] = status_counts.get(a["status"], 0) + 1
# Top priorities
priorities = sorted(analyses, key=lambda x: x["health_score"])[:3]
return {
"summary": {
"total_products": total_products,
"adopted_products": adopted_count,
"adoption_rate": round((adopted_count / total_products) * 100, 1) if total_products else 0,
"avg_component_coverage": avg_coverage,
"avg_token_compliance": avg_compliance,
"avg_a11y_score": avg_a11y,
"avg_health_score": avg_health,
"total_custom_overrides": total_overrides,
"status_distribution": status_counts,
},
"products": analyses,
"top_priorities": [
{"product": p["product"], "health_score": p["health_score"], "recommendations": p["recommendations"][:2]}
for p in priorities
],
}
def format_human_output(report: Dict, threshold: int) -> str:
"""Format adoption report as human-readable text."""
s = report["summary"]
lines = []
lines.append("=" * 60)
lines.append("DESIGN SYSTEM ADOPTION REPORT")
lines.append("=" * 60)
lines.append(f"\n PORTFOLIO SUMMARY")
lines.append(f" " + "-" * 50)
lines.append(f" Products tracked: {s['total_products']}")
lines.append(f" Products adopted: {s['adopted_products']} ({s['adoption_rate']}%)")
lines.append(f" Avg component coverage: {s['avg_component_coverage']}%")
lines.append(f" Avg token compliance: {s['avg_token_compliance']}%")
lines.append(f" Avg accessibility: {s['avg_a11y_score']}%")
lines.append(f" Avg health score: {s['avg_health_score']}%")
lines.append(f" Total custom overrides: {s['total_custom_overrides']}")
lines.append(f"\n Status distribution:")
for status, count in s["status_distribution"].items():
bar = "#" * (count * 5)
lines.append(f" {status:<18} {count} {bar}")
lines.append(f"\n PER-PRODUCT BREAKDOWN")
lines.append(f" " + "-" * 50)
lines.append(f" {'Product':<20} {'Coverage':>9} {'Tokens':>8} {'A11y':>6} {'Health':>8} {'Status':<15}")
lines.append(f" {'-'*20} {'-'*9} {'-'*8} {'-'*6} {'-'*8} {'-'*15}")
for p in sorted(report["products"], key=lambda x: -x["health_score"]):
flag = " *" if p["health_score"] < threshold else ""
lines.append(
f" {p['product']:<20} {p['component_coverage']:>8}% {p['token_compliance']:>7}% "
f"{p['a11y_score']:>5}% {p['health_score']:>7}% {p['status']:<15}{flag}"
)
lines.append(f"\n * Below {threshold}% health threshold")
lines.append(f"\n TOP PRIORITIES")
lines.append(f" " + "-" * 50)
for i, p in enumerate(report["top_priorities"], 1):
lines.append(f" {i}. {p['product']} (health: {p['health_score']}%)")
for rec in p["recommendations"]:
lines.append(f" - {rec}")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(
description="Analyze design system adoption across products",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python adoption_analyzer.py sample
python adoption_analyzer.py adoption_data.csv
python adoption_analyzer.py adoption_data.csv --threshold 80
python adoption_analyzer.py adoption_data.csv --json
CSV columns:
product, total_components, ds_components, total_tokens, ds_tokens,
custom_overrides, a11y_score, last_audit
""",
)
parser.add_argument("input", help='CSV file with adoption data or "sample" to create sample')
parser.add_argument("--threshold", "-t", type=int, default=75, help="Health score threshold for flagging (default: 75)")
parser.add_argument("--json", action="store_true", help="Output as JSON")
args = parser.parse_args()
if args.input == "sample":
create_sample_csv("sample_adoption.csv")
return
products = load_adoption_csv(args.input)
if not products:
print("Error: No data found in CSV", file=sys.stderr)
sys.exit(1)
report = analyze_portfolio(products)
if args.json:
print(json.dumps(report, indent=2))
else:
print(format_human_output(report, args.threshold))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Component Scaffolder for Design System Lead
Generates component documentation scaffolds including props table,
variants, states, accessibility requirements, and usage examples.
Uses ONLY Python standard library.
Usage:
python component_scaffold.py --name Button --category primitive
python component_scaffold.py --name DataTable --category pattern --variants "default,compact,striped"
python component_scaffold.py --name Modal --category composite --json
"""
import argparse
import json
import sys
from datetime import datetime
from typing import Dict, List
# Component category templates
CATEGORY_TEMPLATES = {
"primitive": {
"description": "A foundational UI element used as a building block for more complex components.",
"default_variants": ["primary", "secondary", "tertiary"],
"default_sizes": ["sm", "md", "lg"],
"default_states": ["default", "hover", "active", "focus", "disabled"],
"complexity": "low",
"examples": ["Button", "Input", "Icon", "Badge", "Label", "Checkbox", "Radio"],
},
"composite": {
"description": "A component composed of multiple primitives working together.",
"default_variants": ["default", "bordered", "elevated"],
"default_sizes": ["sm", "md", "lg"],
"default_states": ["default", "loading", "empty", "error"],
"complexity": "medium",
"examples": ["Card", "Modal", "Dropdown", "Accordion", "Tabs", "Toast"],
},
"pattern": {
"description": "A complex, reusable UI pattern solving a specific user interaction need.",
"default_variants": ["default"],
"default_sizes": ["default", "compact", "expanded"],
"default_states": ["default", "loading", "empty", "error", "success"],
"complexity": "high",
"examples": ["DataTable", "Form", "Navigation", "SearchBar", "Pagination", "FileUpload"],
},
}
# Common accessibility requirements by category
A11Y_REQUIREMENTS = {
"primitive": [
"Minimum touch target: 44x44px",
"Visible focus ring on keyboard navigation (2px offset, high contrast)",
"Color contrast meets WCAG AA (4.5:1 normal text, 3:1 large text)",
"Supports keyboard interaction (Enter/Space for activation)",
],
"composite": [
"Focus trapping for overlays (modal, dropdown)",
"Escape key closes/dismisses component",
"aria-expanded for collapsible sections",
"Screen reader announcements for state changes",
"Visible focus ring on all interactive elements",
],
"pattern": [
"Full keyboard navigation for all interactive elements",
"ARIA landmarks and roles for complex layouts",
"Screen reader-friendly table headers and captions",
"Loading states announced to assistive technology",
"Error messages associated with inputs via aria-describedby",
],
}
def generate_props(name: str, category: str, variants: List[str], sizes: List[str]) -> List[Dict]:
"""Generate standard props table for a component."""
props = [
{"name": "variant", "type": f"'{\"' | '\".join(variants)}'", "default": f"'{variants[0]}'", "required": False, "description": f"Visual style variant"},
{"name": "size", "type": f"'{\"' | '\".join(sizes)}'", "default": "'md'", "required": False, "description": "Component size"},
{"name": "disabled", "type": "boolean", "default": "false", "required": False, "description": "Disables interaction"},
{"name": "className", "type": "string", "default": "''", "required": False, "description": "Additional CSS class names"},
]
# Category-specific props
if category == "primitive":
props.extend([
{"name": "onClick", "type": "function", "default": "-", "required": False, "description": "Click event handler"},
{"name": "aria-label", "type": "string", "default": "-", "required": False, "description": "Accessible label (required for icon-only)"},
])
elif category == "composite":
props.extend([
{"name": "open", "type": "boolean", "default": "false", "required": False, "description": "Controls open/visible state"},
{"name": "onClose", "type": "function", "default": "-", "required": False, "description": "Close event handler"},
{"name": "children", "type": "ReactNode", "default": "-", "required": True, "description": "Component content"},
])
elif category == "pattern":
props.extend([
{"name": "data", "type": "array", "default": "[]", "required": True, "description": "Data source"},
{"name": "loading", "type": "boolean", "default": "false", "required": False, "description": "Loading state"},
{"name": "onAction", "type": "function", "default": "-", "required": False, "description": "Primary action handler"},
{"name": "emptyState", "type": "ReactNode", "default": "-", "required": False, "description": "Empty state content"},
])
return props
def generate_tokens_map(name: str, category: str) -> Dict:
"""Generate design token mapping for the component."""
base = {
"background": f"{{component.{name.lower()}.bg}}",
"text": f"{{color.foreground}}",
"border": f"{{component.{name.lower()}.border}}",
"borderRadius": f"{{component.{name.lower()}.radius}}",
"padding": f"{{spacing.component-padding}}",
}
if category == "composite":
base["shadow"] = f"{{component.{name.lower()}.shadow}}"
base["overlay"] = "{color.overlay}"
return base
def generate_scaffold(args) -> Dict:
"""Generate complete component scaffold."""
category_template = CATEGORY_TEMPLATES.get(args.category, CATEGORY_TEMPLATES["primitive"])
variants = args.variants.split(",") if args.variants else category_template["default_variants"]
sizes = args.sizes.split(",") if args.sizes else category_template["default_sizes"]
states = category_template["default_states"]
props = generate_props(args.name, args.category, variants, sizes)
tokens = generate_tokens_map(args.name, args.category)
a11y = A11Y_REQUIREMENTS.get(args.category, A11Y_REQUIREMENTS["primitive"])
scaffold = {
"component": {
"name": args.name,
"category": args.category,
"description": category_template["description"],
"version": "0.1.0",
"status": "draft",
"created": datetime.now().strftime("%Y-%m-%d"),
},
"anatomy": {
"slots": _generate_anatomy_slots(args.name, args.category),
},
"variants": [{"name": v, "description": f"{v.title()} visual style"} for v in variants],
"sizes": [{"name": s, "description": f"{s.upper()} size variant"} for s in sizes],
"states": [{"name": s, "description": f"{s.title()} interaction state"} for s in states],
"props": props,
"design_tokens": tokens,
"accessibility": a11y,
"usage_guidelines": {
"do": _generate_do_guidelines(args.name, args.category),
"dont": _generate_dont_guidelines(args.name, args.category),
},
"code_example": _generate_code_example(args.name, variants[0], sizes),
"testing_checklist": [
f"All {len(variants)} variants render correctly",
f"All {len(sizes)} sizes render correctly",
"All states visually distinct",
"Keyboard navigation works",
"Screen reader announces correctly",
"Responsive behavior verified at all breakpoints",
"Visual regression snapshot captured",
],
"file_structure": {
"component": f"components/{args.category}s/{args.name}/{args.name}.tsx",
"styles": f"components/{args.category}s/{args.name}/{args.name}.styles.ts",
"tests": f"components/{args.category}s/{args.name}/{args.name}.test.tsx",
"stories": f"components/{args.category}s/{args.name}/{args.name}.stories.tsx",
"docs": f"components/{args.category}s/{args.name}/README.md",
},
}
return scaffold
def _generate_anatomy_slots(name: str, category: str) -> List[Dict]:
"""Generate component anatomy slots."""
base_slots = [
{"name": "root", "element": "div", "description": "Outermost wrapper"},
]
if category == "primitive":
base_slots.extend([
{"name": "leadingIcon", "element": "span", "description": "Optional leading icon"},
{"name": "label", "element": "span", "description": "Text content"},
{"name": "trailingIcon", "element": "span", "description": "Optional trailing icon"},
])
elif category == "composite":
base_slots.extend([
{"name": "header", "element": "div", "description": "Component header area"},
{"name": "body", "element": "div", "description": "Main content area"},
{"name": "footer", "element": "div", "description": "Actions or metadata area"},
])
elif category == "pattern":
base_slots.extend([
{"name": "toolbar", "element": "div", "description": "Controls and filters"},
{"name": "content", "element": "div", "description": "Primary content region"},
{"name": "pagination", "element": "nav", "description": "Navigation controls"},
])
return base_slots
def _generate_do_guidelines(name: str, category: str) -> List[str]:
"""Generate 'do' usage guidelines."""
return [
f"Use {name} for its intended purpose within the design system",
"Apply design tokens instead of hardcoded values",
"Include appropriate ARIA attributes for accessibility",
"Test across all supported breakpoints and browsers",
"Follow established naming conventions for variants",
]
def _generate_dont_guidelines(name: str, category: str) -> List[str]:
"""Generate 'don't' usage guidelines."""
return [
f"Don't use {name} as a substitute for a different component",
"Don't override design tokens with inline styles",
"Don't nest interactive elements inside interactive elements",
"Don't remove focus indicators for keyboard users",
"Don't create new variants without RFC approval",
]
def _generate_code_example(name: str, default_variant: str, sizes: List[str]) -> str:
"""Generate a code usage example."""
return f"""import {{ {name} }} from '@design-system/components';
// Basic usage
<{name} variant="{default_variant}">{name} Content</{name}>
// With size
<{name} variant="{default_variant}" size="{sizes[1] if len(sizes) > 1 else sizes[0]}">{name}</{name}>
// Disabled
<{name} variant="{default_variant}" disabled>{name}</{name}>"""
def format_human_output(scaffold: Dict) -> str:
"""Format scaffold as human-readable markdown-style output."""
c = scaffold["component"]
lines = []
lines.append("=" * 60)
lines.append(f"COMPONENT SCAFFOLD: {c['name']}")
lines.append("=" * 60)
lines.append(f"\n Category: {c['category']}")
lines.append(f" Status: {c['status']}")
lines.append(f" Description: {c['description']}")
lines.append(f"\n ANATOMY")
for slot in scaffold["anatomy"]["slots"]:
lines.append(f" <{slot['element']}> {slot['name']} - {slot['description']}")
lines.append(f"\n VARIANTS: {', '.join(v['name'] for v in scaffold['variants'])}")
lines.append(f" SIZES: {', '.join(s['name'] for s in scaffold['sizes'])}")
lines.append(f" STATES: {', '.join(s['name'] for s in scaffold['states'])}")
lines.append(f"\n PROPS TABLE")
lines.append(f" {'Name':<15} {'Type':<25} {'Default':<12} {'Required':<10} Description")
lines.append(f" {'-'*15} {'-'*25} {'-'*12} {'-'*10} {'-'*20}")
for p in scaffold["props"]:
req = "Yes" if p["required"] else "No"
ptype = str(p["type"])[:24]
lines.append(f" {p['name']:<15} {ptype:<25} {str(p['default']):<12} {req:<10} {p['description']}")
lines.append(f"\n DESIGN TOKENS")
for k, v in scaffold["design_tokens"].items():
lines.append(f" {k}: {v}")
lines.append(f"\n ACCESSIBILITY")
for req in scaffold["accessibility"]:
lines.append(f" - {req}")
lines.append(f"\n USAGE GUIDELINES")
lines.append(f" Do:")
for item in scaffold["usage_guidelines"]["do"]:
lines.append(f" + {item}")
lines.append(f" Don't:")
for item in scaffold["usage_guidelines"]["dont"]:
lines.append(f" - {item}")
lines.append(f"\n CODE EXAMPLE")
lines.append(f" ```")
lines.append(scaffold["code_example"])
lines.append(f" ```")
lines.append(f"\n FILE STRUCTURE")
for key, path in scaffold["file_structure"].items():
lines.append(f" {key}: {path}")
lines.append(f"\n TESTING CHECKLIST")
for item in scaffold["testing_checklist"]:
lines.append(f" [ ] {item}")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(
description="Generate design system component scaffold with docs, props, and a11y requirements",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python component_scaffold.py --name Button --category primitive
python component_scaffold.py --name Card --category composite --variants "default,bordered,elevated"
python component_scaffold.py --name DataTable --category pattern --json
python component_scaffold.py --name Modal --category composite --sizes "sm,md,lg,xl"
""",
)
parser.add_argument("--name", "-n", required=True, help="Component name (PascalCase)")
parser.add_argument("--category", "-c", choices=["primitive", "composite", "pattern"], required=True, help="Component category")
parser.add_argument("--variants", "-v", help="Comma-separated variant names")
parser.add_argument("--sizes", "-s", help="Comma-separated size names")
parser.add_argument("--json", action="store_true", help="Output as JSON")
args = parser.parse_args()
scaffold = generate_scaffold(args)
if args.json:
print(json.dumps(scaffold, indent=2))
else:
print(format_human_output(scaffold))
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Design Token Generator for Design System Lead
Generates a three-tier design token system (primitive -> semantic -> component)
from a brand color input. Outputs in JSON, CSS, or SCSS format.
Uses ONLY Python standard library.
Usage:
python token_gen.py --color "#0066CC"
python token_gen.py --color "#0066CC" --format css --output dist/
python token_gen.py --color "#0066CC" --format scss --tiers all --json
"""
import argparse
import colorsys
import json
import math
import os
import sys
from typing import Dict, List, Tuple
def hex_to_rgb(hex_color: str) -> Tuple[int, int, int]:
"""Convert hex color to RGB tuple."""
h = hex_color.lstrip("#")
return tuple(int(h[i : i + 2], 16) for i in (0, 2, 4))
def rgb_to_hex(r: int, g: int, b: int) -> str:
"""Convert RGB to hex string."""
return "#{:02x}{:02x}{:02x}".format(max(0, min(255, r)), max(0, min(255, g)), max(0, min(255, b)))
def adjust_hue(hex_color: str, degrees: float) -> str:
"""Rotate hue of a hex color by given degrees."""
r, g, b = hex_to_rgb(hex_color)
h, s, v = colorsys.rgb_to_hsv(r / 255, g / 255, b / 255)
h = (h + degrees / 360) % 1.0
nr, ng, nb = colorsys.hsv_to_rgb(h, s, v)
return rgb_to_hex(int(nr * 255), int(ng * 255), int(nb * 255))
def generate_color_scale(hex_color: str) -> Dict[str, str]:
"""Generate a 10-step color scale from a base color."""
r, g, b = hex_to_rgb(hex_color)
h, s, v = colorsys.rgb_to_hsv(r / 255, g / 255, b / 255)
scale = {}
steps = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900]
for step in steps:
if step < 500:
new_v = 0.95 + (1.0 - 0.95) * ((500 - step) / 500)
new_s = s * (0.2 + 0.8 * (step / 500))
elif step == 500:
new_v = v
new_s = s
else:
factor = (step - 500) / 400
new_v = v * (1 - factor * 0.7)
new_s = min(1.0, s * (1 + factor * 0.3))
nr, ng, nb = colorsys.hsv_to_rgb(h, new_s, new_v)
scale[str(step)] = rgb_to_hex(int(nr * 255), int(ng * 255), int(nb * 255))
return scale
def contrast_ratio(hex1: str, hex2: str) -> float:
"""Calculate WCAG contrast ratio between two colors."""
def relative_luminance(hex_c: str) -> float:
r, g, b = hex_to_rgb(hex_c)
rs, gs, bs = r / 255, g / 255, b / 255
rl = rs / 12.92 if rs <= 0.03928 else ((rs + 0.055) / 1.055) ** 2.4
gl = gs / 12.92 if gs <= 0.03928 else ((gs + 0.055) / 1.055) ** 2.4
bl = bs / 12.92 if bs <= 0.03928 else ((bs + 0.055) / 1.055) ** 2.4
return 0.2126 * rl + 0.7152 * gl + 0.0722 * bl
l1 = relative_luminance(hex1)
l2 = relative_luminance(hex2)
lighter = max(l1, l2)
darker = min(l1, l2)
return round((lighter + 0.05) / (darker + 0.05), 2)
def generate_primitive_tokens(brand_color: str) -> Dict:
"""Generate primitive (raw value) tokens."""
secondary = adjust_hue(brand_color, 180)
accent = adjust_hue(brand_color, 30)
return {
"color": {
"blue": generate_color_scale(brand_color),
"secondary": generate_color_scale(secondary),
"accent": generate_color_scale(accent),
"gray": {
"50": "#f9fafb", "100": "#f3f4f6", "200": "#e5e7eb",
"300": "#d1d5db", "400": "#9ca3af", "500": "#6b7280",
"600": "#4b5563", "700": "#374151", "800": "#1f2937", "900": "#111827",
},
"white": "#ffffff",
"black": "#000000",
"green": {"500": "#10b981", "600": "#059669", "700": "#047857"},
"red": {"500": "#ef4444", "600": "#dc2626", "700": "#b91c1c"},
"yellow": {"500": "#f59e0b", "600": "#d97706", "700": "#b45309"},
},
"spacing": {str(i): f"{i * 4}px" for i in range(0, 17)},
"fontSize": {
"xs": "12px", "sm": "14px", "base": "16px", "lg": "18px",
"xl": "20px", "2xl": "24px", "3xl": "30px", "4xl": "36px", "5xl": "48px",
},
"fontWeight": {
"light": "300", "normal": "400", "medium": "500",
"semibold": "600", "bold": "700", "extrabold": "800",
},
"borderRadius": {
"none": "0", "sm": "4px", "md": "8px", "lg": "12px",
"xl": "16px", "2xl": "24px", "full": "9999px",
},
"lineHeight": {
"tight": "1.25", "snug": "1.375", "normal": "1.5",
"relaxed": "1.625", "loose": "2",
},
}
def generate_semantic_tokens(primitives: Dict) -> Dict:
"""Generate semantic (purpose-based alias) tokens."""
return {
"color": {
"primary": "{color.blue.500}",
"primary-hover": "{color.blue.600}",
"primary-active": "{color.blue.700}",
"secondary": "{color.secondary.500}",
"secondary-hover": "{color.secondary.600}",
"background": "{color.white}",
"background-subtle": "{color.gray.50}",
"background-muted": "{color.gray.100}",
"foreground": "{color.gray.900}",
"foreground-muted": "{color.gray.600}",
"foreground-subtle": "{color.gray.400}",
"border": "{color.gray.200}",
"border-strong": "{color.gray.300}",
"success": "{color.green.500}",
"success-hover": "{color.green.600}",
"error": "{color.red.500}",
"error-hover": "{color.red.600}",
"warning": "{color.yellow.500}",
"warning-hover": "{color.yellow.600}",
"info": "{color.blue.500}",
"overlay": "rgba(0, 0, 0, 0.5)",
"focus-ring": "{color.blue.300}",
},
"spacing": {
"xs": "{spacing.1}",
"sm": "{spacing.2}",
"md": "{spacing.4}",
"lg": "{spacing.6}",
"xl": "{spacing.8}",
"2xl": "{spacing.12}",
"3xl": "{spacing.16}",
"component-padding": "{spacing.4}",
"section-gap": "{spacing.8}",
"page-margin": "{spacing.6}",
},
"typography": {
"heading": {"fontFamily": "Inter, system-ui, sans-serif", "fontWeight": "{fontWeight.bold}"},
"body": {"fontFamily": "Inter, system-ui, sans-serif", "fontWeight": "{fontWeight.normal}"},
"mono": {"fontFamily": "JetBrains Mono, monospace", "fontWeight": "{fontWeight.normal}"},
},
}
def generate_component_tokens(semantics: Dict) -> Dict:
"""Generate component-scoped tokens."""
return {
"button": {
"primary": {
"bg": "{color.primary}",
"bg-hover": "{color.primary-hover}",
"bg-active": "{color.primary-active}",
"text": "{color.white}",
"border": "transparent",
"radius": "{borderRadius.md}",
},
"secondary": {
"bg": "{color.background}",
"bg-hover": "{color.background-subtle}",
"text": "{color.foreground}",
"border": "{color.border}",
"radius": "{borderRadius.md}",
},
"destructive": {
"bg": "{color.error}",
"bg-hover": "{color.error-hover}",
"text": "{color.white}",
"border": "transparent",
"radius": "{borderRadius.md}",
},
"size-sm": {"height": "32px", "paddingX": "12px", "fontSize": "{fontSize.sm}"},
"size-md": {"height": "40px", "paddingX": "16px", "fontSize": "{fontSize.base}"},
"size-lg": {"height": "48px", "paddingX": "20px", "fontSize": "{fontSize.lg}"},
},
"input": {
"bg": "{color.background}",
"bg-disabled": "{color.background-muted}",
"border": "{color.border}",
"border-focus": "{color.primary}",
"border-error": "{color.error}",
"text": "{color.foreground}",
"placeholder": "{color.foreground-subtle}",
"radius": "{borderRadius.md}",
"size-sm": {"height": "32px", "paddingX": "12px", "fontSize": "{fontSize.sm}"},
"size-md": {"height": "40px", "paddingX": "16px", "fontSize": "{fontSize.base}"},
"size-lg": {"height": "48px", "paddingX": "20px", "fontSize": "{fontSize.lg}"},
},
"card": {
"bg": "{color.background}",
"border": "{color.border}",
"radius": "{borderRadius.lg}",
"padding": "{spacing.component-padding}",
"shadow": "0 1px 3px rgba(0,0,0,0.1)",
},
"modal": {
"bg": "{color.background}",
"overlay": "{color.overlay}",
"radius": "{borderRadius.xl}",
"padding": "{spacing.section-gap}",
"shadow": "0 20px 60px rgba(0,0,0,0.15)",
},
}
def resolve_references(tokens: Dict, primitives: Dict) -> Dict:
"""Resolve {reference} tokens to actual values for export."""
flat_primitives = {}
def flatten(obj, prefix=""):
for k, v in obj.items():
key = f"{prefix}.{k}" if prefix else k
if isinstance(v, dict):
flatten(v, key)
else:
flat_primitives[key] = v
flatten(primitives)
def resolve(obj):
if isinstance(obj, str):
if obj.startswith("{") and obj.endswith("}"):
ref = obj[1:-1]
return flat_primitives.get(ref, obj)
return obj
elif isinstance(obj, dict):
return {k: resolve(v) for k, v in obj.items()}
return obj
return resolve(tokens)
def export_css(tokens: Dict, tier_name: str) -> str:
"""Export tokens as CSS custom properties."""
lines = [f"/* {tier_name} tokens */", ":root {"]
def flatten(obj, prefix):
for k, v in obj.items():
key = f"{prefix}-{k}"
if isinstance(v, dict):
flatten(v, key)
else:
lines.append(f" --{key}: {v};")
flatten(tokens, tier_name)
lines.append("}")
return "\n".join(lines)
def export_scss(tokens: Dict, tier_name: str) -> str:
"""Export tokens as SCSS variables."""
lines = [f"// {tier_name} tokens"]
def flatten(obj, prefix):
for k, v in obj.items():
key = f"{prefix}-{k}"
if isinstance(v, dict):
flatten(v, key)
else:
lines.append(f"${key}: {v};")
flatten(tokens, tier_name)
return "\n".join(lines)
def format_human_output(all_tokens: Dict, brand_color: str) -> str:
"""Format token summary for human-readable output."""
lines = []
lines.append("=" * 60)
lines.append("DESIGN TOKEN SYSTEM")
lines.append("=" * 60)
lines.append(f"\n Brand Color: {brand_color}")
lines.append(f" Architecture: Three-tier (primitive -> semantic -> component)")
for tier_name, tier_data in all_tokens.items():
count = sum(1 for _ in _count_leaves(tier_data))
lines.append(f"\n {tier_name.upper()} TOKENS ({count} values)")
lines.append(" " + "-" * 40)
for category in tier_data:
if isinstance(tier_data[category], dict):
sub_count = sum(1 for _ in _count_leaves(tier_data[category]))
lines.append(f" {category}: {sub_count} tokens")
else:
lines.append(f" {category}: {tier_data[category]}")
# Contrast check
primitives = all_tokens.get("primitive", {})
blue_scale = primitives.get("color", {}).get("blue", {})
if "500" in blue_scale and "900" in blue_scale:
cr_white = contrast_ratio(blue_scale["500"], "#ffffff")
cr_black = contrast_ratio(blue_scale["500"], "#000000")
lines.append(f"\n WCAG CONTRAST CHECK (primary-500)")
lines.append(f" vs white: {cr_white}:1 {'PASS AA' if cr_white >= 4.5 else 'FAIL AA'}")
lines.append(f" vs black: {cr_black}:1 {'PASS AA' if cr_black >= 4.5 else 'FAIL AA'}")
return "\n".join(lines)
def _count_leaves(obj):
"""Yield leaf values from nested dict."""
if isinstance(obj, dict):
for v in obj.values():
yield from _count_leaves(v)
else:
yield obj
def main():
parser = argparse.ArgumentParser(
description="Generate three-tier design token system from brand color",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python token_gen.py --color "#0066CC"
python token_gen.py --color "#0066CC" --format css --output dist/
python token_gen.py --color "#8B4513" --tiers primitive --json
python token_gen.py --color "#FF6B6B" --format scss
""",
)
parser.add_argument("--color", "-c", default="#0066CC", help="Brand color in hex (default: #0066CC)")
parser.add_argument("--format", "-f", choices=["json", "css", "scss", "summary"], default="summary", help="Output format (default: summary)")
parser.add_argument("--tiers", "-t", choices=["all", "primitive", "semantic", "component"], default="all", help="Token tiers to generate (default: all)")
parser.add_argument("--output", "-o", help="Output directory for generated files")
parser.add_argument("--json", action="store_true", help="Shortcut for --format json")
args = parser.parse_args()
if args.json:
args.format = "json"
brand_color = args.color.strip("'\"")
# Generate tokens
primitives = generate_primitive_tokens(brand_color)
semantics = generate_semantic_tokens(primitives)
components = generate_component_tokens(semantics)
all_tokens = {}
if args.tiers in ("all", "primitive"):
all_tokens["primitive"] = primitives
if args.tiers in ("all", "semantic"):
all_tokens["semantic"] = semantics
if args.tiers in ("all", "component"):
all_tokens["component"] = components
# Output
if args.format == "json":
print(json.dumps(all_tokens, indent=2))
elif args.format == "summary":
print(format_human_output(all_tokens, brand_color))
elif args.format in ("css", "scss"):
export_fn = export_css if args.format == "css" else export_scss
resolved_primitives = primitives
resolved_semantics = resolve_references(semantics, primitives)
resolved_components = resolve_references(components, {**primitives, **semantics})
output_parts = []
if args.tiers in ("all", "primitive"):
output_parts.append(export_fn(resolved_primitives, "primitive"))
if args.tiers in ("all", "semantic"):
output_parts.append(export_fn(resolved_semantics, "semantic"))
if args.tiers in ("all", "component"):
output_parts.append(export_fn(resolved_components, "component"))
result = "\n\n".join(output_parts)
if args.output:
os.makedirs(args.output, exist_ok=True)
ext = "css" if args.format == "css" else "scss"
filepath = os.path.join(args.output, f"tokens.{ext}")
with open(filepath, "w") as f:
f.write(result)
print(f"Tokens written to {filepath}")
else:
print(result)
if __name__ == "__main__":
main()
Related skills
How it compares
Pick design-system-lead for multi-surface governance and token architecture; pick corporate or gradient for single-product visual theming.
FAQ
What does design-system-lead deliver?
Design-system-lead delivers design token schemas, component specifications, accessibility rules, and contribution guidelines. Developers use the output to keep multiple product surfaces visually and behaviorally consistent as frontend teams scale.
When should teams use design-system-lead?
Teams should use design-system-lead when product surfaces drift without shared standards across web, mobile, or extension UIs. The skill addresses token architecture and governance problems that single-page styling skills cannot solve.