Round 1 — Establish the semantic token layer
Part of the UI-parity epic (#22). resumelint has no design tokens: tailwind.config.js defines colors as zero (fontFamily only), src/styles.css hardcodes bg-white / bg-neutral-950 with a manual prefers-color-scheme block, and the three feature components carry ~120 raw palette classes (text-neutral-500, bg-amber-100, border-neutral-800, …) each with hand-rolled dark variants.
This round ports the token substrate from Recruidea so feature code has real semantic classes to reuse — matching what CLAUDE.md already (incorrectly) claims is canonical.
Scope
-
Palette → src/styles.css. Port the light + dark --color-* values from Recruidea packages/expo-common/src/theme/tokens.ts (lightPalette / darkPalette) into a :root { … } block plus a dark block. Recruidea drives dark mode via NativeWind vars(); resumelint is plain Vite + Tailwind, so adapt — use @media (prefers-color-scheme: dark) (current mechanism) to swap the --color-* values. Keep only the tokens resumelint actually uses (brand, surface, content, border, accent, feedback) — drop status/tier/sponsor/chip palettes that belong to the dashboard app.
-
Mapping → tailwind.config.js. Extend theme.extend.colors to map semantic names to the vars, matching Recruidea's names exactly:
surface: { base, card, card-warm, subtle, hover }
content: { primary, secondary, tertiary, muted, inverse }
border: { light, DEFAULT, strong }
brand: { navy, navy-dark, amber, amber-light, cream }
accent: { primary, primary-hover, forward, forward-bg }
feedback (error/warning/info/success) bg/border/text/icon
-
Migrate components. Replace every raw palette class in src/components/{DropZone,PdfPreview,Result}.tsx with the semantic equivalent. Manual dark: variants disappear — the var swap handles dark mode. Target: zero (bg|text|border|from|to)-(neutral|gray|slate|red|amber|green|orange|zinc|stone)-N classes remaining under src/components.
-
Reconcile CLAUDE.md. The "Styling & Tokens" section names bg-surface / text-ink / text-brand-primary. Rename to the adopted vocab (bg-surface-card, text-content-primary, text-brand-amber) so doc matches code.
Explicitly NOT this round
- No visual redesign. Net visual change should be ~neutral — this is a substrate swap, not the score-card chrome (that's Round 2).
- No
Result.tsx decomposition (separate concern).
Acceptance
References (local ~/recruidea)
packages/expo-common/src/theme/tokens.ts — lightPalette / darkPalette
dashboard/tailwind.config.js — semantic name mapping to copy
Round 1 — Establish the semantic token layer
Part of the UI-parity epic (#22). resumelint has no design tokens:
tailwind.config.jsdefines colors as zero (fontFamily only),src/styles.csshardcodesbg-white/bg-neutral-950with a manualprefers-color-schemeblock, and the three feature components carry ~120 raw palette classes (text-neutral-500,bg-amber-100,border-neutral-800, …) each with hand-rolled dark variants.This round ports the token substrate from Recruidea so feature code has real semantic classes to reuse — matching what
CLAUDE.mdalready (incorrectly) claims is canonical.Scope
Palette →
src/styles.css. Port the light + dark--color-*values from Recruideapackages/expo-common/src/theme/tokens.ts(lightPalette/darkPalette) into a:root { … }block plus a dark block. Recruidea drives dark mode via NativeWindvars(); resumelint is plain Vite + Tailwind, so adapt — use@media (prefers-color-scheme: dark)(current mechanism) to swap the--color-*values. Keep only the tokens resumelint actually uses (brand, surface, content, border, accent, feedback) — drop status/tier/sponsor/chip palettes that belong to the dashboard app.Mapping →
tailwind.config.js. Extendtheme.extend.colorsto map semantic names to the vars, matching Recruidea's names exactly:surface: { base, card, card-warm, subtle, hover }content: { primary, secondary, tertiary, muted, inverse }border: { light, DEFAULT, strong }brand: { navy, navy-dark, amber, amber-light, cream }accent: { primary, primary-hover, forward, forward-bg }feedback(error/warning/info/success) bg/border/text/iconMigrate components. Replace every raw palette class in
src/components/{DropZone,PdfPreview,Result}.tsxwith the semantic equivalent. Manualdark:variants disappear — the var swap handles dark mode. Target: zero(bg|text|border|from|to)-(neutral|gray|slate|red|amber|green|orange|zinc|stone)-Nclasses remaining undersrc/components.Reconcile
CLAUDE.md. The "Styling & Tokens" section namesbg-surface/text-ink/text-brand-primary. Rename to the adopted vocab (bg-surface-card,text-content-primary,text-brand-amber) so doc matches code.Explicitly NOT this round
Result.tsxdecomposition (separate concern).Acceptance
grep -rE "(bg|text|border|from|to)-(neutral|gray|slate|red|amber|green|orange|zinc|stone)-[0-9]" src/componentsreturns nothingtailwind.config.jsexposes the semantic token names above;styles.cssdefines the light + dark--color-*valuesCLAUDE.mdtoken vocab matches the shipped confignpm run typecheckandnpm run buildgreenReferences (local
~/recruidea)packages/expo-common/src/theme/tokens.ts—lightPalette/darkPalettedashboard/tailwind.config.js— semantic name mapping to copy