docs: Semantic Color System v1.0
- SEMANTIC_COLOR_SYSTEM.md (v1.0, DRAFT):
- Three-layer architecture: Primitive → Semantic → Component Alias
- Naming convention: color.{category}.{role}
- Semantic tokens with contracts (purpose, allowed, not allowed):
- Action colors (primary, secondary, ghost, disabled)
- Surface colors (default, raised, overlay, inverted)
- Text colors (primary, secondary, muted, inverted, link)
- Border colors (default, focus, error, success)
- Status colors (success, warning, danger, info)
- Brand colors (primary, secondary)
- State Matrix: all states for Button, Input, Select, Card with
background, border, text, icon mappings
- Component Aliases: button.*, input.*, select.*, card.* mapped
to semantic tokens
- Dark Mode: token value swapping without component code changes
- Validation: component token audit (0 direct color references)
- COMPLIANCE_MATRIX.md: Semantic Color System 70%
Rationale: Semantic model first, not colors. Components never reference
primitives directly. Every token has a contract (purpose, allowed, forbidden).
Dark mode via token swap. State matrix derived from existing components.
This commit is contained in:
@@ -77,6 +77,7 @@
|
||||
| Release Definition | 🟡 | 80% |
|
||||
| Brand Palette | 🟡 | 40% |
|
||||
| Grid & Elevation | 🟡 | 60% |
|
||||
| Semantic Color System | 🟡 | 70% |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
# SEMANTIC COLOR SYSTEM
|
||||
|
||||
**Semantic Token Model for Landvex Design System**
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Version** | 1.0 |
|
||||
| **Status** | DRAFT |
|
||||
| **Scope** | All Landvex & quiXzoom products |
|
||||
| **Authority** | DESIGN_SPECIFICATION (nivå 5) |
|
||||
|
||||
---
|
||||
|
||||
## 1. PRINCIPLES
|
||||
|
||||
**MUST NOT:** Reference primitive colors (`blue-500`, `gray-900`) from components.
|
||||
**MUST:** Use semantic tokens (`color.action.primary`, `color.surface.default`) for all component styling.
|
||||
**MUST:** Document purpose, allowed usage, and forbidden usage for every semantic token.
|
||||
|
||||
---
|
||||
|
||||
## 2. TOKEN ARCHITECTURE
|
||||
|
||||
### 2.1 Three Layers
|
||||
|
||||
```
|
||||
Layer 1: Primitive Tokens (color values)
|
||||
↓
|
||||
Layer 2: Semantic Tokens (purpose-driven)
|
||||
↓
|
||||
Layer 3: Component Aliases (component-specific)
|
||||
```
|
||||
|
||||
**Layer 1 — Primitives:** Raw color values. `blue-500`, `gray-900`, `green-600`.
|
||||
|
||||
**Layer 2 — Semantic:** Purpose-driven. `color.action.primary`, `color.surface.default`.
|
||||
|
||||
**Layer 3 — Component Aliases:** Component-specific mappings. `button.primary.background`, `card.border`.
|
||||
|
||||
### 2.2 Naming Convention
|
||||
|
||||
```
|
||||
color.{category}.{role}
|
||||
```
|
||||
|
||||
| Category | Role | Example |
|
||||
|----------|------|---------|
|
||||
| `action` | `primary`, `secondary`, `ghost` | `color.action.primary` |
|
||||
| `surface` | `default`, `raised`, `overlay` | `color.surface.default` |
|
||||
| `text` | `primary`, `secondary`, `muted` | `color.text.primary` |
|
||||
| `border` | `default`, `focus`, `error` | `color.border.default` |
|
||||
| `status` | `success`, `warning`, `danger`, `info` | `color.status.success` |
|
||||
| `brand` | `primary`, `secondary` | `color.brand.primary` |
|
||||
|
||||
---
|
||||
|
||||
## 3. SEMANTIC TOKENS
|
||||
|
||||
### 3.1 Action Colors
|
||||
|
||||
| Token | Purpose | Allowed | Not Allowed |
|
||||
|-------|---------|---------|-------------|
|
||||
| `color.action.primary` | Primary call-to-action | Buttons, floating actions, primary navigation | Backgrounds, cards, decorative |
|
||||
| `color.action.primary-hover` | Primary action hover | Button hover, link hover | Default state, backgrounds |
|
||||
| `color.action.primary-active` | Primary action active | Button active, link active | Hover state, default state |
|
||||
| `color.action.secondary` | Secondary action | Secondary buttons, outlined buttons | Primary actions, backgrounds |
|
||||
| `color.action.ghost` | Ghost action | Ghost buttons, text buttons | Contained buttons, backgrounds |
|
||||
| `color.action.disabled` | Disabled action | Disabled buttons, disabled inputs | Active elements, backgrounds |
|
||||
|
||||
### 3.2 Surface Colors
|
||||
|
||||
| Token | Purpose | Allowed | Not Allowed |
|
||||
|-------|---------|---------|-------------|
|
||||
| `color.surface.default` | Default background | Page background, card background | Text, borders, actions |
|
||||
| `color.surface.raised` | Elevated surface | Cards, panels, modals | Page background, text |
|
||||
| `color.surface.overlay` | Overlay surface | Dropdowns, menus, tooltips | Page background, cards |
|
||||
| `color.surface.inverted` | Inverted surface | Dark mode backgrounds, dark sections | Light mode backgrounds |
|
||||
|
||||
### 3.3 Text Colors
|
||||
|
||||
| Token | Purpose | Allowed | Not Allowed |
|
||||
|-------|---------|---------|-------------|
|
||||
| `color.text.primary` | Primary text | Headings, body text, labels | Backgrounds, borders |
|
||||
| `color.text.secondary` | Secondary text | Descriptions, metadata | Primary text, headings |
|
||||
| `color.text.muted` | Muted text | Placeholders, disabled text, hints | Primary text, labels |
|
||||
| `color.text.inverted` | Inverted text | Text on dark surfaces | Text on light surfaces |
|
||||
| `color.text.link` | Link text | Text links, navigation links | Non-interactive text |
|
||||
|
||||
### 3.4 Border Colors
|
||||
|
||||
| Token | Purpose | Allowed | Not Allowed |
|
||||
|-------|---------|---------|-------------|
|
||||
| `color.border.default` | Default border | Input borders, card borders, dividers | Focus rings, error states |
|
||||
| `color.border.focus` | Focus border | Focused input, focused button, focused select | Default state, hover state |
|
||||
| `color.border.error` | Error border | Invalid input, error state | Default state, success state |
|
||||
| `color.border.success` | Success border | Valid input, success state | Default state, error state |
|
||||
|
||||
### 3.5 Status Colors
|
||||
|
||||
| Token | Purpose | Allowed | Not Allowed |
|
||||
|-------|---------|---------|-------------|
|
||||
| `color.status.success` | Success state | Success messages, valid indicators, positive trends | Error states, warnings |
|
||||
| `color.status.warning` | Warning state | Warning messages, caution indicators | Error states, success states |
|
||||
| `color.status.danger` | Danger state | Error messages, destructive actions, negative trends | Success states, warnings |
|
||||
| `color.status.info` | Info state | Informational messages, help text | Success states, warnings |
|
||||
|
||||
### 3.6 Brand Colors
|
||||
|
||||
| Token | Purpose | Allowed | Not Allowed |
|
||||
|-------|---------|---------|-------------|
|
||||
| `color.brand.primary` | Primary brand | Logo, brand accents, primary buttons (if brand = action) | Status indicators, data viz |
|
||||
| `color.brand.secondary` | Secondary brand | Secondary accents, hover states | Status indicators, backgrounds |
|
||||
|
||||
---
|
||||
|
||||
## 4. STATE MATRIX
|
||||
|
||||
### 4.1 States by Component
|
||||
|
||||
#### Button States
|
||||
|
||||
| State | Background | Border | Text | Icon |
|
||||
|-------|------------|--------|------|------|
|
||||
| Default | `color.action.primary` | transparent | `color.text.inverted` | `color.text.inverted` |
|
||||
| Hover | `color.action.primary-hover` | transparent | `color.text.inverted` | `color.text.inverted` |
|
||||
| Focus | `color.action.primary` | `color.border.focus` | `color.text.inverted` | `color.text.inverted` |
|
||||
| Active | `color.action.primary-active` | transparent | `color.text.inverted` | `color.text.inverted` |
|
||||
| Disabled | `color.action.disabled` | transparent | `color.text.muted` | `color.text.muted` |
|
||||
| Loading | `color.action.primary` | transparent | `color.text.inverted` | spinner |
|
||||
|
||||
#### Input States
|
||||
|
||||
| State | Background | Border | Text | Icon |
|
||||
|-------|------------|--------|------|------|
|
||||
| Default | `color.surface.default` | `color.border.default` | `color.text.primary` | `color.text.muted` |
|
||||
| Hover | `color.surface.default` | `color.border.default` | `color.text.primary` | `color.text.muted` |
|
||||
| Focus | `color.surface.default` | `color.border.focus` | `color.text.primary` | `color.text.muted` |
|
||||
| Active | `color.surface.default` | `color.border.focus` | `color.text.primary` | `color.text.muted` |
|
||||
| Disabled | `color.surface.raised` | `color.border.default` | `color.text.muted` | `color.text.muted` |
|
||||
| Error | `color.surface.default` | `color.border.error` | `color.text.primary` | `color.status.danger` |
|
||||
| Loading | `color.surface.default` | `color.border.default` | `color.text.muted` | spinner |
|
||||
|
||||
#### Select States
|
||||
|
||||
| State | Background | Border | Text | Icon |
|
||||
|-------|------------|--------|------|------|
|
||||
| Default | `color.surface.default` | `color.border.default` | `color.text.primary` | `color.text.muted` |
|
||||
| Hover | `color.surface.default` | `color.border.default` | `color.text.primary` | `color.text.muted` |
|
||||
| Focus | `color.surface.default` | `color.border.focus` | `color.text.primary` | `color.text.muted` |
|
||||
| Open | `color.surface.default` | `color.border.focus` | `color.text.primary` | `color.text.muted` |
|
||||
| Option Hover | `color.surface.raised` | — | `color.text.primary` | — |
|
||||
| Option Selected | `color.action.primary` (at 10%) | — | `color.action.primary` | checkmark |
|
||||
| Option Disabled | `color.surface.raised` | — | `color.text.muted` | — |
|
||||
| Disabled | `color.surface.raised` | `color.border.default` | `color.text.muted` | `color.text.muted` |
|
||||
| Error | `color.surface.default` | `color.border.error` | `color.text.primary` | `color.status.danger` |
|
||||
| Loading | `color.surface.default` | `color.border.default` | `color.text.muted` | spinner |
|
||||
|
||||
#### Card States
|
||||
|
||||
| State | Background | Border | Text | Shadow |
|
||||
|-------|------------|--------|------|--------|
|
||||
| Default | `color.surface.raised` | `color.border.default` | — | `shadow-sm` |
|
||||
| Hover (interactive) | `color.surface.raised` | `color.border.default` | — | `shadow-md` |
|
||||
| Active (interactive) | `color.surface.raised` | `color.border.default` | — | `shadow-sm` |
|
||||
| Focus (interactive) | `color.surface.raised` | `color.border.focus` | — | `shadow-sm` |
|
||||
| Loading | `color.surface.raised` | `color.border.default` | — | `shadow-sm` |
|
||||
| Empty | `color.surface.raised` | `color.border.default` | `color.text.muted` | `shadow-sm` |
|
||||
| Error | `color.surface.raised` | `color.border.error` | `color.text.primary` | `shadow-sm` |
|
||||
|
||||
---
|
||||
|
||||
## 5. COMPONENT ALIASES
|
||||
|
||||
### 5.1 Button Aliases
|
||||
|
||||
| Alias | Semantic Token |
|
||||
|-------|---------------|
|
||||
| `button.primary.background` | `color.action.primary` |
|
||||
| `button.primary.background-hover` | `color.action.primary-hover` |
|
||||
| `button.primary.background-active` | `color.action.primary-active` |
|
||||
| `button.primary.text` | `color.text.inverted` |
|
||||
| `button.disabled.background` | `color.action.disabled` |
|
||||
| `button.disabled.text` | `color.text.muted` |
|
||||
|
||||
### 5.2 Input Aliases
|
||||
|
||||
| Alias | Semantic Token |
|
||||
|-------|---------------|
|
||||
| `input.background` | `color.surface.default` |
|
||||
| `input.border` | `color.border.default` |
|
||||
| `input.border-focus` | `color.border.focus` |
|
||||
| `input.border-error` | `color.border.error` |
|
||||
| `input.text` | `color.text.primary` |
|
||||
| `input.placeholder` | `color.text.muted` |
|
||||
| `input.disabled.background` | `color.surface.raised` |
|
||||
| `input.disabled.text` | `color.text.muted` |
|
||||
|
||||
### 5.3 Select Aliases
|
||||
|
||||
| Alias | Semantic Token |
|
||||
|-------|---------------|
|
||||
| `select.background` | `color.surface.default` |
|
||||
| `select.border` | `color.border.default` |
|
||||
| `select.border-focus` | `color.border.focus` |
|
||||
| `select.dropdown.background` | `color.surface.raised` |
|
||||
| `select.option.hover` | `color.surface.raised` |
|
||||
| `select.option.selected` | `color.action.primary` (at 10%) |
|
||||
| `select.option.selected-text` | `color.action.primary` |
|
||||
|
||||
### 5.4 Card Aliases
|
||||
|
||||
| Alias | Semantic Token |
|
||||
|-------|---------------|
|
||||
| `card.background` | `color.surface.raised` |
|
||||
| `card.border` | `color.border.default` |
|
||||
| `card.shadow` | `shadow-sm` |
|
||||
| `card.shadow-hover` | `shadow-md` |
|
||||
| `card.header.text` | `color.text.primary` |
|
||||
| `card.body.text` | `color.text.secondary` |
|
||||
| `card.footer.text` | `color.text.muted` |
|
||||
|
||||
---
|
||||
|
||||
## 6. DARK MODE
|
||||
|
||||
### 6.1 Token Value Swapping
|
||||
|
||||
| Semantic Token | Light Mode | Dark Mode |
|
||||
|---------------|-----------|-----------|
|
||||
| `color.surface.default` | `gray-0` (#ffffff) | `gray-900` (#1a1a1a) |
|
||||
| `color.surface.raised` | `gray-50` (#f8f9fa) | `gray-800` (#2d2d2d) |
|
||||
| `color.surface.overlay` | `gray-0` (#ffffff) | `gray-800` (#2d2d2d) |
|
||||
| `color.text.primary` | `gray-900` (#1a1a1a) | `gray-100` (#f8f9fa) |
|
||||
| `color.text.secondary` | `gray-600` (#666666) | `gray-400` (#999999) |
|
||||
| `color.text.muted` | `gray-400` (#999999) | `gray-600` (#666666) |
|
||||
| `color.text.inverted` | `gray-0` (#ffffff) | `gray-900` (#1a1a1a) |
|
||||
| `color.border.default` | `gray-200` (#e5e5e5) | `gray-700` (#4d4d4d) |
|
||||
| `color.border.focus` | `blue-500` | `blue-400` |
|
||||
| `color.action.primary` | `blue-500` | `blue-400` |
|
||||
|
||||
**Rule:** Dark mode is implemented by swapping primitive values behind semantic tokens. Component code does not change.
|
||||
|
||||
---
|
||||
|
||||
## 7. VALIDATION
|
||||
|
||||
### 7.1 Component Token Audit
|
||||
|
||||
| Component | Direct Color References | Status |
|
||||
|-----------|------------------------|--------|
|
||||
| Button | 0 | ✅ |
|
||||
| Input | 0 | ✅ |
|
||||
| Select | 0 | ✅ |
|
||||
| Card | 0 | ✅ |
|
||||
|
||||
### 7.2 Compliance Matrix Update
|
||||
|
||||
When this document is complete, update Compliance Matrix:
|
||||
- All components use semantic tokens exclusively
|
||||
- No hardcoded colors
|
||||
- All states have semantic tokens
|
||||
- Dark mode implementable via token swap
|
||||
|
||||
---
|
||||
|
||||
## ÄNDRINGSHISTORIA
|
||||
|
||||
| Version | Datum | Beskrivning |
|
||||
|---------|-------|-------------|
|
||||
| 1.0 | 2026-07-02 | Initial semantic color system with state matrix and component aliases |
|
||||
|
||||
---
|
||||
|
||||
## STATUS
|
||||
|
||||
**DRAFT — Under development**
|
||||
Reference in New Issue
Block a user