Tokens (light + dark, neumorphism, 54/54 WCAG AA contrast pairs), the self-hosted JetBrains Mono fonts, and interactive mockups of every screen across three iterations. Iteration 3 is final: phone, tablet and desktop tiers, device preview, and "empty spool weight" terminology. The build scripts regenerate the screens byte-identically from source. Implementation is tracked in Maestro feature UI Refresh - V3.0 (224b72a1-8d84-4970-97ea-5dafa4d8ea3b). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
158 lines
9.9 KiB
Markdown
158 lines
9.9 KiB
Markdown
# Extrudex Soft UI (Design System v3) proposal: summary
|
||
|
||
2026-09-18. This is a proposal only. **Nothing was changed** in the Extrudex
|
||
repository (still clean at `dev` `321ce0d`) or in CTXD. Nothing was deleted.
|
||
|
||
## What I built and where it is
|
||
|
||
Everything is in `~/Design/extrudex-v3/`.
|
||
|
||
| File | What it is |
|
||
|---|---|
|
||
| `00-understanding.md` | Step 1: every field on each existing screen, every stored printer field, the v2.0 palette, and how CTXD differs from the code |
|
||
| `design-system-v3.css` | Step 2: the token set. v2.0 base kept, dark and light themes, neumorphism tokens (surfaces, raised and inset pairs, 4 intensity levels, radius scale), state tokens, reference components |
|
||
| `design-system-v3.md` | Step 2: every changed or added token with its reason, the state matrix, the dark-mode approach, 2 alternative palettes, and contrast tables for both themes (54/54 pass, plus 9 more pairs) |
|
||
| `fonts/` | JetBrains Mono 400/500/700/800 woff2 (the same `@fontsource` 5.3.0 files the app ships) + OFL license |
|
||
| `screens/01-dashboard.html` | **New standalone Dashboard**: stock tiles, running low (net + gross, tare unknown shown), net kg by material, recent prints with weight source and upper-bound duration marks, compact printer strip |
|
||
| `screens/02-filament.html` | Inventory: working search and filters, table/cards toggle, the 5-part name, net remaining vs tare (+ source) vs gross, Edit, Delete with a confirmation dialog |
|
||
| `screens/03-spool-form.html` | Add/Edit spool with a scenario switcher: **409 conflict**, **400 field errors**, **tare unknown**, **add new**, plus a control-state specimen |
|
||
| `screens/04-printers.html` | Printers: stored fields only, a "dev today / dev + feature branch" data toggle, the **MQTT dropped** state (A1), and a **Future, not built** section |
|
||
| `source/` | Build inputs (`build.py` makes each screen self-contained with base64 fonts) and `checks/table.py`, which regenerates the contrast table |
|
||
|
||
Every screen has a Light/Dark toggle (also `?theme=light` or `?theme=dark` in
|
||
the URL), has no network dependencies, and was checked at 1440 px and 390 px in
|
||
headless Chrome.
|
||
|
||
## Decisions that go against DECISIONS.MD or the v2.0 rules
|
||
|
||
1. **Styling: "tokens verbatim… do not edit a token to suit a component."**
|
||
v3 changes the *values* of a few v2.0 semantic tokens (`--surface-raised`,
|
||
`--shadow-raised`, `--focus-ring`, `--radius-sm`, `--radius-md`,
|
||
`--text-on-accent` in light). This isn't editing a token to suit a
|
||
component. It's a proposed new *version* of the design system, and each
|
||
change has a reason in the .md. It still needs your call: adopting it means
|
||
updating the guide at `pages.ccl` first and then copying it verbatim into
|
||
`theme.css`, as the rule intends.
|
||
2. **v2.0 brand rules "0 radius" and "flat shadows"** are overturned. Soft UI
|
||
can't exist without them. `--radius-none` stays for tables and code.
|
||
3. **Primary buttons changed color, dark theme** (`#8f7ae0` → `#a99af0`),
|
||
because v2.0's ink-on-accent is **4.32:1** and fails AA. That's a brand-color
|
||
shift on the most visible control.
|
||
4. **CONTEXT scope: "printer status pages… deliberately out until daily use."**
|
||
The Printers screen was designed because you asked for it. Note that a
|
||
printers view already exists on `dev`, embedded in Floor.
|
||
|
||
Things I followed even where the code has moved past the docs:
|
||
- **Weight source** is shown with 4 values (`typed`, `sliced`, `recalled`,
|
||
`unknown`). DECISIONS.MD lists 3. The schema adds `sliced` and says
|
||
`recalled` is no longer written.
|
||
- **Tare origin**: the code (`resolveTare` in `types.ts`) falls back to a
|
||
**brand** tare, labeled as a guess. DECISIONS.MD says tare comes "from
|
||
spool_type, never from brand". The mockups never show a brand-derived tare.
|
||
|
||
## Open questions
|
||
|
||
1. **Adopt or reject** the two brand-rule changes (radius, shadows) and the
|
||
lighter primary-button violet? Everything else depends on this.
|
||
2. **Floor → Dashboard + Printers.** The proposal splits today's Floor into a
|
||
stock-first Dashboard and a separate Printers page. Is that the direction,
|
||
or should Floor stay as one page restyled?
|
||
3. **Weight source in `GET /api/prints`.** It's stored but not served, so the
|
||
Dashboard needs a small API change. OK to add it?
|
||
4. **`recalled` vs `sliced`.** Should DECISIONS.MD be updated to say `sliced`
|
||
exists and `recalled` is legacy? That's a CTXD edit, which I didn't make.
|
||
5. **Brand-tare fallback.** Code and DECISIONS.MD disagree. Which one is right?
|
||
6. **Serial display.** I masked the middle of serials (`01P09A••••••4821`). Show
|
||
in full, masked, or hidden?
|
||
7. **"Tare unknown only" filter** is new on the Filament page (it helps work
|
||
down the "weigh it yourself" list). Keep it?
|
||
8. **The 409 "reapply my change" button** assumes the client can diff the
|
||
fields you changed against the new version. Today the form only shows the
|
||
server's message. Do you want that behavior, or just "reload"?
|
||
9. **Alternative palettes** A (warm graphite) and B (slate/teal) are in the .md.
|
||
Do you want either mocked up?
|
||
10. **CTXD is out of date** (Dashboard.tsx, no auth, Bambu only, the design
|
||
system URL). Should someone refresh CONTEXT.MD? I made no CTXD edits.
|
||
|
||
## Proposed Maestro tasks (titles only, smallest first; not created)
|
||
|
||
1. Add `weight_source` to the `GET /api/prints` response
|
||
2. Add v3 warning and info status tokens to `theme.css`
|
||
3. Add the `--border-control` token and apply it to buttons, inputs and selects
|
||
4. Replace the v2.0 focus ring with the v3 2px offset outline
|
||
5. Fix primary-button text contrast (4.32:1 → 6.14:1)
|
||
6. Show a weight-source chip on each print row
|
||
7. Show an upper-bound mark on durations with connection gaps
|
||
8. Show "gaps not counted" on prints with null `connection_gaps`
|
||
9. Show tare, tare source and gross weight on the Filament table and cards
|
||
10. Show "tare unknown" (never 0) wherever gross weight is derived
|
||
11. Add the "Tare unknown only" filter to Filament
|
||
12. Map spool 400 messages to their fields in SpoolForm
|
||
13. Add the 5-part name preview to SpoolForm
|
||
14. Add the net/tare/gross scale diagram to SpoolForm
|
||
15. Replace the SpoolForm 409 footer text with a conflict panel and reload actions
|
||
16. Add a light theme with a stored per-browser toggle
|
||
17. Add the neumorphism shadow and radius tokens (after the brand decision)
|
||
18. Restyle buttons, inputs and chips with the v3 state matrix
|
||
19. Split Floor into a stock-first Dashboard and a Printers page
|
||
20. Render the connection-lost state on printer cards (after the printer-connections feature merges)
|
||
21. Publish Design System v3 to `pages.ccl` and re-sync `theme.css` verbatim
|
||
|
||
---
|
||
|
||
# Iteration 2 (2026-09-18): navigation, data display and interaction
|
||
|
||
Everything is in `iteration-2/`. Iteration 1 above is unchanged, for comparison.
|
||
|
||
| File | What it is |
|
||
|---|---|
|
||
| `iteration-2/00-ux-review.md` | 12 findings from iteration 1, the navigation model, flows ranked by frequency, interaction patterns, data-display rules, accessibility notes, 5 new questions, 18 more task titles |
|
||
| `iteration-2/screens/index.html` | **Start here.** Flow map plus 8 guided flows that deep-link into each state |
|
||
| `iteration-2/screens/01-dashboard.html` | "Needs you" queue first, then stock tiles, recent prints by day, printers and running low. Everything clickable |
|
||
| `iteration-2/screens/02-filament.html` | Saved views with counts, Stock/Weights columns, grouping, sortable headers, row ⋯ menu, weigh session |
|
||
| `iteration-2/screens/03-prints.html` | **New.** Needs attention (inline suggestions, grams, batch) · All · Running · Archived |
|
||
| `iteration-2/screens/04-printers.html` | Urgency order, jump strip, holder fill + Load, stale "last known" state, dev/feature toggle |
|
||
| `iteration-2/source/` | `data.js` (one shared model), `app.js` (shell, palette, panel, toasts), `components.css`, pages, `build.py` |
|
||
|
||
What's shared across every page: the spool/print/load **panel** (deep-linked,
|
||
Esc/back closes, j/k steps), the **⌘K palette**, nav **badges** for work
|
||
waiting, **toasts** after each save, a **freshness** indicator with an offline
|
||
state, and a phone **tab bar** with a floating Add button.
|
||
|
||
**Corrected from iteration 1:** it showed AMS "slot" positions, which the
|
||
database doesn't store. Iteration 2 shows holder fill ("3 / 4") instead.
|
||
|
||
Verified: every page and panel state loads with no console errors in headless
|
||
Chrome, at 1440 px and 390 px, in both themes. There are no network requests,
|
||
and no new colors (the v3 contrast table still applies).
|
||
|
||
---
|
||
|
||
# Iteration 3 (2026-09-18): remaining screens, tablet and phone
|
||
|
||
Everything is in `iteration-3/`. Iterations 1 and 2 are unchanged.
|
||
|
||
- **Start here:** `iteration-3/screens/index.html` (flow map, 14 flows) and
|
||
`iteration-3/screens/devices.html` (every screen in live phone 390 × 844,
|
||
tablet 820 × 1180 and 1180 × 820 frames).
|
||
- **New screens:** 05 Lists · 06 Labels · 07 Access · 08 System · 09 Scan:
|
||
holder · 10 Scan: spool, plus Add/Edit printer, Manage holders and Remove
|
||
printer panels on Printers.
|
||
- **Your answers from `iteration-2/00-ux-review.md`, applied:** Change spool
|
||
(with real grams-returned wording), lightest-first weigh sessions with
|
||
location, Filament badge for unverified tares, and load/attribute palette
|
||
commands.
|
||
- **Responsive:** three tiers (phone < 700, tablet 700–1180 with a compact
|
||
rail, desktop). Spec in `iteration-3/00-changes.md` §4.
|
||
- **Findings:** list names are case-sensitive in the schema; audit log,
|
||
low-filament report and machine tokens have APIs but no screens on `dev`.
|
||
- **Verified:** all 12 pages and 18 panel/palette states load with no console
|
||
errors; checked at 390, 820 and 1180 px and desktop, in both themes. No
|
||
network requests, no new colors.
|
||
|
||
**Terminology update (2026-09-18):** iteration 3's UI now says **"empty spool
|
||
weight"** everywhere it said "tare" (verified: no rendered text, tooltip, label
|
||
or placeholder contains "tare"). Code and API names (`tare_grams` etc.) are
|
||
unchanged. See `iteration-3/00-changes.md` §1b. Open item: GLOSSARY.MD in CTXD
|
||
still uses "Tare".
|