diff --git a/PLAN.md b/PLAN.md new file mode 100644 index 000000000..cbb5cd6c9 --- /dev/null +++ b/PLAN.md @@ -0,0 +1,279 @@ +# PLAN.md — Redesign van het opencodex-dashboard naar het ChefGroep design-system + +> Werkdocument voor de herinrichting van de `gui/`-dashboard van opencodex naar +> de design-taal van [`OnlineChefGroep/design-system`](https://github.com/OnlineChefGroep/design-system) +> (v2 "Devin-richting"), in de Nederlandse "De Pas"-stem die al in +> `gui/src/i18n/nl.ts` is begonnen. +> +> Dit plan beschrijft wat er verandert, in welke volgorde, met welke risico's en +> hoe we per fase bewijzen dat het werkt. Code volgt pas na akkoord op de scope. + +--- + +## 1. Doel + +Het opencodex-dashboard krijgt de ChefGroep-huisstijl: **warm off-white, één +blauw accent, shadcn-componenten, Lucide-iconen, golfjes in plaats van spinners, +Nederlandse copy**, met light én dark als gelijkwaardige eersteklas thema's. + +Eén zin: *een stil, warm, mat instrument dat toont wat er gebeurt terwijl het +gebeurt* (`design-system/DESIGN.md` §1). + +Niet-doelen: de proxy-runtime (`src/`), de API-contracten, de i18n-architectuur +of de routing veranderen niet. Dit is puur een presentatie-laag. + +--- + +## 2. Twee design-systemen naast elkaar + +### 2.1 Wat er nu staat (opencodex `gui/`) + +Het dashboard heeft al een volwassen, eigen design-system, vastgelegd bovenin +`gui/src/styles.css` (1334 regels) plus ~10 per-surface CSS-bestanden: + +- **Grammatica:** OpenAI-producttaal — monochroom wit / bijna-zwart, zwarte + (light) of witte (dark) primaire acties, pill-knoppen, haarlijn-borders, + platte oppervlakken, mono voor model-id's en URL's. +- **Thema:** light + dark via de native `light-dark()`-functie; elke token wordt + één keer geschreven, `data-theme` (of de OS) kiest de kant. +- **Tokens:** volledige set custom properties — `--bg`, `--rail`, `--surface`, + `--raised`, `--border`, `--text`/`--muted`/`--faint`, `--accent` + (monochroom!), `--green`/`--red`/`--amber` (+ `-soft`), een 4px-spacing-grid, + radii `--radius-*`, typografie-schaal `--text-*`, gewichten, control-maten, + icon-maten, `--motion-fast/normal`, schaduwen, **glass**-tokens en + toggle-tokens. +- **Iconen:** eigen set in `gui/src/icons.tsx` + `gui/src/provider-icons.ts`. +- **Copy:** Engels met i18n (`gui/src/i18n/`: en, ko, zh, ru, ja, de, **nl**). +- **Bestaande NL-laag:** `gui/src/i18n/nl.ts` draagt al de ChefGroep "De Pas"-stem + (`nav.dashboard` → "De pas", `nav.providers` → "Leveranciers", …). + +### 2.2 Waar we heen gaan (`design-system` v2) + +Bron van waarheid: `tokens.css`, `DESIGN.md`, `motion-spec.md`, +`prototype-v2.html`. + +- **Oppervlak:** warm off-white `#F7F6F5` (light) / basalt-warm `#121111` + (dark). Haarlijnen, geen glow, geen gradients, geen schaduw in product-cards. +- **Accent:** één blauw — `#317CFF` (light) / `#5C97FF` (dark). Niets anders mag + schreeuwen. Groen (`#1F883D`) is gereserveerd voor git/PR/toestemming, amber + voor hold/wacht-op-jou, rood voor deletes/destructive. +- **Typografie:** General Sans 400/500/600 (koppen 500, tracking −0.02em); + JetBrains Mono uitsluitend voor data (timers, diffs, commands, paden). +- **Componenten:** shadcn-conventies — `.btn` (h32, r6, primary = tekst↔bg + omgekeerd), `.gbtn` (28px ghost-icon), `.badge` (pill), `.input`/`.select`, + `.switch`, `.seg` (segmented), `.sgroup` (grouped setting-card). +- **Iconen:** Lucide SVG-sprite (`components/icons.svg`, 31 symbols), grid 24, + stroke 2, ronde caps. Nooit emoji. +- **Motion:** geen spinners. Activiteit = worked-row timer + tool-ripples + (`motion-spec.md`), press-physics `scale(0.97)`, vaste easing + `cubic-bezier(0.22,1,0.36,1)`, duren 140/280/420ms, `prefers-reduced-motion` + verplicht. +- **Stem:** warm, direct Nederlands. Verboden: em-dashes, buzzwords, verzonnen + metrics, emoji. +- **Skins:** `data-style="devin"` (default) en `data-style="strak"` als tweede + complete skin over dezelfde taal. + +### 2.3 Kloof-analyse + +| Dimensie | Nu (opencodex) | Doel (design-system) | Impact | +|---|---|---|---| +| Basiskleur | monochroom wit/zwart | warm off-white `#F7F6F5` | token-remap | +| Accent | monochroom (zwart/wit) | blauw `#317CFF` | token-remap + splitsing accent/primary | +| Font | OpenAI Sans | General Sans + JetBrains Mono | assets bundelen | +| Radius | 12/8/6/4 + pill | md6/lg10/pill | token-remap | +| Schaduw/glass | `--shadow*`, `--glass-*`, ambient wash | verboden in product | neutraliseren | +| Iconen | eigen `icons.tsx` | Lucide sprite | component-swap | +| Motion | keyframes/animaties (o.a. `depas.css`, `styles.css`) | ripple + worked-row, geen spinners | herbouw | +| Copy | Engels + i18n (nl bestaat) | NL "De Pas" default | i18n uitbreiden | + +Meevaller: omdat opencodex zijn tokens centraliseert in `:root`, herkleurt het +overschrijven van die variabelen het hele dashboard in één klap. De lastige +delen zijn de *opinies* van het systeem: spinners→ripples, icon-swap en de +Nederlandse copy-stem. + +--- + +## 3. Aanpak in fasen + +Elke fase is een eigen, reviewbare PR met before/after-bewijs. We beginnen laag +en omkeerbaar en werken naar de opinie-lagen toe. + +### Fase 0 — Fundament +- Design-tokens vendoren: `design-system/tokens.css`-waarden overnemen als bron + (kopie in `gui/src/styles/ds-tokens.css`, met herkomst-commentaar en datum). +- Skin-schakelaar voorbereiden: `data-style` op `` (default `devin`), + persist in `localStorage`, net als `theme.ts` dat voor `data-theme` doet. +- Definition of done: build en typecheck groen, geen visuele wijziging nog. + +### Fase 1 — Token-laag (de grote herkleuring) +- De `:root`-tokens in `gui/src/styles.css` hermappen naar de design-system- + waarden (light + dark), zie de mapping-tabel in §4. +- Accent splitsen: **primary-actie** blijft tekst↔bg-omkering (zwart-op-warm), + **accent-blauw** komt op links, focus-ring, switch-aan, selectie en + actieve nav. +- `--shadow*`, `--glass-*` en de ambient wash neutraliseren op product- + oppervlakken (haarlijn i.p.v. schaduw). +- Definition of done: elke pagina rendert in light én dark, screenshots + before/after, geen contrast-regressies (WCAG AA op tekst). + +### Fase 2 — Typografie +- General Sans (400/500/600) en JetBrains Mono bundelen als + `@fontsource`-pakketten (past bij de bestaande `@fontsource`-aanpak in + `gui/package.json`). +- `--font-ui` → General Sans, `--font-code` → JetBrains Mono; koppen weight 500, + tracking −0.02em; `.num` = tabular-nums op timers/tellers. +- Definition of done: fonts laden lokaal (geen externe fetch), fallback-stack + intact voor CJK/KR. + +### Fase 3 — Componenten (shadcn-contracten) +- `.btn`, `.gbtn`, `.badge`, `.input`/`.select`, `.switch`, `.seg`, `.sgroup` + uitlijnen op de contracten uit `tokens.css`. +- Bestaande knoppen/inputs/toggles in `gui/src/ui.tsx` en per-surface CSS naar + deze klassen brengen; press-physics `scale(0.97)` op `:active`. +- Definition of done: één component-audit-pagina (of Storybook-achtige route) + die alle varianten toont in beide thema's. + +### Fase 4 — Iconen +- Lucide-sprite (`design-system/components/icons.svg`) opnemen; `.ic`-contract + (15px, stroke 2, ronde caps). +- `gui/src/icons.tsx` per icoon omzetten naar Lucide-symbols; emoji in copy + opsporen en verwijderen (ban). +- Definition of done: geen emoji-iconen meer, alle nav/knop-iconen Lucide. + +### Fase 5 — Motion & signatuur +- Alle spinners/loaders vervangen door het worked-row + ripple-systeem + (`motion-spec.md`): read = `line-strong`, write = `accent`, extern = amber. +- Vaste easing/duren-tokens (`--ease-out`, 140/280/420) invoeren; press-physics + en pane-slide volgens spec; `prefers-reduced-motion` volledig respecteren + (geen informatieverlies). +- Definition of done: geen `@keyframes spin` meer; reduced-motion getest. + +### Fase 6 — Copy-stem "De Pas" (NL) +- `gui/src/i18n/nl.ts` uitbreiden tot volledige dekking; NL als standaardtaal + overwegen (beslissing §6). +- Ban-check op copy: geen em-dashes, geen emoji, geen buzzwords/verzonnen + metrics. Statuslijn "Klaar voor instructies". +- Respecteer `gui/AGENTS.md`: **geen hardgecodeerde UI-teksten** in + `src/pages`/`src/components`; elke string in álle locale-bestanden; draai + `bun run lint:i18n`. +- Definition of done: `bun --bun run lint:gui` en `lint:i18n` groen, nl compleet. + +### Fase 7 — Skins (optioneel) +- `data-style="strak"` als tweede skin activeren via een seg in de + instellingen; `?style=strak` support. +- Definition of done: wisselen persistent, beide skins in light+dark correct. + +--- + +## 4. Token-mapping (Fase 1, concreet) + +Waarden uit `design-system/tokens.css`. `light-dark(licht, donker)` blijft de +opencodex-conventie. + +| opencodex-token | Nieuw (light) | Nieuw (dark) | Herkomst / noot | +|---|---|---|---| +| `--bg` | `#F7F6F5` | `#121111` | ds `--bg` | +| `--rail` | `#F2F1F0` | `#171615` | iets onder `--bg` | +| `--surface` | `#FFFFFF` | `#1B1A19` | ds `--surface` | +| `--raised` / `--raised-hover` | `#EFEFEF` / `#E7E6E5` | `#242322` / `#2C2B2A` | ds `--surface-sunk` | +| `--border` / `--border-soft` | `rgba(0,0,0,.14)` / `rgba(0,0,0,.08)` | `rgba(255,255,255,.16)` / `.09` | ds `--line-strong` / `--line` | +| `--hover` | `rgba(0,0,0,.045)` | `rgba(255,255,255,.05)` | ds `--hover` | +| `--text` / `--muted` / `--faint` | `#191919` / `rgba(0,0,0,.55)` / `.38` | `#F0EEEB` / `.55` / `.35` | ds `--text*` | +| `--accent` (primary bg) | `#191919` | `#F0EEEB` | blijft tekst↔bg-omkering | +| `--accent-ink` (op primary) | `#F7F6F5` | `#191919` | inverse van `--text` | +| **nieuw** `--accent-blue` | `#317CFF` | `#5C97FF` | links/focus/switch/selectie | +| **nieuw** `--accent-blue-ink` | `#1D5FD6` | `#8AB4FF` | link-hover, PR-nummers | +| `--accent-soft` / `--accent-ring` | `rgba(49,124,255,.09)` | `rgba(92,151,255,.12)` | focus-ring 3px | +| `--green` (+ soft) | `#1F883D` / `rgba(.10)` | `#3FB950` / `rgba(.12)` | gereserveerd git/PR | +| `--red` (+ soft) | `#CF222E` | `#F85149` | deletes/destructive | +| `--amber` (+ soft) | `#BF5B00` | `#D9A038` | hold/wacht-op-jou | +| `--radius` / `-sm` / `-xs` | `10px` / `8px` / `6px` | idem | ds `--r-lg` / tussen / `--r-md` | +| `--radius-pill` | `200px` | idem | ds `--r-pill` | +| `--motion-fast` / `-normal` | `140ms` / `280ms` | idem | ds `--dur-fast/med` | +| **nieuw** `--ease-out` | `cubic-bezier(0.22,1,0.36,1)` | idem | ds | +| `--shadow*` / `--glass-*` | neutraliseren (haarlijn) | idem | ban: geen schaduw/glow in product | +| `--toggle-on-bg` | `--accent-blue` | `--accent-blue` | switch-aan = blauw | + +--- + +## 5. Bestandsimpact & risico + +| Gebied | Bestanden | Risico | Aanpak | +|---|---|---|---| +| Kern-tokens | `gui/src/styles.css` (`:root`) | Laag | Centrale remap; makkelijk terug te draaien | +| Per-surface CSS | `gui/src/styles/*.css`, `styles-*.css` | Midden | Hergebruikt tokens; alleen hardcoded kleuren opsporen | +| Ambient/glass | `styles.css` wash + `--glass-*` | Midden | Uitzetten; visuele controle per pagina | +| Componenten | `gui/src/ui.tsx`, modals | Midden | Klassen naar shadcn-contract | +| Iconen | `gui/src/icons.tsx`, `provider-icons.ts` | Midden | Sprite-swap, per icoon | +| Motion | `depas.css`, `styles.css` keyframes | Hoog | Herbouw signatuur; reduced-motion | +| Copy | `gui/src/i18n/*.ts` | Midden | nl compleet + i18n-lint | + +De grootste risico's zitten in Fase 5 (motion, want gedrag) en het opsporen van +hardgecodeerde kleuren buiten de tokenlaag. + +--- + +## 6. Beslissingen die input nodig hebben + +1. **Diepte nu:** alleen Fase 1 (herkleuring, structuur en Engels/i18n intact), + of volledige adoptie (t/m ripples + Lucide + NL default)? +2. **Fonts:** General Sans en JetBrains Mono bundelen — akkoord op licentie/ + gewicht in de npm-package (`gui/dist`)? +3. **Standaardtaal:** NL "De Pas" als default, of taal-detectie met NL als optie? +4. **OpenAI-skin behouden?** De huidige monochrome look als derde `data-style` + bewaren, of vervangen? +5. **Skins:** is `strak` in scope, of alleen `devin`? + +--- + +## 7. Testen & bewijs + +Per `AGENTS.md` (Bun-native) en `gui/AGENTS.md`: + +- `bun run typecheck` — strict, moet groen. +- `bun run test` — volledige suite (let op de bekende container-/drift-failures + uit `## Cursor Cloud specific instructions`). +- `bun --bun run lint:gui` en `bun run lint:i18n` — groen (lint draait onder de + Bun-runtime, zie AGENTS.md). +- `bun run privacy:scan` — groen. +- **Handmatig (computerUse):** elke gewijzigde pagina in light + dark, before/ + after-screenshots; korte demo-video van een kernflow (bv. provider toevoegen) + in de nieuwe stijl. +- **Dev-run:** `bun run dev:proxy` (`:10100`) + + `OPENCODEX_PROXY_TARGET=http://127.0.0.1:10100 bun run dev:gui` (`:5173`). + +Definition of done voor het geheel: alle checks groen, geen contrast-regressies, +before/after-bewijs per fase, `docs-site/` bijgewerkt waar gebruikersgedrag +zichtbaar verandert. + +--- + +## 8. Rollout / PR-strategie + +- Werk per fase op een eigen `cursor/…`-branch; één PR per fase, klein en + reviewbaar, met screenshots. +- **Branch-target:** per `AGENTS.md`/`CONTRIBUTING.md` gaan feature-PR's naar + `dev` (niet `main`). +- Volgorde: Fase 0 → 1 → 2 → 3 → 4 → 5 → 6 → (7). Fase 1 kan al los landen als + zichtbare winst; latere fasen bouwen erop voort. +- Elke PR verwijst terug naar dit plan en vinkt de bijbehorende fase af. + +--- + +## 9. Buiten scope + +- De proxy-runtime, adapters, routing, management-API (`src/`). +- De i18n-architectuur zelf (alleen inhoud/dekking verandert). +- Nieuwe features of pagina's; dit is presentatie, geen functionaliteit. +- De 3-pane sessie/transcript/artifact-layout uit `DESIGN.md` §8 — die is voor + een agent-sessie-product, niet voor dit settings-dashboard. Overwegen als + aparte richting, niet in deze redesign. + +--- + +## 10. Bronnen + +- `OnlineChefGroep/design-system`: `tokens.css`, `DESIGN.md`, `motion-spec.md`, + `prototype-v2.html`, `surfaces/*.md`. +- opencodex: `gui/src/styles.css`, `gui/src/theme.ts`, `gui/src/i18n/nl.ts`, + `gui/AGENTS.md`, `AGENTS.md`.