Files
boc/docs/design/LANDVEX_DESIGN_SPECIFICATION.md
T
Bernt 22be1efcd4 docs: Typography v1 + Foundation Colors + Anti-Patterns
- LANDVEX_DESIGN_SPECIFICATION.md:
  - Typography v1 (chapter 3): Inter + JetBrains Mono, type scale,
    heading hierarchy, line height rules, letter spacing, max line length,
    tabular figures, numerical typography
  - Foundation Colors (chapter 4.1): 12-step neutral palette (neutral-0 to neutral-1000)
  - Semantic Colors (chapter 4.2): surface, text, border mappings
  - Brand Palette (chapter 4.3): placeholder for brand colors
  - Semantic Status Colors (chapter 4.4): green, yellow, red, blue
  - Map Layer Palette (chapter 4.6): dedicated geospatial palette
  - Updated primitive references from gray-* to neutral-*

- DESIGN_ANTI_PATTERNS.md (v1.0, LOCKED):
  - 19 anti-patterns across 5 categories: visual, technical, interaction,
    content, AI-specific
  - Each with: forbidden description, rationale, alternative
  - AI-specific rules: no hardcoded values, no invented components,
    no skipping token lifecycle

Rationale: Typography before colors (harder to change). Neutral palette
before brand (90% of surface area). Anti-patterns prevent recurring
mistakes and guide AI agents.
2026-07-02 08:42:55 +00:00

740 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# LANDVEX DESIGN SPECIFICATION
**Technical Contract Between UX, UI, Frontend, AI Agents, QA, and Codebase**
| | |
|---|---|
| **Version** | 1.0-skeleton |
| **Status** | DRAFT — Under utveckling |
| **Scope** | Landvex Enterprise Platform |
| **Authority** | DESIGN_SPECIFICATION (nivå 5 i dokumenthierarkin) |
| **Parent** | `LANDVEX_DESIGN_CONSTITUTION.md` |
---
## PART A — GOVERNANCE
## 0. Token Philosophy
See `TOKEN_PHILOSOPHY.md` for the complete token governance rules.
**Quick Reference:**
- Three levels: Primitive → Semantic → Component
- Semantic first, primitive only when necessary
- DTCG JSON as canonical format
- Semantic versioning for token changes
- Deprecation policy: mark, maintain 2 versions, then remove
- Token lifecycle: Draft → Experimental → Stable → Deprecated → Removed
- Design Review Gate required before new token creation
---
> **Om detta dokument**
> Detta är ett levande kontrakt. Varje kapitel fylls på successivt.
> Ingen implementation får bryta mot en specificerad regel.
> Ospecificerade områden är fria att utforskas, men bör dokumenteras här när de stabiliseras.
---
## Innehållsförteckning
### PART A — GOVERNANCE
0. [Token Philosophy](#0-token-philosophy)
### PART B — TOKENS
1. [Design Tokens](#1-design-tokens)
- 1.1 Primitive Tokens
- 1.2 Semantic Tokens
- 1.3 Component Tokens
2. [Layout System](#2-layout-system)
3. [Typography](#3-typography)
4. [Color System](#4-color-system)
5. [Motion System](#5-motion-system)
6. [Elevation & Shadows](#6-elevation--shadows)
7. [Iconography](#7-iconography)
### PART C — COMPONENTS
8. [Components](#8-components)
9. [Maps & Geospatial Layer](#9-maps--geospatial-layer)
10. [Accessibility](#10-accessibility)
11. [Responsive Behavior](#11-responsive-behavior)
12. [Empty States](#12-empty-states)
13. [Loading States](#13-loading-states)
14. [Error States](#14-error-states)
### PART D — VALIDATION
15. [Acceptance Criteria](#15-acceptance-criteria)
16. [Design QA](#16-design-qa)
17. [Visual Regression](#17-visual-regression)
18. [Release Checklist](#18-release-checklist)
---
## PART B — TOKENS
## 1. Design Tokens
> **Status:** ⏳ Ej påbörjad
> **Parent:** `TOKEN_PHILOSOPHY.md`
### 1.0 Token Architecture
All tokens follow the three-level hierarchy defined in `TOKEN_PHILOSOPHY.md`:
```
Level 1: Primitive Tokens → Raw values (numbers, colors, dimensions)
Level 2: Semantic Tokens → Purpose-driven (surface-primary, text-muted)
Level 3: Component Tokens → Component-specific (button-primary-bg-hover)
```
**Rule:** Components reference Level 2 (Semantic) by default. Level 3 (Component) only when component-specific override is required. Level 1 (Primitive) never directly from components.
### 1.1 Primitive Tokens
#### 1.1.1 Spacing Scale
| Token | Value | Usage |
|-------|-------|-------|
| `space-0` | 0px | — |
| `space-1` | 4px | Tight padding, icon gaps |
| `space-2` | 8px | Default element padding |
| `space-3` | 12px | Component internal spacing |
| `space-4` | 16px | Standard gap |
| `space-5` | 24px | Section spacing |
| `space-6` | 32px | Large section spacing |
| `space-7` | 48px | Page-level spacing |
| `space-8` | 64px | Major section breaks |
| `space-9` | 96px | Hero/page top |
#### 1.1.2 Border Radius
| Token | Value | Usage |
|-------|-------|-------|
| `radius-0` | 0px | Sharp edges (data tables, maps) |
| `radius-1` | 2px | Subtle rounding |
| `radius-2` | 4px | Default (buttons, inputs) |
| `radius-3` | 8px | Cards, panels |
| `radius-4` | 12px | Large cards, modals |
| `radius-full` | 9999px | Pills, avatars |
#### 1.1.3 Z-Index Scale
| Token | Value | Usage |
|-------|-------|-------|
| `z-base` | 0 | Default layer |
| `z-dropdown` | 100 | Dropdowns, popovers |
| `z-sticky` | 200 | Sticky headers |
| `z-modal` | 300 | Modals, dialogs |
| `z-tooltip` | 400 | Tooltips |
| `z-toast` | 500 | Notifications |
| `z-overlay` | 600 | Full-screen overlays |
#### 1.1.4 Opacity Scale
| Token | Value | Usage |
|-------|-------|-------|
| `opacity-0` | 0% | Hidden |
| `opacity-25` | 25% | Disabled text |
| `opacity-50` | 50% | Placeholder text |
| `opacity-75` | 75% | Secondary text |
| `opacity-100` | 100% | Primary content |
#### 1.1.5 Blur Scale
| Token | Value | Usage |
|-------|-------|-------|
| `blur-0` | 0px | No blur |
| `blur-sm` | 4px | Subtle backdrop |
| `blur-md` | 8px | Modal backdrop |
| `blur-lg` | 16px | Full-screen overlay |
#### 1.1.6 Border Width
| Token | Value | Usage |
|-------|-------|-------|
| `border-0` | 0px | No border |
| `border-1` | 1px | Default dividers |
| `border-2` | 2px | Focus rings, active states |
| `border-4` | 4px | Emphasis, errors |
### 1.2 Semantic Tokens
#### 1.2.1 Surface Colors
| Token | Primitive Reference | Usage |
|-------|---------------------|-------|
| `surface-primary` | `neutral-0` | Main background |
| `surface-secondary` | `neutral-50` | Card background |
| `surface-elevated` | `neutral-0` + shadow | Modal, popover |
| `surface-overlay` | `neutral-1000` @ 50% | Backdrop |
#### 1.2.2 Text Colors
| Token | Primitive Reference | Usage |
|-------|---------------------|-------|
| `text-primary` | `neutral-1000` | Headings, body |
| `text-secondary` | `neutral-600` | Captions, metadata |
| `text-muted` | `neutral-400` | Placeholders |
| `text-inverse` | `neutral-0` | On dark surfaces |
#### 1.2.3 Border Colors
| Token | Primitive Reference | Usage |
|-------|---------------------|-------|
| `border-default` | `neutral-200` | Dividers |
| `border-focus` | `brand-500` | Focus rings |
| `border-error` | `semantic-red-500` | Error states |
### 1.3 Component Tokens
#### 1.3.1 Button
| Token | Semantic Reference | Usage |
|-------|-------------------|-------|
| `button-primary-bg` | `surface-primary` | Default background |
| `button-primary-bg-hover` | `brand-600` | Hover state |
| `button-primary-text` | `text-inverse` | Label color |
#### 1.3.2 Data Grid
| Token | Semantic Reference | Usage |
|-------|-------------------|-------|
| `table-row-hover` | `neutral-50` | Hover highlight |
| `table-header-bg` | `neutral-100` | Header background |
### 1.4 Export Format
Canonical: DTCG JSON. Derived: CSS custom properties, Tailwind config, Swift, Kotlin.
See `TOKEN_PHILOSOPHY.md` §3 for full specification.
---
## 2. Layout System
> **Status:** ⏳ Ej påbörjad
### 2.1 Grid
### 2.2 Breakpoints
| Name | Width | Target |
|------|-------|--------|
| `xs` | 0px | Phone portrait |
| `sm` | 640px | Phone landscape |
| `md` | 768px | Tablet portrait |
| `lg` | 1024px | Tablet landscape / small desktop |
| `xl` | 1280px | Desktop |
| `2xl` | 1536px | Large desktop |
### 2.3 Container Widths
### 2.4 Sidebar / Panel System
---
## 3. Typography
> **Status:** ✅ Specified
> **Principle:** Typography is the foundation of information hierarchy. It must be readable, scannable, and calm.
### 3.1 Font Stack
| Role | Font | Fallback | Usage |
|------|------|----------|-------|
| **Primary** | Inter | system-ui, -apple-system, sans-serif | All UI text, headings, body |
| **Monospace** | JetBrains Mono | ui-monospace, SFMono-Regular, monospace | Data, code, coordinates, tabular figures |
**Rationale:** Inter is designed for screen readability at small sizes. JetBrains Mono distinguishes similar characters (0/O, 1/l/I) — critical for geodata.
### 3.2 Font Fallback Strategy
```css
/* Primary */
font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
/* Monospace */
font-family: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, monospace;
```
### 3.3 Variable Font
- **Inter:** Variable font enabled (weight 100900)
- **JetBrains Mono:** Static weights only (400, 500, 700)
- **Performance:** Subset to Latin Extended + Swedish characters
### 3.4 Type Scale
| Token | Size | Line Height | Weight | Letter Spacing | Usage |
|-------|------|-------------|--------|----------------|-------|
| `text-xs` | 12px | 16px | 400 | 0.01em | Captions, metadata, timestamps |
| `text-sm` | 14px | 20px | 400 | 0 | Body small, secondary text |
| `text-base` | 16px | 24px | 400 | 0 | Body, paragraphs |
| `text-lg` | 18px | 28px | 400 | -0.01em | Lead paragraph, emphasis |
| `text-xl` | 20px | 28px | 500 | -0.02em | Section headers, card titles |
| `text-2xl` | 24px | 32px | 500 | -0.02em | Page titles, modal headers |
| `text-3xl` | 30px | 36px | 600 | -0.02em | Major headings, dashboard titles |
| `text-4xl` | 36px | 40px | 600 | -0.03em | Hero titles, empty states |
### 3.5 Heading Hierarchy
| Level | Token | Weight | Usage |
|-------|-------|--------|-------|
| H1 | `text-4xl` | 600 | Page title, top-level view |
| H2 | `text-3xl` | 600 | Section title, dashboard panel |
| H3 | `text-2xl` | 500 | Card title, modal header |
| H4 | `text-xl` | 500 | Subsection, list header |
| H5 | `text-lg` | 400 | Label, group title |
| H6 | `text-base` | 500 | Small label, filter title |
### 3.6 Font Weights
| Token | Value | Usage |
|-------|-------|-------|
| `font-normal` | 400 | Body, descriptions |
| `font-medium` | 500 | Emphasis, labels, buttons |
| `font-semibold` | 600 | Headings, active states |
| `font-bold` | 700 | Strong emphasis, alerts |
### 3.7 Line Height Rules
| Context | Rule | Rationale |
|---------|------|-----------|
| Body text | 1.5× font size | Readability for long text |
| Headings | 1.21.3× font size | Tight, scannable |
| Data/numbers | 1.25× font size | Alignment in tables |
| Captions | 1.4× font size | Small text needs air |
### 3.8 Letter Spacing
| Context | Value | Rationale |
|---------|-------|-----------|
| Body | 0 | Natural reading |
| Headings | -0.02em | Tighter, more impactful |
| All-caps labels | 0.05em | Improves legibility |
| Captions | 0.01em | Slight openness |
### 3.9 Max Line Length
| Context | Max Width | Rationale |
|---------|-----------|-----------|
| Body text | 65ch | Optimal reading width |
| Data tables | none | Full width |
| Side panels | 45ch | Narrow column readability |
### 3.10 Monospace Usage
| Context | Font | Features |
|---------|------|----------|
| Coordinates | JetBrains Mono | Tabular figures, always |
| Financial data | JetBrains Mono | Tabular figures, decimal alignment |
| Code snippets | JetBrains Mono | Ligatures disabled |
| Timestamps | JetBrains Mono | Fixed width for alignment |
### 3.11 Tabular Figures
**Always enabled for:**
- Data tables
- Financial values
- Coordinates (lat/long)
- Timestamps
- IDs and reference numbers
```css
font-variant-numeric: tabular-nums;
```
### 3.12 Numerical Typography
| Rule | Value | Example |
|------|-------|---------|
| Decimal separator | `.` (period) | `123.45` |
| Thousands separator | ` ` (space) | `1 234 567` |
| Negative numbers | `-` prefix | `-456.78` |
| Percentage | No space before `%` | `42.5%` |
| Currency | Symbol before, space after | `$ 1 234.56` |
---
## 4. Color System
> **Status:** ✅ Foundation specified, Brand & Map pending
> **Principle:** Information dominates color. Color supports, never competes.
### 4.1 Foundation Colors (Neutral Palette)
**Primitive Tokens:**
| Token | Hex | Usage |
|-------|-----|-------|
| `neutral-0` | `#ffffff` | Pure white, highest elevation |
| `neutral-50` | `#f8f9fa` | Card backgrounds, hover states |
| `neutral-100` | `#f1f3f5` | Subtle backgrounds, table headers |
| `neutral-200` | `#e9ecef` | Borders, dividers |
| `neutral-300` | `#dee2e6` | Disabled backgrounds |
| `neutral-400` | `#ced4da` | Placeholder text, inactive icons |
| `neutral-500` | `#adb5bd` | Secondary text, muted elements |
| `neutral-600` | `#868e96` | Captions, metadata |
| `neutral-700` | `#495057` | Body text secondary |
| `neutral-800` | `#343a40` | Body text primary |
| `neutral-900` | `#212529` | Headings, primary text |
| `neutral-1000` | `#0f172a` | Deepest surfaces, overlays |
**Rationale:** 12-step scale provides sufficient granularity without excess. Based on open-source neutral scales (Open Color, Tailwind) for familiarity.
### 4.2 Semantic Colors
Derived from primitives, mapped to purpose:
| Token | Primitive | Usage |
|-------|-----------|-------|
| `surface-primary` | `neutral-0` | Main background |
| `surface-secondary` | `neutral-50` | Card background |
| `surface-tertiary` | `neutral-100` | Table header, subtle fill |
| `surface-overlay` | `neutral-1000` @ 50% | Modal backdrop |
| `text-primary` | `neutral-900` | Headings, body |
| `text-secondary` | `neutral-600` | Captions, metadata |
| `text-muted` | `neutral-400` | Placeholders, disabled |
| `text-inverse` | `neutral-0` | On dark surfaces |
| `border-default` | `neutral-200` | Dividers, outlines |
| `border-strong` | `neutral-300` | Focus states, active |
### 4.3 Brand Palette
> **Status:** ⏳ Pending brand definition
Landvex brand colors are used sparingly (510% of surface area).
| Token | Hex | Usage |
|-------|-----|-------|
| `brand-50` | — | Lightest tint |
| `brand-100` | — | Hover backgrounds |
| `brand-200` | — | Subtle highlights |
| `brand-300` | — | — |
| `brand-400` | — | — |
| `brand-500` | — | Primary action, links |
| `brand-600` | — | Hover state |
| `brand-700` | — | Active state |
| `brand-800` | — | — |
| `brand-900` | — | Deepest shade |
**Rule:** Brand colors never appear in data visualization or map layers.
### 4.4 Semantic Status Colors
| Token | Hex | Usage |
|-------|-----|-------|
| `semantic-green-500` | `#40c057` | Success, active, positive |
| `semantic-yellow-500` | `#fcc419` | Warning, pending, attention |
| `semantic-red-500` | `#fa5252` | Error, danger, negative |
| `semantic-blue-500` | `#339af0` | Info, neutral highlight |
### 4.5 Data Visualization Colors
> **Status:** ⏳ Pending data viz requirements
Separate palette for charts, graphs, KPIs. Must be:
- Colorblind-safe
- Distinguishable in monochrome
- Consistent across all data products
### 4.6 Map Layer Palette
> **Status:** ⏳ Pending Mapbox configuration
Dedicated palette for geospatial visualization:
| Layer | Token | Rationale |
|-------|-------|-----------|
| Map surface | `map-surface` | Subtle, non-competing |
| Terrain | `map-terrain` | Elevation indication |
| Roads | `map-road` | Hierarchy (motorway → path) |
| Water | `map-water` | Consistent with cartographic convention |
| Buildings | `map-building` | Subtle 3D effect |
| Administrative | `map-boundary` | Dashed, muted |
| Mission markers | `map-mission` | Brand color, high visibility |
| Heatmap | `map-heatmap` | Gradient from neutral to alert |
| Selection | `map-selection` | Clear, non-intrusive |
| Overlay | `map-overlay` | Contextual information |
**Principle:** Map colors must work in all lighting conditions and never compete with data overlays.
---
## 5. Motion System
> **Status:** ⏳ Ej påbörjad
### 5.1 Duration Scale
| Token | Value | Usage |
|-------|-------|-------|
| `duration-instant` | 0ms | No animation |
| `duration-fast` | 100ms | Hover states |
| `duration-normal` | 200ms | Standard transitions |
| `duration-slow` | 300ms | Page transitions |
| `duration-slower` | 500ms | Complex animations |
### 5.2 Easing Functions
| Token | Value | Usage |
|-------|-------|-------|
| `ease-linear` | linear | Continuous motion |
| `ease-in` | cubic-bezier(0.4, 0, 1, 1) | Exit animations |
| `ease-out` | cubic-bezier(0, 0, 0.2, 1) | Enter animations |
| `ease-in-out` | cubic-bezier(0.4, 0, 0.2, 1) | Standard |
| `ease-spring` | cubic-bezier(0.34, 1.56, 0.64, 1) | Playful interactions |
### 5.3 Motion Principles
---
## 6. Elevation & Shadows
> **Status:** ⏳ Ej påbörjad
### 6.1 Shadow Scale
### 6.2 Usage Rules
---
## 7. Iconography
> **Status:** ⏳ Ej påbörjad
### 7.1 Icon Set
### 7.2 Icon Sizes
### 7.3 Icon + Text Pairing
---
## PART C — COMPONENTS
## 8. Components
> **Status:** ⏳ Ej påbörjad
> **Princip:** Varje komponent har en egen specifikation med states, ARIA, keyboard, touch, animation och acceptance criteria.
### 8.1 Button
**States:**
- Default
- Hover
- Focus
- Pressed (Active)
- Loading
- Disabled
**Variants:**
- Primary
- Secondary
- Tertiary (Ghost)
- Danger
- Icon-only
**ARIA:**
- `role="button"`
- `aria-label` for icon-only
- `aria-disabled` for disabled
- `aria-busy` for loading
**Keyboard:**
- `Enter` / `Space` to activate
- `Tab` to focus
**Touch:**
- Min 44x44px touch target
- Active state on press
**Animation:**
- Hover: background-color 100ms ease-out
- Press: scale(0.98) 50ms
- Loading: spinner rotation 1s linear infinite
**Acceptance Criteria:**
- [ ] All states are visually distinct
- [ ] Focus ring is visible
- [ ] Loading state prevents double-submit
- [ ] Disabled state is not focusable
- [ ] Touch target meets 44px minimum
### 8.2 Input / Text Field
### 8.3 Select / Dropdown
### 8.4 Checkbox
### 8.5 Radio Button
### 8.6 Toggle / Switch
### 8.7 Card
### 8.8 Modal / Dialog
### 8.9 Toast / Notification
### 8.10 Tooltip
### 8.11 Data Table
### 8.12 Tabs
### 8.13 Navigation
### 8.14 Sidebar
### 8.15 Map Overlay
---
## 9. Maps & Geospatial Layer
> **Status:** ⏳ Ej påbörjad
### 9.1 Mapbox Configuration
### 9.2 Layer Styles
### 9.3 Interaction Patterns
### 9.4 Geometries & Coordinates Display
---
## 10. Accessibility
> **Status:** ⏳ Ej påbörjad
### 10.1 WCAG 2.1 AA Compliance
### 10.2 Keyboard Navigation
### 10.3 Screen Reader Support
### 10.4 Focus Management
### 10.5 Color Contrast
### 10.6 Reduced Motion
---
## 11. Responsive Behavior
> **Status:** ⏳ Ej påbörjad
### 11.1 Device Adaptive Principles
### 11.2 Phone (< 768px)
### 11.3 Tablet (768px - 1024px)
### 11.4 Desktop (> 1024px)
---
## 12. Empty States
> **Status:** ⏳ Ej påbörjad
### 12.1 Principles
### 12.2 Patterns by Context
---
## 13. Loading States
> **Status:** ⏳ Ej påbörjad
### 13.1 Skeleton Patterns
### 13.2 Progress Indicators
### 13.3 Stepped Loading
---
## 14. Error States
> **Status:** ⏳ Ej påbörjad
### 14.1 Error Message Structure
### 14.2 Inline Errors
### 14.3 Page-Level Errors
### 14.4 Toast Errors
---
## PART D — VALIDATION
## 15. Acceptance Criteria
> **Status:** ⏳ Ej påbörjad
### 15.1 Definition of Done (Design)
### 15.2 Checklist per Component
### 15.3 Cross-Browser Requirements
---
## 16. Design QA
> **Status:** ⏳ Ej påbörjad
### 16.1 Manual Review Process
### 16.2 Automated Checks (Future)
### 16.3 Screenshot Review
---
## 17. Visual Regression
> **Status:** ⏳ Ej påbörjad — Fas 3
### 17.1 Scope
### 17.2 Tools
### 17.3 Thresholds
---
## 18. Release Checklist
> **Status:** ⏳ Ej påbörjad
### 18.1 Pre-Release Design Review
### 18.2 Post-Release Verification
---
## ÄNDRINGSHISTORIA
| Version | Datum | Beskrivning |
|---------|-------|-------------|
| 1.0-skeleton | 2026-07-02 | Initial struktur med 18 kapitel, tomt innehåll |
---
## STATUS
**DRAFT — Under utveckling**
- Fyll på kapitel successivt
- Markera kapitel som ✅ när de är specificerade och godkända
- Brytande ändringar: Kräver Architecture Review