# 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 100–900) - **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.2–1.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 (5–10% 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