Enforce single source of truth for all future color work: - All DESIGN.md color changes → frontend/colors.mjs exclusively - No direct edits to tailwind.config.ts or globals.css - Build script auto-syncs all systems - Added mandatory rule sections to: - CLAUDE.md (entry point for all AI agents) - DESIGN_COLOR_RULES.md (enforcement details) Prevents: - Color duplication across files - Sync inconsistencies - Manual CSS variable maintenance References COLOR_SYSTEM_ARCHITECTURE.md for implementation. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
10 KiB
Design System Color Rules - MANDATORY FOR ALL UI/UX
Status: ACTIVE | Effective: 2026-04-25
Owner: AI Development Team | Audience: All Frontend Developers/AI Agents
⚠️ CRITICAL RULE: No hardcoded Tailwind colors are permitted. All UI colors MUST come from
DESIGN.mdcolor system via tailwind.config.ts or globals.css.
THE RULE
NEVER use arbitrary Tailwind colors like:
- ❌
bg-green-500,text-green-400 - ❌
bg-red-600,text-rose-500 - ❌
bg-blue-500,text-indigo-400 - ❌
bg-amber-500,bg-yellow-400 - ❌
bg-sky-500,text-cyan-400 - ❌ Any other standard Tailwind color names
ALWAYS use semantic colors from DESIGN.md:
- ✅
bg-primary,text-primary - ✅
bg-secondary,text-secondary - ✅
bg-tertiary,text-tertiary(for success/healthy states) - ✅
bg-error,text-error - ✅
bg-success,text-success - ✅
bg-warning,text-warning - ✅
bg-muted,text-muted - ✅
border-outline,border-outline-variant
SEMANTIC COLOR MAPPING
Use these mappings for ALL UI decisions:
Status Indicators
| Intent | Color | Value | Use Case |
|---|---|---|---|
| ✅ Success / Healthy | tertiary |
#00e639 | "Scanner Ready", quantity +, check-in, online status |
| ❌ Error / Destructive | error |
#ffb4ab | "Delete item", errors, low stock, offline |
| ⚠️ Warning / Caution | primary |
#ffb781 | "Caution Orange", warnings, important actions |
| ℹ️ Info / Secondary | secondary |
#c8c6c5 | Secondary actions, hints, disabled text |
| 🔇 Muted / Disabled | muted |
#474746 | Disabled buttons, placeholder text |
Action Elements
| Element | Color | Example |
|---|---|---|
| Primary Button | bg-primary |
"Extract Data", "Create", "Upload" |
| Secondary Button | bg-secondary |
"Cancel", alternative actions |
| Destructive Button | bg-error |
"Delete Item", "Discard", "Remove" |
| Button Hover | hover:opacity-80 |
Darken any button on hover |
| Button Focus Ring | focus:ring-{color} |
Use same color as button |
Data Visualization
| Data Type | Color | Context |
|---|---|---|
| Quantity Increased | text-tertiary |
Stock added, items received |
| Quantity Decreased | text-error |
Stock removed, items shipped |
| Neutral Change | text-primary/50 |
Muted primary |
| Negative Status | text-error |
Low stock, missing items |
| Positive Status | text-tertiary |
Available, in stock |
Action Log Colors
| Action Type | Color | Rationale |
|---|---|---|
| CHECK_IN (receive) | tertiary |
Success/positive action |
| DELETE | error |
Destructive action |
| TRASH/DISCARD | error |
Destructive action |
| CREATE | primary |
Primary/caution action |
| DB (database) | secondary |
System/info action |
| REMOVE | primary |
Warning/caution |
TECHNICAL IMPLEMENTATION
✅ CORRECT Examples
// Status indicator - success
<div className="w-2 h-2 bg-tertiary animate-pulse" />
<span className="text-tertiary">Scanner: Ready</span>
// Destructive button
<button className="bg-error hover:opacity-80 focus:ring-error">
Delete Item
</button>
// Data change - quantity increased
<span className={log.quantity_change > 0 ? "text-tertiary" : "text-error"}>
{log.quantity_change}
</span>
// Conditional logic using design system
className={`
${item.quantity <= minQty ? "text-error" : "text-primary"}
${isOnline ? "bg-tertiary" : "bg-error"}
focus:ring-${isDestructive ? "error" : "primary"}
`}
// From globals.css variables
const statusColor = {
"success": "var(--tertiary)",
"error": "var(--error)",
"warning": "var(--primary)"
}
❌ WRONG Examples (DO NOT USE)
// ❌ Hardcoded arbitrary colors
<div className="w-2 h-2 bg-green-500 animate-pulse" />
<button className="bg-red-600 hover:bg-red-700">Delete</button>
// ❌ Arbitrary Tailwind color names
className="text-amber-500 bg-indigo-500/10 border border-rose-500/20"
// ❌ Hex colors in className
className="bg-[#4b0082] text-[#ff6b6b]"
// ❌ Mixing design system with arbitrary colors
className="bg-primary hover:bg-green-500 text-error"
COLOR AVAILABILITY IN TAILWIND
All DESIGN.md colors are available in tailwind.config.ts:
// frontend/tailwind.config.ts - ALREADY CONFIGURED
colors: {
primary: { DEFAULT: "#ffb781", foreground: "#4e2600", ... },
secondary: { DEFAULT: "#c8c6c5", foreground: "#303030", ... },
tertiary: { DEFAULT: "#00e639", foreground: "#003907", ... },
error: { DEFAULT: "#ffb4ab", foreground: "#690005", ... },
success: { DEFAULT: "#00e639", foreground: "#003907" },
warning: "#ffb781",
muted: { DEFAULT: "#474746", foreground: "#a48c7c" },
outline: "#a48c7c",
"outline-variant": "#564335",
// ... all surface, border, background colors
}
CSS VARIABLES (globals.css)
For custom CSS or dynamic color assignment:
/* All available in :root */
--primary: #ffb781;
--secondary: #c8c6c5;
--tertiary: #00e639;
--error: #ffb4ab;
--on-error: #690005;
--error-container: #93000a;
--on-error-container: #ffdad6;
--muted: #474746;
--outline: #a48c7c;
--outline-variant: #564335;
/* ... 50+ more */
// Usage in React
const statusColor = `var(--${isError ? 'error' : 'tertiary'})`
<div style={{ color: statusColor }} />
ENFORCEMENT RULES FOR AI AGENTS
BEFORE writing any color-related code:
- ✅ Check DESIGN.md for the semantic intent
- ✅ Map intent to color using the Semantic Color Mapping table above
- ✅ Use design system color from tailwind.config.ts
- ✅ Reference this file if uncertain about color choice
- ❌ Never use
bg-green,text-red,border-blue, etc.
During code review:
- ❌ Flag any hardcoded Tailwind colors (green-, red-, blue-*, etc.)
- ✅ Require fixes before merge
🔒 MANDATORY: All Color Definition Changes → frontend/colors.mjs ONLY
SINGLE SOURCE OF TRUTH RULE (Updated 2026-04-25):
When adding, updating, or modifying ANY color from DESIGN.md:
✅ CORRECT WORKFLOW:
- Edit ONLY:
frontend/colors.mjs(the authoritative color source) - Update the color definition in the
colorsexport object - Run:
npm run buildornpm run dev - Build script AUTOMATICALLY:
- Generates CSS variables in
globals.css:root - Syncs with
tailwind.config.ts(which imports from colors.mjs) - Zero manual sync required
- Generates CSS variables in
❌ INCORRECT WORKFLOWS (DO NOT DO):
- ❌ Editing
tailwind.config.tscolor definitions directly - ❌ Manually adding CSS variables to
globals.css - ❌ Updating colors in multiple files
- ❌ Assuming changes in one file will propagate to another
Why This Matters:
| Before | After (colors.mjs SSOT) |
|---|---|
| 2 files to edit | 1 file (colors.mjs) |
| High sync risk | Zero sync risk |
| Manual duplication | Auto-generated |
| Easy to break | Build validates |
Example: Adding a New Color Variant
// ✅ CORRECT: Edit frontend/colors.mjs ONLY
export const colors = {
primary: {
DEFAULT: "#ffb781",
// ← Add new variant here
"subtle": "#f5c5a3", // ← NEW
},
};
// Then: npm run build
// Result: Automatic sync to all systems
Reference Documentation:
- CLAUDE.md — Mandatory rule entry point
- COLOR_SYSTEM_ARCHITECTURE.md — Technical implementation details
- colors.mjs — The authoritative source (keep comments updated)
- ✅ Reference DESIGN_COLOR_RULES.md in comments
For TypeScript/Linting:
Add to .eslintrc.json if possible:
{
"rules": {
"no-restricted-syntax": [
"error",
{
"selector": "CallExpression[callee.name='className'][arguments.0.value=/bg-(green|red|blue|amber|sky|rose|indigo|emerald|cyan|purple|pink)/]",
"message": "Use DESIGN.md colors (primary, secondary, tertiary, error) instead of arbitrary Tailwind colors"
}
]
}
}
EXCEPTION CASES (VERY RARE)
Only use arbitrary colors for:
- Third-party libraries (e.g., vitest UI, dev tools) - in node_modules only
- Debug/Development tools - prefixed with
// debug-only - Dynamic user themes - explicitly documented with reason
If you encounter a design need NOT covered by DESIGN.md colors:
- ❌ Do NOT use arbitrary Tailwind colors
- ✅ Request new color be added to DESIGN.md
- ✅ Create GitHub issue with screenshot and use case
- ✅ Await approval before implementing
CHECKLIST FOR NEW FEATURES
Before writing UI code, answer:
- Have I read DESIGN.md colors section?
- Have I reviewed the Semantic Color Mapping in this file?
- Have I identified the intent: success/error/warning/info?
- Have I used the correct semantic color from design system?
- Have I avoided ALL arbitrary Tailwind colors (green-, red-, etc.)?
- Have I tested the color contrast meets WCAG AA (7:1 ratio)?
- Have I verified the color looks correct on both light and dark surfaces?
QUICK REFERENCE
If you need to color something:
Status = Success/Healthy? → Use tertiary (#00e639)
Status = Error/Failed? → Use error (#ffb4ab)
Action = Warning/Caution? → Use primary (#ffb781)
Action = Secondary/Info? → Use secondary (#c8c6c5)
Text = Muted/Disabled? → Use muted (#474746)
Border = Regular? → Use outline (#a48c7c)
Border = Subtle variant? → Use outline-variant (#564335)
Data change = Increase/Positive? → Use tertiary
Data change = Decrease/Negative? → Use error
RELATED DOCUMENTS
- 📋 DESIGN.md - Full color palette, typography, spacing rules
- 📋 DESIGN_COMPLIANCE_FIX_PLAN.md - Detailed fix plan for all hardcoded colors
- 📋 AI_RULES.md - Section 3: UI/UX Premium Fidelity Standards
- 📋 PROJECT_ARCHITECTURE.md - Section 2.2: Styling specification
VERSION HISTORY
| Date | Change | Author |
|---|---|---|
| 2026-04-25 | Created rule document | AI Development Team |
| 2026-04-25 | Fixed 44+ hardcoded colors | Phase 8 Remediation |
Last Reviewed: 2026-04-25
Next Review: 2026-05-25
Owner: AI Development Team