semantic-coding

Replace hardcoded styles with semantic design tokens (colors, typography, spacing, sizing) across a codebase. Use when refactoring inline hex colors/px values to a design system, migrating to CSS vari

SKILL.md

GitHub

Semantic Coding

Scan files, replace hardcoded styles with semantic design tokens (colors, typography, spacing, sizing), edit files directly.

Refactored from semantic-colors (color-only) into a comprehensive design system skill.

Usage

/semantic-coding [path]

DO NOT TOUCH (Non-Negotiable)

  • Gradients: from-*, via-*, to-*, bg-gradient-*, linear-gradient(), radial-gradient(), conic-gradient()
  • SVG defs: <linearGradient>, <radialGradient>, <stop>, url(#...), anything inside <defs>
  • Glass morphism: rgba(255,255,255,0.0x) overlays on gradient backgrounds
  • Decorative shadows: boxShadow glow effects tied to gradient LED/orb effects
  • Animations: @keyframes, animation timing values, transform values
  • Template literals: `border-${color}-500`, dynamic class construction
  • Arbitrary values: bg-[#hex], text-[14px], p-[20px] (JIT bracket syntax)
  • Component props: Color/style values passed as non-className props (e.g., <Button color="red-500" />)
  • Token source files: globals.css, tailwind.config.*, tokens.ts, theme.ts
  • Excluded dirs: node_modules, .next, lib/generated, prisma/, dist/, __tests__/, *.test.*, *.spec.*

If a value is inside a protected context, skip and log ⚠ skipped (protected context).


Color Rules

Color Replacements

Note: Color-to-semantic mapping depends on your project's brand palette. The defaults below assume orange=brand, blue=info. If your brand uses blue/indigo/etc., map that family to brand instead and adjust accordingly.

Hardcoded Semantic
text-red-*, text-rose-* text-error
text-green-*, text-emerald-*, text-teal-* text-success
text-yellow-*, text-amber-* text-warning
text-blue-*, text-cyan-* text-info
text-orange-* text-brand
text-indigo-*, text-violet-*, text-purple-* text-primary
text-pink-*, text-fuchsia-* text-accent
text-gray-*, text-slate-*, text-zinc-*, text-stone-*, text-neutral-*, text-ink-* text-muted-foreground
text-gray-900, text-slate-900, text-zinc-900 text-foreground
text-white (on semantic bg) text-{bg-token}-foreground
text-black text-foreground
bg-red-*, bg-rose-* (shade ≥500) bg-error
bg-red-*, bg-rose-* (shade <500) bg-error/10
bg-green-*, bg-emerald-*, bg-teal-* (shade ≥500) bg-success
bg-green-*, bg-emerald-*, bg-teal-* (shade <500) bg-success/10
bg-yellow-*, bg-amber-* (shade ≥500) bg-warning
bg-yellow-*, bg-amber-* (shade <500) bg-warning/10
bg-blue-*, bg-cyan-* (shade ≥500) bg-info
bg-blue-*, bg-cyan-* (shade <500) bg-info/10
bg-orange-* bg-brand or bg-brand/10
bg-indigo-*, bg-violet-*, bg-purple-* bg-primary or bg-primary/10
bg-gray-*, bg-slate-*, bg-zinc-*, bg-stone-*, bg-neutral-*, bg-ink-* bg-muted
bg-white (page-level) bg-background
bg-white (inside card/panel) bg-card
bg-black/50 (overlay) bg-overlay
border-gray-*, border-slate-*, border-zinc-*, border-stone-*, border-neutral-*, border-ink-* border-border
border-red-*, border-rose-* border-error
border-green-*, border-emerald-*, border-teal-* border-success
border-blue-*, border-cyan-* border-info
border-yellow-*, border-amber-* border-warning
border-orange-* border-brand
border-indigo-*, border-violet-*, border-purple-* border-primary
shadow-emerald-*, shadow-green-* shadow-success
shadow-red-* shadow-error
shadow-blue-* shadow-info
ring-red-* ring-error
ring-green-* ring-success
ring-blue-* ring-info
divide-gray-*, divide-slate-* divide-border
placeholder-gray-* placeholder-muted-foreground

Foreground Pairing

Background Foreground
bg-primary text-primary-foreground
bg-brand text-brand-foreground
bg-success text-success-foreground
bg-error text-error-foreground
bg-warning text-warning-foreground
bg-info text-info-foreground

Dark Mode Override Removal

Collapse light+dark pairs into one semantic token:

- className="text-green-600 dark:text-green-400"
+ className="text-success"

- className="bg-red-100 dark:bg-red-900/20 border-red-200 dark:border-red-800"
+ className="bg-error/10 border-error"

Typography Rules

Font Family

Hardcoded Semantic
font-sans (body text) font-body
font-sans (headings) font-heading
font-mono font-mono
font-serif font-display
Inline fontFamily: 'Inter' var(--font-body)
Inline fontFamily: 'monospace' var(--font-mono)

Font Size (Text Scale)

Hardcoded Semantic Use Case
text-xs text-caption Labels, hints, timestamps
text-sm text-body-sm Secondary content, metadata
text-base text-body Body text, paragraphs
text-lg text-body-lg Lead paragraphs, emphasis
text-xl text-heading-sm Small headings, card titles
text-2xl text-heading-md Section headings
text-3xl text-heading-lg Page titles
text-4xl, text-5xl text-heading-xl Hero headings
text-6xl, text-7xl, text-8xl, text-9xl text-display Display/marketing headings
Inline fontSize: '14px' var(--text-body-sm)
Inline fontSize: '24px' var(--text-heading-md)

Font Weight

Hardcoded Semantic Use Case
font-extralight (200) font-thin Decorative, display text
font-light (300) font-light Subtle body text
font-normal (400) font-normal Body text
font-medium (500) font-medium Emphasis, labels
font-semibold (600) font-semibold Subheadings
font-bold (700) font-bold Headings, CTAs
font-extrabold (800), font-black (900) font-heavy Display, marketing

Line Height

Hardcoded Semantic Use Case
leading-none leading-none Display text, single-line
leading-tight leading-tight Headings
leading-snug leading-snug Subheadings
leading-normal leading-normal Body text
leading-relaxed leading-relaxed Long-form content
leading-loose leading-loose Legal, fine print

Letter Spacing

Hardcoded Semantic
tracking-tighter tracking-heading
tracking-tight tracking-heading
tracking-normal tracking-body
tracking-wide tracking-label
tracking-wider tracking-label
tracking-widest + uppercase tracking-overline

Composite Typography Patterns

Match multi-class patterns before individual classes. Apply the first matching composite rule.

Hardcoded Pattern Semantic
text-6xl+ font-bold/extrabold text-display
text-4xl font-bold tracking-tight text-heading-xl
text-3xl font-semibold text-title
text-2xl font-semibold text-subtitle
text-lg font-medium text-lead
text-base text-body
text-sm text-gray-* text-muted
text-xs uppercase tracking-wide text-overline
text-xs font-medium text-label

Spacing Rules

Semantic Spacing Scale

Hardcoded Semantic Value
p-1, m-1 space-xs 4px
p-2, m-2 space-sm 8px
p-3, m-3 space-md 12px
p-4, m-4 space-lg 16px
p-5, m-5 space-xl 20px
p-6, m-6 space-2xl 24px
p-8, m-8 space-3xl 32px
p-10, m-10 space-4xl 40px
p-12, m-12 space-5xl 48px

Component Spacing Patterns

Context Recommended Token
Button padding px-button py-button or p-4
Card padding p-card or p-6
Section padding p-section or py-12 px-6
Input padding px-input py-input or px-4 py-2
Gap between items gap-sm (8px), gap-md (12px), gap-lg (16px)
Stack spacing space-y-sm, space-y-md, space-y-lg

Sizing Rules

Width/Height

Hardcoded Semantic Use Case
w-4 h-4 size-icon-xs Small icons
w-5 h-5 size-icon-sm Default icons
w-6 h-6 size-icon-md Medium icons
w-8 h-8 size-icon-lg Large icons
w-10 h-10 size-avatar-sm Small avatars
w-12 h-12 size-avatar-md Medium avatars
w-16 h-16 size-avatar-lg Large avatars
h-10, h-11 h-input Input/button height
max-w-sm max-w-form Form container
max-w-xl max-w-content Content container
max-w-5xl max-w-page Page container

Border Radius

Hardcoded Semantic Use Case
rounded rounded-sm Subtle rounding
rounded-md rounded-base Default rounding
rounded-lg rounded-lg Cards, modals
rounded-xl rounded-xl Large cards
rounded-2xl rounded-2xl Hero sections
rounded-full rounded-full Pills, avatars

Shadow Rules

Hardcoded Semantic Use Case
shadow-sm shadow-sm Subtle elevation
shadow shadow-base Default elevation
shadow-md shadow-md Cards
shadow-lg shadow-lg Modals, dropdowns
shadow-xl shadow-xl Popovers
shadow-2xl shadow-2xl Floating elements
shadow-success shadow-success Success glow
shadow-error shadow-error Error glow

Z-Index Rules

Hardcoded Semantic Use Case
z-0 z-base Default layer
z-10 z-dropdown Dropdowns
z-20 z-sticky Sticky headers
z-30 z-overlay Overlays
z-40 z-modal Modals
z-50 z-toast Toasts, tooltips

Inline Style Replacements

Hardcoded Semantic
style={{ color: '#111827' }} className="text-foreground"
style={{ color: '#6b7280' }} className="text-muted-foreground"
style={{ backgroundColor: '#ffffff' }} var(--color-background)
style={{ fontSize: '14px' }} var(--text-body-sm)
style={{ fontWeight: 600 }} className="font-semibold"
style={{ padding: '16px' }} className="p-4" or var(--space-lg)
style={{ borderRadius: '8px' }} var(--radius-base)

Third-Party Config Pattern

When a library requires specific values at initialization, use runtime CSS variable resolution:

function cssVar(name, fallback) {
  if (typeof window === 'undefined') return fallback;
  return getComputedStyle(document.documentElement)
    .getPropertyValue(name).trim() || fallback;
}

// Usage: cssVar('--color-brand', '#F97316')

Initialize in useEffect (not module level) so CSS variables are available.


Scoped Token Pattern

When a page has a fixed dark background that doesn't change with theme, use var() with inline fallback:

color: 'var(--status-text-muted, #a1a1aa)'

Status Mapping

Status Semantic
DRAFT muted
PENDING, SUBMITTED warning
CONFIRMED, SUCCESS, COMPLETED, PAID success
REJECTED, ERROR, CANCELLED error
INFO, SENT, RECEIVED info

Available Tokens Reference

Colors

Text: text-foreground, text-muted-foreground, text-primary, text-primary-foreground, text-brand, text-brand-foreground, text-accent, text-success, text-success-foreground, text-warning, text-warning-foreground, text-error, text-error-foreground, text-info, text-info-foreground

Background: bg-background, bg-card, bg-muted, bg-primary, bg-brand, bg-accent, bg-success, bg-warning, bg-error, bg-info, bg-overlay

Border: border-border, border-input, border-primary, border-brand, border-success, border-error, border-warning, border-info

Ring: ring-primary, ring-success, ring-error, ring-info

Shadow: shadow-success, shadow-error, shadow-info

Misc: divide-border, placeholder-muted-foreground

Typography

Font Family: font-body, font-heading, font-mono, font-display

Font Size: text-caption, text-body-sm, text-body, text-body-lg, text-heading-sm, text-heading-md, text-heading-lg, text-heading-xl, text-display

Composite: text-title, text-subtitle, text-lead, text-muted, text-overline, text-label

Font Weight: font-thin, font-light, font-normal, font-medium, font-semibold, font-bold, font-heavy

Letter Spacing: tracking-heading, tracking-body, tracking-label, tracking-overline

Line Height: leading-none, leading-tight, leading-snug, leading-normal, leading-relaxed, leading-loose

Spacing

Padding/Margin: space-xs, space-sm, space-md, space-lg, space-xl, space-2xl, space-3xl, space-4xl, space-5xl

Component: p-card, p-section, p-input, px-button, py-button

Gap: gap-xs, gap-sm, gap-md, gap-lg, gap-xl

Stack: space-y-sm, space-y-md, space-y-lg

Sizing

Icons: size-icon-xs, size-icon-sm, size-icon-md, size-icon-lg

Avatars: size-avatar-sm, size-avatar-md, size-avatar-lg

Containers: max-w-form, max-w-content, max-w-page

Input: h-input

Effects

Radius: rounded-sm, rounded-base, rounded-lg, rounded-xl, rounded-2xl, rounded-full

Shadow: shadow-sm, shadow-base, shadow-md, shadow-lg, shadow-xl, shadow-2xl

Z-Index: z-base, z-dropdown, z-sticky, z-overlay, z-modal, z-toast


Behavior

For each .tsx, .jsx, .ts, .js file in the target path (skip excluded dirs):

  1. Read the file
  2. Find hardcoded styles (colors, fonts, sizes, spacing)
  3. Check if inside protected context (gradient/SVG-def/animation)
  4. If safe → apply matching rule and edit immediately
  5. If protected context → skip, log as ⚠ skipped

After all files are done, re-scan to verify zero remaining violations. Print summary.

Summary Format

Semantic coding refactor: N files changed, M replacements
- file.tsx: colors (5), typography (3), spacing (2)
⚠ file.tsx:42 — skipped (gradient context)
⚠ file.tsx:88 — skipped (SVG defs)