Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
279 changes: 279 additions & 0 deletions PLAN.md
Original file line number Diff line number Diff line change
@@ -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 `<html>` (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`.
Loading