semantic-coding
georgekhananaev/claude-skills-vault/.claude/skills/semantic-coding/SKILL.md
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 variables or Tailwind theme tokens, or enforcing token consistency.
Skill28 starsChanged 4 months ago
What's in it
- Semantic Coding
- Usage
- DO NOT TOUCH (Non-Negotiable)
- Color Rules
- Color Replacements
- Foreground Pairing
- Dark Mode Override Removal
- Typography Rules
- Font Family
- Font Size (Text Scale)
- Font Weight
- Line Height
- Letter Spacing
- Composite Typography Patterns
- Spacing Rules
- Semantic Spacing Scale
- Component Spacing Patterns
- Sizing Rules
- Width/Height
- Border Radius
- Shadow Rules
- Z-Index Rules
- Inline Style Replacements
- Third-Party Config Pattern
- Scoped Token Pattern
- Status Mapping
- Available Tokens Reference
- Colors
- Typography
- Spacing
---
name: semantic-coding
description: 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 variables or Tailwind theme tokens, or enforcing token consistency.
---
# 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:
```diff
- 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:
```js
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:
```js
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)
```
More agent context in georgekhananaev/claude-skills-vault
63 other files this repository gives its agents, the first 60 shown.
AGENTS.md
Skill
- agy-cli.claude/skills/agy-cli/SKILL.md
- aws-cli.claude/skills/aws-cli/SKILL.md
- better-auth.claude/skills/better-auth/SKILL.md
- brainstorm.claude/skills/brainstorm/SKILL.md
- claude-seo.claude/skills/claude-seo/SKILL.md
- code-quality.claude/skills/code-quality/SKILL.md
- codex-cli.claude/skills/codex-cli/SKILL.md
- color-accessibility-audit.claude/skills/color-accessibility-audit/SKILL.md
- vercel-composition-patterns.claude/skills/composition-patterns/SKILL.md
- data-wrangler.claude/skills/data-wrangler/SKILL.md
- doc-navigator.claude/skills/doc-navigator/SKILL.md
- domain-checker.claude/skills/domain-checker/SKILL.md
- fastapi-senior-dev.claude/skills/fastapi-senior-dev/SKILL.md
- file-converter.claude/skills/file-converter/SKILL.md
- firebase-cli.claude/skills/firebase-cli/SKILL.md
- firecrawl.claude/skills/firecrawl-cli/SKILL.md
- frontend-design.claude/skills/frontend-design/SKILL.md
- gemini-cli.claude/skills/gemini-cli/SKILL.md
- github-cli.claude/skills/github-cli/SKILL.md
- materialreacttable-mastery.claude/skills/materialreacttable-mastery/SKILL.md
- mcp-builder.claude/skills/mcp-builder/SKILL.md
- mermaid-diagram.claude/skills/mermaid-diagram/SKILL.md
- monday-com.claude/skills/monday-com/SKILL.md
- mongodb-atlas-cli.claude/skills/mongodb-atlas-cli/SKILL.md
- multi-agent-patterns.claude/skills/multi-agent-patterns/SKILL.md
- n8n-cli.claude/skills/n8n-cli/SKILL.md
- natural-language.claude/skills/natural-language/SKILL.md
- neon-postgres-agent-platforms.claude/skills/neon-postgres-agent-platforms/SKILL.md
- next-cache-components.claude/skills/next-cache-components/SKILL.md
- nextjs-senior-dev.claude/skills/nextjs-senior-dev/SKILL.md
- next-upgrade.claude/skills/next-upgrade/SKILL.md
- notebooklm.claude/skills/notebooklm-skill/SKILL.md
- obsidian-skills.claude/skills/obsidian-skills/SKILL.md
- owasp-security.claude/skills/owasp-security/SKILL.md
- parallel-agents.claude/skills/parallel-agents/SKILL.md
- planning-with-files.claude/skills/planning-with-files/SKILL.md
- plan-to-tdd.claude/skills/plan-to-tdd/SKILL.md
- project-change-log.claude/skills/project-change-log/SKILL.md
- pydantic-model.claude/skills/pydantic-model/SKILL.md
- react-best-practices.claude/skills/react-best-practices/SKILL.md
- salesforce-cli.claude/skills/salesforce-cli/SKILL.md
- senior-backend.claude/skills/senior-backend/SKILL.md
- skill-creator.claude/skills/skill-creator/SKILL.md
- stripe-best-practices.claude/skills/stripe-best-practices/SKILL.md
- supabase-cli.claude/skills/supabase-cli/SKILL.md
- swift-concurrency-6-2.claude/skills/swift-concurrency6.2/SKILL.md
- swiftui-patterns.claude/skills/swiftui-patterns/SKILL.md
- system-architect.claude/skills/system-architect/SKILL.md
- terraform.claude/skills/terraform/SKILL.md
- testing-automation-expert.claude/skills/testing-automation-expert/SKILL.md
- test-levels.claude/skills/test-levels/SKILL.md
- token-optimizer.claude/skills/token-optimizer/SKILL.md
- trailofbits-security.claude/skills/trailofbits-security/SKILL.md
- ui-ux-pro-max.claude/skills/ui-ux-pro-max/SKILL.md
- uiux-toolkit.claude/skills/uiux-toolkit/SKILL.md
- upgrade-packages-js.claude/skills/upgrade-packages-js/SKILL.md
- vercel-cli.claude/skills/vercel-cli/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool public_context_discussion, action report. How to connect one.

