deckhearth/.convoys/scanner-desktop-layout/audits/design-system-20260815.md
varutasu 938c161a26
feat(scanner): add desktop workstation layout (#165)
Give /scanner a md+ camera, live match inspector, and history strip
(with device picker, batch scan, and tips) without regressing the
mobile immersive checkout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-15 17:21:23 -05:00

153 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Design-System Audit — scanner-desktop-layout
**Role:** `role-design-system-auditor`
**Surface:** `convoy/scanner-desktop-layout` workstation UI (`git diff origin/main` + untracked scanner components)
**Convoy:** `.convoys/scanner-desktop-layout.md`
**Multitask group:** `audit-scanner-desktop-layout-local`
**Date:** 2026-08-15
**Scope:** UI / DS only — read-only; no code changes
**Inputs reviewed**
| Source | Notes |
| --- | --- |
| Diff UI (vs `origin/main`) | `pages/scanner.js`, `components/scanner/ScannerCamera.js` (+ unrelated dashboard/Layout noise in same branch tip — **out of audit scope**) |
| Untracked (convoy) | `ScannerTips.js`, `ScannerResultPanel.js`, `ScannerHistoryStrip.js` + component tests |
| Direction lock | `design_direction` v1 + `## Design direction` + `## UX` |
| Tokens | `docs/DESIGN_TOKENS.md`, `styles/globals.css` |
| Primitives | `components/ui/{GlassSurface,Button,Modal,Input}.js` |
| Skill | `.cursor/skills/design-systems/SKILL.md` **not installed**; report follows prior Liquid Glass audit shape + role file |
---
## Audit summary
| Check | Status | Notes |
| --- | --- | --- |
| Direction lock (md+ workstation grid) | ✅ Strong | Framed camera + desk bar + inspector rail + history strip + Tips Modal; mobile immersive left alone |
| Hex in JSX (new convoy files) | ❌ | `#ffffff` on Queue/Duplicates badge in `ScannerHistoryStrip.js` |
| VOCAB / stale strings | ✅ | `VOCAB.ADD_TO_*` / `MY_COLLECTION`; no Wishlist / Mark Owned / All My Cards |
| `backdrop-filter` on strip chips | ✅ | Chips solid `--bg-secondary`; container is `GlassSurface tint="mid"` |
| GlassSurface / Button / Modal reuse | ✅ High | Tips=`Modal`; inspector/strip/desk/camera frame=`GlassSurface`; primary CTAs=`Button` |
| Custom modal scrim | ✅ | Tips + leave + list picker use `<Modal>` only |
| Sev ≥ 3 findings | **1** | Hex literal on tab badges |
---
## Maturity scoring (repo DS + this surface)
Scores 04. Evidence cites paths/counts.
| Axis | Score | Evidence |
| --- | --- | --- |
| **Tokens (T)** | **3** | Workstation surfaces consume `--glass-surface-*` via `GlassSurface`, `--text-*`, `--accent-ember` / `--accent-flame`, `--ember-rim-*`, `--border`. Residual: on-accent text still `#ffffff` in new strip badges (and pre-existing `Button.js` primary/danger). No `--text-on-accent` alias in `globals.css`. |
| **Components (C)** | **3** | Kit: GlassSurface, Modal, Button, Input, SearchBar, StatCard. New surfaces compose GlassSurface + Button + Modal. Gaps: no Switch / TabList primitive — Auto-detect + Foil switches and strip tabs are raw `<button>` (acceptable; pattern repeated ×3). |
| **Patterns (P)** | **3** | Locked workstation pattern largely shipped: `Layout chrome="default"` at md+, camera `variant="workstation"` with ember brackets + reduced-motion scan-line (`ScannerCamera.js` `DetectionFrame`), desk `GlassSurface mid`, inspector `tint="low"`, strip three tabs + batch banner, Tips `<Modal size="md">`. Minor drift: confidence fill uses `--color-warning` / `--color-success` vs directions flame/gold highlight row (aligned with UX “reuse ReviewCardItem” instead). |
| **Governance (G)** | **3** | Convoy `design_direction` locked 2026-08-15; `ui-and-theming.mdc` + vocab CI; `forbidden-hex-in-jsx` documented in `DESIGN_TOKENS.md`. Design-systems skill package still absent in-repo. |
| **Adoption (A)** | **3** | Desktop surface counts: `<Button>` ×12 across `scanner.js` + ResultPanel + HistoryStrip + Tips; `<GlassSurface>` on camera frame, desk bar, inspector, strip container, Auto-detect badge; `<Modal>` ×1 Tips + leave/list on page. Chips correctly **avoid** GlassSurface blur. Raw `<button>` ×7 mostly switches/tabs/Clear All (direction allows Clear All as text link). |
**Composite:** T3 / C3 / P3 / G3 / A3
**Top leverage:** **Tokens (T)** — introduce a shared on-accent text token (or route badge text through `<Button>` / a tiny Badge primitive) and purge `#ffffff` from convoy JSX so the hex gate and Liquid Glass lock stay green.
---
## Direction lock
Locked fields enforced: Liquid Glass; md+ workstation (camera + inspector + strip); ember accents; VOCAB CTAs; no hex; no per-chip `backdrop-filter`; Tips via `<Modal>`; no custom scrim; mobile immersive unchanged.
| Locked requirement | Diff status |
| --- | --- |
| md+ `chrome="default"`; mobile immersive | ✅ `pages/scanner.js` |
| Page title / subtitle + Scanner Tips | ✅ Header + `ScannerTips` |
| Camera framed panel + ember brackets | ✅ `variant="workstation"` + `DetectionFrame` L-brackets + scan-line + `prefers-reduced-motion` |
| Desk bar: Camera / Upload / Batch / Auto-detect | ✅ `GlassSurface tint="mid"` + native `<select>` + `Button`×2 + switch |
| Device picker fallbacks inline (not modal) | ✅ `camera.devicePickerMessage` under select |
| Inspector rail `w-[360px]` + GlassSurface low | ✅ `ScannerResultPanel` |
| Empty / confidence / VOCAB primary + Rescan / Add to List | ✅ |
| Strip: Recent / Queue / Dupes + Clear All + View All | ✅ `ScannerHistoryStrip` |
| Chips solid `--bg-secondary`; focused ember rim | ✅; no chip `backdrop-filter` |
| Batch progress + Cancel | ✅ `BatchProgressBanner` |
| Tips = `<Modal>` five tips (not popover) | ✅ `ScannerTips.js` |
| No hex / no Wishlist / Mark Owned | ❌ one `#ffffff`; vocab clean |
| Checkout sheet mobile-only | ✅ `md:hidden` mount |
---
## Token audit (3-tier)
| Tier | Expectation | Diff notes |
| --- | --- | --- |
| Primitives | Hex only in CSS token definitions | No new CSS hex from convoy. **JSX** `#ffffff` in strip badge violates consumer rule. |
| Aliases | `--glass-surface-*`, blur, rim, elevation, text, accent | Correctly used via GlassSurface props + `var(--*)` styles. Missing alias for on-accent / inverse text (primitives still hardcode `#ffffff`). |
| Components | GlassSurface / Button / Modal compose aliases | Desk, inspector, strip, Tips comply. Tab badge invents parallel on-accent styling instead of composing Button/Badge. |
---
## Component / adoption audit (scoped desktop surface)
| Element | Expected | Actual | Rate |
| --- | --- | --- | --- |
| Camera frame | `GlassSurface` low + ember rim | Yes (`ScannerCamera` workstation branch) | High |
| Desk control bar | `GlassSurface` mid | Yes (`pages/scanner.js`) | High |
| Inspector | `GlassSurface` low | Yes (`ScannerResultPanel`) | High |
| History strip shell | `GlassSurface` mid | Yes | High |
| Strip chips | Solid `--bg-secondary` (no blur) | Yes | High |
| Tips | `<Modal>` | Yes | High |
| Primary / secondary CTAs | `<Button>` | Yes (Upload, Batch, Add, Rescan, Cancel, View All) | High |
| Auto-detect / Foil | Switch pattern | Raw `<button role="switch">` ×2 | Medium — no Switch primitive |
| Strip tabs | tablist | Raw `<button role="tab">` | Medium — correct a11y; not Button |
| Clear All | Text link | Raw `<button>` ember text | Medium — matches direction “text link” |
| Leave / List | `<Modal>` | Yes (page) | High |
**Missing primitive (optional follow-up):** `Switch` (and optionally `Badge`) would remove duplicated toggle/`#ffffff` badge styling across desk + inspector + strip.
---
## Findings
Severity 04. Cap prioritized; sev ≥ 3 blocks merge recommendation for DS gate.
| ID | Sev | Finding | Evidence | Fix |
| --- | --- | --- | --- | --- |
| DS-1 | **3** | Hardcoded hex in convoy JSX | `ScannerHistoryStrip.js` tab badge `color: '#ffffff'` (≈L250) | Replace with theme token (add `--text-on-accent` / reuse Buttons on-accent once tokenized) so `forbidden-hex-in-jsx` stays green |
| DS-2 | **2** | Toggle knobs use Tailwind `bg-white` | `pages/scanner.js` Auto-detect knob; `ScannerResultPanel.js` Foil knob | Prefer `backgroundColor: 'var(--bg-primary)'` or a documented knob token — avoid raw white utility on themed surfaces |
| DS-3 | **1** | Confidence bar accent drift vs Design direction color table | `ScannerResultPanel` `confidenceRingColor`: mid `--color-warning`, high `--color-success` | Optional align to `--accent-flame` / `--accent-gold` for ≥90% match badge; or document UX override (ReviewCardItem reuse) as accepted |
| DS-4 | **1** | Clear All lacks destructive hover | Always `--accent-ember` | Direction: destructive on hover — add hover token mix if shipping polish pass |
| DS-5 | **1** | Systemic on-accent hex in primitive (context) | `components/ui/Button.js` primary/danger still `#ffffff` / `#dc2626` | Out of convoy scope but explains copy-paste; tokenize in a follow-up DS convoy |
### Passes (not findings)
- No `"Add to Collection"`, `"Save to Wishlist"`, `"Mark Owned"`, `"All My Cards"` in scoped new UI.
- Inspector + strip CTAs import `VOCAB.ADD_TO_MY_COLLECTION` / `VOCAB.ADD_TO_LIST`.
- Tips uses `<Modal size="md">` with convoy-authored five tips; no custom scrim.
- Strip chips: solid `--bg-secondary`, focused `--ember-rim-pronounced`; no per-chip blur.
- Camera detection chrome: ember/flame L-brackets + scan-line with `prefers-reduced-motion` static mid-line.
- Auto-detect badge: `motion-safe:animate-pulse` when ON.
- Confidence bar width transition gated with `@media (prefers-reduced-motion: reduce)`.
- Icons are SVG (lightbulb / empty-state camera), not emoji.
- Mobile checkout sheet remains `md:hidden`; workstation controls `hidden md:flex`.
---
## Governance notes
- Contribution path: `docs/DESIGN_TOKENS.md` + `.cursor/rules/ui-and-theming.mdc`.
- CI: `forbidden-hex-in-jsx` + stale-vocab gates — **DS-1 will fail the hex gate once these files are in CIs path**.
- Design-systems skill/templates not under `.cursor/skills/design-systems/` — G capped partly by missing shared audit tooling.
---
## Recommendation
**Treat DS as not merge-clean until DS-1 is fixed** (one-line / token swap on the strip badge). DS-2 is the next polish item for light/dark knob contrast. DS-3DS-5 are non-blocking documentation / follow-up token work.
**Child tasks (sev ≥ 3):**
1. Remove `#ffffff` from `ScannerHistoryStrip.js` badge text — use a CSS variable (prefer adding `--text-on-accent: #fff` in `globals.css` and referencing it from Button + badge).
---
## Hand-off
DS audit complete. Maturity: **T3/C3/P3/G3/A3**. Top leverage: invest in **Tokens** (on-accent alias + purge convoy hex). Sev ≥ 3 findings: **1**. Report: `.convoys/scanner-desktop-layout/audits/design-system-20260815.md`.