|
| 1 | +# gui/DESIGN.md — de ontwerptaal van het dashboard |
| 2 | + |
| 3 | +> De levende ontwerp- en smaakgids voor het opencodex-dashboard (`gui/`). |
| 4 | +> Dit is de ChefGroep-taal (v2 "Devin-richting"): een stil, warm, mat instrument. |
| 5 | +> Bron van waarheid voor de *taal*: [`OnlineChefGroep/design-system`](https://github.com/OnlineChefGroep/design-system) |
| 6 | +> (`tokens.css`, `DESIGN.md`, `motion-spec.md`). Dit bestand legt vast hoe die |
| 7 | +> taal in dít dashboard leeft, en — belangrijker — **hoe je 'm uitbreidt zonder |
| 8 | +> 'm te breken**. |
| 9 | +
|
| 10 | +Alles hier is gebouwd op tokens in `src/styles.css`. Verzin nooit losse |
| 11 | +px-waarden of kleuren in een component; gebruik een token. Zo blijft de hele |
| 12 | +app in één keer te herstemmen. |
| 13 | + |
| 14 | +--- |
| 15 | + |
| 16 | +## 1. De drie pijlers |
| 17 | + |
| 18 | +1. **Stil oppervlak.** Warm off-white, haarlijnen, plat. Geen glow, geen |
| 19 | + gradients, geen glasmorfisme, geen geneste schaduw. |
| 20 | +2. **Levende activiteit.** Werk toon je als rust of een golfje, nooit als |
| 21 | + ronddraaiende spinner. |
| 22 | +3. **Begrijpelijk.** Eén accent, één type-ladder, één set radii, één easing. |
| 23 | + Hiërarchie komt uit grootte/gewicht/kleur — niet uit decoratie. |
| 24 | + |
| 25 | +--- |
| 26 | + |
| 27 | +## 2. Kleur |
| 28 | + |
| 29 | +Eén accent: blauw (`--accent-blue`). Alles wat "klik mij / hier ben je / dit is |
| 30 | +aan" zegt is blauw: links, focus-ring, actieve nav, geselecteerde tab, toggles, |
| 31 | +selectie. De **primaire knop** blijft juist monochroom (tekst↔achtergrond |
| 32 | +omgekeerd) — dat is de shadcn-conventie, geen tweede accent. |
| 33 | + |
| 34 | +| Rol | Token | |
| 35 | +|---|---| |
| 36 | +| Achtergrond / rail / kaart | `--bg` · `--rail` · `--surface` · `--raised` | |
| 37 | +| Lijnen | `--border` (sterk) · `--border-soft` (hairline) | |
| 38 | +| Tekst | `--text` · `--muted` · `--faint` | |
| 39 | +| Primaire actie | `--accent` (+ `--accent-ink`) | |
| 40 | +| Het accent | `--accent-blue` · `--accent-blue-ink` · `--accent-soft` (ring/tint) | |
| 41 | +| Semantiek | `--green` (git/PR/toestemming) · `--amber` (wacht-op-jou) · `--red` (destructief) | |
| 42 | + |
| 43 | +Regels: groen/amber/rood zijn **gereserveerd**, nooit decoratie. Neutraal is |
| 44 | +warm, nooit koudgrijs. Dark mode is basalt-warm, geen zuiver zwart. Elke token |
| 45 | +is `light-dark(licht, donker)` — schrijf beide kanten, altijd. |
| 46 | + |
| 47 | +--- |
| 48 | + |
| 49 | +## 3. Typografie |
| 50 | + |
| 51 | +- **Archivo** (`--font-ui`) voor alles; **JetBrains Mono** (`--font-code`) |
| 52 | + uitsluitend voor machinedata (timers, model-id's, paden, diffs, tellers). |
| 53 | +- Eén type-ladder — gebruik de tokens, nooit losse px: |
| 54 | + |
| 55 | +| Token | px | Gebruik | |
| 56 | +|---|---|---| |
| 57 | +| `--text-micro` | 10.5 | meta, tellers, caps-labels | |
| 58 | +| `--text-caption` | 11.5 | labels, captions | |
| 59 | +| `--text-label` | 12.5 | secundair / beschrijvingen | |
| 60 | +| `--text-control` | 13.5 | **UI-standaard** (body van de app) | |
| 61 | +| `--text-body` | 14 | leestekst | |
| 62 | +| `--text-subtitle` | 16 | kleine titels | |
| 63 | +| `--text-section` | 18 | sectiekoppen | |
| 64 | +| `--text-title` | 22 | paginatitels | |
| 65 | +| `--text-display` | 28 | hero-getallen | |
| 66 | + |
| 67 | +- Koppen: gewicht 500, `letter-spacing: var(--tracking-tight)` (−0.02em), |
| 68 | + `text-wrap: balance`. Leading via `--leading-*` (tight 1.2 / ui 1.45 / |
| 69 | + body 1.55 / relaxed 1.65). |
| 70 | +- **Getallen lijnen uit**: alles wat een getal is krijgt `.num` of |
| 71 | + `font-variant-numeric: tabular-nums` (stat-waarden, quota, tellers, timers). |
| 72 | +- Utilities: `.num` (tabulaire cijfers), `.caps` (uppercase microlabel), |
| 73 | + `.prose` (68ch leesmaat). Componeer hiermee; verzin geen nieuwe. |
| 74 | + |
| 75 | +--- |
| 76 | + |
| 77 | +## 4. Motion |
| 78 | + |
| 79 | +Bewegen is transform + opacity, nooit `width/height/top/left`. Eén easing |
| 80 | +(`--ease-out`), duren `--motion-fast/normal/slow` (140/280/420ms). Alles settle-t |
| 81 | +vroeg, niets bounct, niets loopt oneindig. De vaste set: |
| 82 | + |
| 83 | +- **Intent-reveal:** één rustige rise per navigatie (`.main-inner > *`), niet |
| 84 | + per kaart. |
| 85 | +- **Press-physics:** `scale(0.97–0.98)` op knoppen, nav-rijen, tabs, chips, |
| 86 | + segments. Nooit op inputs, tekst of panelen. |
| 87 | +- **Modal:** scrim vervaagt in, kaart rijst en settle-t. |
| 88 | +- **Ripple i.p.v. spinner:** `.spin` is een kalm blauw golfje. |
| 89 | + |
| 90 | +`prefers-reduced-motion` zet **alles** uit met nul informatieverlies (globale |
| 91 | +guard in `styles.css`). Nieuwe animatie = tokenduur + één keyframe in het |
| 92 | +Motion-blok. Meer niet. |
| 93 | + |
| 94 | +--- |
| 95 | + |
| 96 | +## 5. Skins (`data-style`) |
| 97 | + |
| 98 | +Dezelfde taal draagt meerdere complete skins: |
| 99 | + |
| 100 | +- `devin` (default) — warm, zacht, ronder (`:root`). |
| 101 | +- `strak` — koeler grijs-blauw, scherpere radii. |
| 102 | + |
| 103 | +Zetten: `?style=strak` of een opgeslagen keuze (`localStorage` `ocx-style`), |
| 104 | +toegepast vóór eerste paint in `main.tsx`. Een nieuwe skin = één blok |
| 105 | +token-overrides in `styles.css` (light **én** dark). De taal (§1–§4) blijft |
| 106 | +onder elke skin gelden. |
| 107 | + |
| 108 | +--- |
| 109 | + |
| 110 | +## 5b. Taste-regels (overgenomen uit `design-system/taste/`) |
| 111 | + |
| 112 | +Bindend voor nieuw werk. Twee observaties minimum per regel (zie de bron). |
| 113 | + |
| 114 | +- **Kleur:** neutraal warm tinten, **één accent max**; licht is eersteklas |
| 115 | + standaard. Geen paarse gradients, AI-glow, acid-on-black. Het accent is voor |
| 116 | + links/focus/toggles/status — **niet** voor nav-selectie (die is een kalme |
| 117 | + `--raised`). |
| 118 | +- **Type:** Archivo/General Sans-humanist voor interface; mono **strikt** voor |
| 119 | + data. Nooit Inter/Geist/Space Grotesk of mono voor labels/prose. |
| 120 | +- **Motion:** vroeg settelen, lage amplitude/frequentie; **één** signatuur- |
| 121 | + systeem (de Stroom/ripple), geen verspreide micro-animaties. Geen bounce, |
| 122 | + elastic of oneindige ambient motion. |
| 123 | +- **Dichtheid:** compact, informatiedicht (dichtheid 5–7). `h28`/`r6` voor |
| 124 | + secundaire controls, `r10` voor kaarten. Geen marketing-witruimte in product. |
| 125 | +- **Stem:** warm, direct, menselijk Nederlands op Joep-vlakken. Geen em-dashes, |
| 126 | + buzzwords, lifecycle-jargon of verzonnen metrics. |
| 127 | +- **Structuur:** haarlijnen + ruimte voor scheiding. **Geen** kaart-in-kaart, |
| 128 | + bento-velden of geneste elevation. Tweebaans sidebar met vaste glyph-baan. |
| 129 | +- **Iconen:** echte SVG-lijniconen (Lucide/shadcn, ~1.75px stroke, 15–16px |
| 130 | + grid). Nooit emoji als icoon — nergens. |
| 131 | +- **Metafoor:** water/stroom voor systeemstatus; instrument-framing |
| 132 | + ("gezandstraald instrument"). Geen keuken/bon/brigade of corporate-dashboard. |
| 133 | + |
| 134 | +## 6. Bans (hard) |
| 135 | + |
| 136 | +- Geen spinners/loaders (ripple vervangt ze). |
| 137 | +- Geen emoji als icoon of in copy. Iconen zijn SVG-lijniconen (Lucide-stijl). |
| 138 | +- Geen em-dashes, buzzwords of verzonnen metrics in copy. |
| 139 | +- Geen gradients, glow, glasmorfisme, bento-kaartjes. |
| 140 | +- Geen kaart-in-kaart, geen geneste elevation. |
| 141 | +- Geen oneindige ambient motion. |
| 142 | + |
| 143 | +--- |
| 144 | + |
| 145 | +## 7. Zo breid je uit |
| 146 | + |
| 147 | +- **Nieuwe kleur/rol:** token toevoegen in `:root` mét `light-dark()`, en in |
| 148 | + élke skin (`[data-style="strak"]`). Nooit een losse hex in een component. |
| 149 | +- **Nieuwe component:** hergebruik `.btn`/`.badge`/`.input`/`.switch`/`.seg`, |
| 150 | + radii- en type-tokens. Haarlijn-border, rustige hover, press-physics als het |
| 151 | + klikbaar is. |
| 152 | +- **Nieuwe tekst:** géén hardgecodeerde UI-strings in `src/pages`/ |
| 153 | + `src/components` (zie `gui/AGENTS.md`). Zet de string in **alle** locale- |
| 154 | + bestanden (`src/i18n/*.ts`) en render met `useT()`. Draai `bun run lint:i18n`. |
| 155 | +- **Nieuwe motion:** tokenduur + keyframe in het Motion-blok; transform/opacity |
| 156 | + only; check `prefers-reduced-motion`. |
| 157 | +- **Controleren:** `bun run typecheck`, `bun --bun run lint:gui`, |
| 158 | + `bun run lint:i18n`, `bun run privacy:scan`. Zie `AGENTS.md`. |
0 commit comments