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

10 KiB
Raw Permalink Blame History

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.