feat(styles): add design token system with CSS custom properties#121
Conversation
Introduces a 3-layer design token architecture in tokens.css: - Layer 1: Named palette (grayscale, blue, red, green scales) verified against all 25 CSS Module files in client/src/ - Layer 2: Semantic tokens for backgrounds, text, borders, primary/danger/success actions, status badges, role badges, sidebar, shadows, spacing, border-radius, and transitions - Layer 3: Dark-mode override stubs (commented, for Story 12.4) Imports tokens.css as the first line of index.css and updates the body rule to use --color-bg-secondary / --color-text-primary instead of hardcoded values. No .module.css files are touched — zero visual change. Fixes #116 Co-Authored-By: Claude ux-designer (Sonnet 4.6) <noreply@anthropic.com>
steilerDev
left a comment
There was a problem hiding this comment.
[security-engineer] Security review of PR #121 (Design Token System, Story 12.1)
Summary
No security vulnerabilities identified. Approved.
Analysis
✅ CSS Custom Properties Safety
- CSS variables cannot execute code or cause XSS. Values are purely declarative (colors, spacing, shadows, typography, z-index).
- No
javascript:URLs,eval(), or executable content.
✅ No Sensitive Data Exposure
- All token values are public design constants intended for the UI.
- No API keys, passwords, credentials, or PII in the token file.
✅ No CSS Injection Risks
- Static
@import './tokens.css'with relative path — no dynamic imports or user-controlled values. - Import correctly placed at the top of index.css, before tokens are referenced.
✅ Import Order & Specificity
- Global custom property declarations at the top ensure they are available throughout the cascade.
- Body element correctly references tokens via
var(--color-bg-secondary)andvar(--color-text-primary). - No CSS specificity tricks that could hide content or bypass styling.
✅ No Information Disclosure
- Commented-out dark mode overrides (Layer 3) safely document future work without affecting current behavior.
✅ CSS Parsing Safety
- All color values use standard hex format or
rgba()with no unescaped input. - No unusual CSS syntax that could break parsing or introduce attack vectors.
Verdict
This is a well-designed design token system following CSS best practices. The 3-layer architecture (palette → semantic → dark mode) prevents token value drift and improves maintainability. All values are non-executable and public.
Approved for merge. ✓
steilerDev
left a comment
There was a problem hiding this comment.
[product-architect]
Reviewed against the Story 12.1 acceptance criteria and the planned 3-layer token architecture. The overall structure is solid — the palette/semantic/dark-stub layering is correct, the import placement is right, body styles use semantic tokens, and zero .module.css files were touched. However there are four gaps that must be resolved before this merges, because Story 12.3 (the migration story) will need these tokens to exist when it runs.
CHANGES REQUIRED
1. Missing --shadow-focus-danger token
WorkItemCreatePage.module.css:125 uses box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1). The tokens file defines --color-focus-ring-danger: rgba(220, 38, 38, 0.1) (the color form) but omits the shadow form. This means Story 12.3 has no token to migrate that value to.
Add to the "Focus rings (box-shadow form)" section in tokens.css:
--shadow-focus-danger: 0 0 0 3px rgba(220, 38, 38, 0.1);2. Missing font-weight tokens
Font weights 500, 600, and 700 appear across at least 12 module files. The TYPOGRAPHY section covers --font-size-* but has no --font-weight-* tokens. Story 12.3 cannot migrate these hardcoded values without corresponding tokens.
Add to the TYPOGRAPHY section:
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;3. Green palette naming inconsistency (--color-green-150)
The palette defines:
--color-green-100: #d1fae5— this is the Tailwind emerald-100 value, not green-100--color-green-150: #dcfce7— this is the Tailwind green-100 value, labeled with a non-standard step number
Mixing green and emerald scales under a single green namespace, and using a -150 step that exists in no standard system, will confuse anyone referencing Tailwind docs or using a design tool.
Recommended fix: rename to match actual origin:
--color-green-100: #d1fae5→--color-emerald-100: #d1fae5--color-green-150: #dcfce7→--color-green-100: #dcfce7
Then update the two semantic references that point at these palette tokens:
--color-success-badge-bg: var(--color-green-100)→var(--color-emerald-100)--color-user-active-bg: var(--color-green-150)→var(--color-green-100)
4. Missing coverage for 0.8125rem (13px) font-size
UserManagementPage.module.css:423 uses font-size: 0.8125rem. No token covers this value. Either:
- Add
--font-size-xs-plus: 0.8125rem(or a clearer name), or - Document in a comment that this value must be normalized to
--font-size-xsor--font-size-smduring Story 12.3
Without this, Story 12.3 will encounter a hardcoded size that has no token migration target.
Non-Blocking Observations (no change required)
-
Abbreviated hex values
#fee,#fcc,#c00inWorkItemCreatePage.module.css: Out of scope for Story 12.1 (.module.cssfiles are Story 12.3). Story 12.3 must normalize these —#fef2f2,#fecaca, and#dc2626are all covered by existing tokens. -
Layer 1 and Layer 2 co-located inside
:root: Architecturally valid. CSS custom properties must live inside a selector scope. Comment dividers clearly separate the layers. -
--transition-buttonas a multi-property value: Valid pattern. Worth adding a brief comment so Story 12.3 migration knows callers must writetransition: var(--transition-button)(not nest inside another transition shorthand).
Summary
The 3-layer structure, naming conventions, import placement, and scope discipline are all correct. The four items above are small additive changes to tokens.css only — add the missing danger shadow token, add font-weight tokens, fix the green/emerald palette naming, and add or document the 13px font-size. After those are addressed this is ready to merge.
Add missing shadow-focus-danger, font-weight, and font-size-2xs tokens. Add comments clarifying green palette naming. Co-Authored-By: Claude frontend-developer (Sonnet 4.6) <noreply@anthropic.com>
|
🎉 This PR is included in version 1.8.0-beta.16 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
|
🎉 This PR is included in version 1.8.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
client/src/styles/tokens.css— a new 3-layer design token systemclient/src/styles/index.cssto importtokens.cssfirst and use semantic tokens onbodyNo
.module.cssfiles are touched — zero visual change to the running application.Quality Gates
npm run lint— passednpm run format:check— passednpm run typecheck— passednpm test— 1072 tests, 53 suites, all passednpm run build— pre-existing sandbox webpack error (schema-utils AJV conflict, unrelated to these changes; confirmed by reverting and re-running)Closes #116
🤖 Generated with Claude Code