* Start scanner-mobile-checkout convoy for the cart-then-commit phone flow. Co-authored-by: Cursor <cursoragent@cursor.com> * Ship a cart-then-commit mobile scanner so phone sessions stay on the camera. Scan matches enqueue locally instead of auto-writing ownership, checkout happens in a sheet, and audit fixes cover stale commit detection, returnUrl open redirects, nested Escape, and ember detection chrome. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
11 KiB
Design-System Audit — scanner-mobile-checkout
Role: role-design-system-auditor
Surface: uncommitted feat/scanner-mobile-checkout UI (git diff origin/main + untracked scanner UI)
Convoy: .convoys/scanner-mobile-checkout.md
Date: 2026-08-14
Scope: UI / DS only — read-only; no code changes
Inputs reviewed
| Source | Notes |
|---|---|
| Diff UI | Layout.js, ScannerCamera.js, ScannerCountPill.js, ScannerToast.js, ReviewCardItem.js, ScannerReview.js, pages/scanner.js |
| Untracked | ScannerCheckoutSheet.js, ScannerScanPeek.js |
| Direction lock | design_direction v1 + ## Design direction in convoy |
| 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 in this repo; audit follows role file + prior Liquid Glass audit shape + docs/DESIGN_TOKENS.md |
Audit summary
| Check | Status | Notes |
|---|---|---|
| Direction lock (Liquid Glass + immersive camera + sheet) | ⚠️ Partial | Chrome bars + VOCAB CTAs + Modal reuse land; L-brackets / scan-line missing; sheet tint recipe drifts |
| Hex in JSX | ❌ | 1 literal #ffffff in ReviewCardItem.js |
| Binder / stale vocab | ✅ | No binder / Mark Owned / Save to binder in scoped UI |
backdrop-filter on cart thumbnails |
✅ | Thumbs are solid image/--bg-tertiary; no filter on <img> |
| GlassSurface / Button / Modal reuse | ⚠️ Mixed | Camera chrome + peek: GlassSurface; checkout sheet/toast/rows: glass-panel* / hand-rolled |
| Sev ≥ 3 findings | 2 | Hex literal; missing bracket + scan-line direction lock |
Maturity scoring (repo DS + this surface)
Scores 0–4. Evidence cites paths/counts.
| Axis | Score | Evidence |
|---|---|---|
| Tokens (T) | 3 | Documented 3-tier glass surface / blur / rim / elevation / scrim in docs/DESIGN_TOKENS.md + styles/globals.css. Diff mostly consumes var(--*). Residual: .glass-panel still hardcodes blur(12px) saturate(180%) (not --glass-blur-* / --glass-saturate); toast uses literal blur(12px). |
| Components (C) | 3 | Kit under components/ui/: GlassSurface, Modal, Button, Input, SearchBar, StatCard (+ chrome). Scanner adopts GlassSurface on camera bars/icons/peek (9 call sites in ScannerCamera.js); Modal×2 + Button in pages/scanner.js / checkout footer. Gaps: toast + sheet panel + cart rows skip GlassSurface. |
| Patterns (P) | 2 | Locked pattern “immersive camera + bottom-sheet checkout” partially shipped (immersive Layout, sheet shell mirroring Disambiguation, peek non-interactive). Detection chrome still filled rectangles (info/success), not ember L-brackets + scan-line. Confidence mid-band maps to gold, not direction’s amber/ember table. |
| Governance (G) | 3 | Convoy design_direction locked 2026-08-14; ui-and-theming.mdc + vocab CI; forbidden-hex-in-jsx / forbidden stale strings. No design-systems skill package in-repo (template path missing). |
| Adoption (A) | 2 | This surface: GlassSurface on live chrome/peek ✅; checkout sheet + toast + rows use utility classes / ad-hoc styles ❌; Review N pill is raw <button> with gradient (OK shape) but skips ember-rim + dead GlassSurface import. Vocab CTAs ✅. |
Composite: T3 / C3 / P2 / G3 / A2
Top leverage: Patterns (P) — implement Screen 1 bracket + scan-line recipe and align checkout sheet to GlassSurface tint="low" + toast to GlassSurface/--glass-surface-high so the locked Liquid Glass pattern reads as one system, not chrome-good / body-utility.
Direction lock
Locked fields enforced: Liquid Glass; immersive overlay + bottom sheet; ember/flame accents as rim/glow/gradient only; VOCAB CTAs; no binder; no hex; no per-card Add on peek; no backdrop-filter on cart thumbs; reuse GlassSurface / Modal / Button.
| Locked requirement | Diff status |
|---|---|
Immersive chrome="immersive" mobile |
✅ Layout.js + pages/scanner.js |
Top/bottom glass bars (--glass-surface-mid) |
✅ GlassSurface tint="mid" in ScannerCamera.js |
L-brackets --accent-flame / --accent-ember + scan-line |
❌ Filled border boxes + --color-info / --color-success overlays; no scan-line / prefers-reduced-motion gate |
| Scan peek glass, tap-to-cart only | ✅ ScannerScanPeek.js |
| Toast glass-high + SVG check | ⚠️ SVG ✅; surface is rgba(--bg-secondary-rgb) + literal blur, not GlassSurface / --glass-surface-high |
Review N gradient + --ember-rim-pronounced |
⚠️ Gradient ✅; no ember rim; unused GlassSurface import |
Sheet scrim --modal-scrim + blur-high |
✅ ScannerCheckoutSheet.js styled-jsx |
Sheet panel --glass-surface-low via GlassSurface |
❌ glass-panel-strong → surface-high recipe |
| Footer VOCAB + Button primary/ghost | ⚠️ VOCAB ✅; secondary uses variant="secondary" not ghost |
| Confidence rings tokenized (green / amber / orange) | ⚠️ Tokens used; mid=--accent-gold, low=--color-warning vs lock’s ember/amber table |
| No hex / no binder | ❌ one #ffffff; binder clear |
| Modal for leave + list picker | ✅ |
| No backdrop on thumbnails | ✅ |
Token audit (3-tier)
| Tier | Expectation | Diff notes |
|---|---|---|
| Primitives | Palette / RGB triples in CSS only | No new hex in CSS from this diff. JSX #ffffff violates consumer rule. |
| Aliases | --glass-surface-*, --glass-blur-*, rims, scrim |
Camera/scrim/peek mostly correct. Toast blur literal 12px should be var(--glass-blur-low). .glass-panel utility (row list) still non-token blur/saturate (pre-existing; amplified by N cart rows). |
| Components | GlassSurface / Button / Modal compose aliases | Sheet + toast + rows compose utilities/hand styles instead of primitives. |
Component / adoption audit (scoped surface)
| Element | Expected | Actual | Rate |
|---|---|---|---|
| Glass chrome bars | <GlassSurface> |
Yes (ScannerCamera) |
High |
| Scan peek | <GlassSurface> |
Yes | High |
| Toast | <GlassSurface tint="high"> or equivalent |
Hand-rolled | Low |
| Checkout sheet panel | <GlassSurface tint="low"> |
glass-panel-strong |
Low |
| Cart rows | GlassSurface high or solid --bg-secondary |
.glass-panel (blur per row) |
Medium — OK container glass; GPU stack risk |
| Footer CTAs | <Button> |
Yes | High |
| Leave / List dialogs | <Modal> |
Yes | High |
| Review N | Button or GlassSurface + ember rim | Raw <button> + gradient |
Medium |
Missing primitive usage (not missing primitives): toast + sheet should compose existing GlassSurface rather than inventing parallel glass.
Findings
Severity 0–4. Cap prioritized; sev ≥ 3 blocks merge recommendation for DS gate.
| ID | Sev | Finding | Evidence | Fix |
|---|---|---|---|---|
| DS-1 | 3 | Hardcoded hex in JSX | ReviewCardItem.js qty + button color: '#ffffff' |
Use theme-safe token (e.g. dark-theme --text-primary on ember fill, or shared on-accent pattern used by <Button variant="primary">) |
| DS-2 | 3 | Direction lock: detection chrome ≠ L-brackets + scan-line | ScannerCamera.js filled rect overlays via overlayBorderColor (--color-info / --color-success); no bracket SVG/corners; no ember scan-line / reduced-motion |
Ship Screen 1 bracket recipe (--accent-ember / --accent-flame) + gradient scan-line; disable loop under prefers-reduced-motion |
| DS-3 | 2 | Toast bypasses glass recipe | ScannerToast.js: rgba(var(--bg-secondary-rgb), 0.9) + backdropFilter: 'blur(12px)' |
Wrap with `<GlassSurface tint="high" blur="low |
| DS-4 | 2 | Checkout sheet panel wrong surface tier + no GlassSurface | ScannerCheckoutSheet.js glass-panel-strong (high) for panel + sticky footer |
Panel: GlassSurface tint="low" inside scrim; footer sticky on same recipe or solid inner; match Modal panel docs |
| DS-5 | 2 | Review N missing ember-pronounced rim; dead import | ScannerCountPill.js imports GlassSurface unused; no --ember-rim-pronounced; text-white utility |
Apply rim via GlassSurface as="button" rim="ember-pronounced" or box-shadow token; remove dead import; avoid raw white |
| DS-6 | 2 | Confidence band colors drift from lock | confidenceRingColor: <70 --color-warning, 70–84 --accent-gold, else success |
Align to lock: <70 --accent-ember, 70–84 amber/warning token, ≥85 --color-success |
| DS-7 | 1 | Secondary CTA variant | Checkout footer Button variant="secondary" |
Prefer variant="ghost" per design direction |
| DS-8 | 1 | Leave-modal dismiss copy | pages/scanner.js label "Stay" |
Direction: primary dismiss "Keep scanning" |
| DS-9 | 1 | Hardcoded vocab fallback | ReviewCardItem.js 'My Collection' string |
VOCAB.MY_COLLECTION |
| DS-10 | 1 | Stacked row backdrop-filter via .glass-panel |
Each cart row blurs (blur(12px) in utility) |
Prefer solid --bg-secondary (or GlassSurface without stacking N blurs) for row inners over thumbs — thumbs themselves are clean |
Passes (not findings)
- No
"binder"/"Save to binder"/"Mark Owned"in scoped UI. - Checkout CTAs import
VOCAB.ADD_TO_MY_COLLECTION/VOCAB.ADD_TO_LIST. - List picker uses
collectionDisplayName. - Peek has no Add / condition / foil; single open-cart control.
- Toast icons are SVG (no emoji glyphs).
- Scrim uses
--modal-scrim+var(--glass-blur-high). - Cart thumbnails: no
backdrop-filter. - Leave + List picker use
<Modal>; commit CTAs use<Button>.
Governance notes
- Contribution path for glass:
docs/DESIGN_TOKENS.md+ui-and-theming.mdc(“reach forcomponents/ui/first”). - CI: hex-in-JSX + stale vocab gates apply — DS-1 will fail / should fail
forbidden-hex-in-jsx. - Design-systems skill/templates not present under
.cursor/skills/design-systems/— maturity G capped partly by missing shared audit tooling in-repo.
Recommendation
Do not treat DS as merge-clean until DS-1 and DS-2 are fixed. DS-3–DS-6 are the follow-up pass that makes checkout/toast/pill match the same Liquid Glass composition as the camera chrome.
Child tasks (sev ≥ 3):
- Replace
#ffffffinReviewCardItem.js(and any siblingtext-whiteon detection badges if hex-gate/token policy treats them as on-accent debt). - Implement ember/flame L-brackets + reduced-motion-aware scan-line on the viewfinder per locked Screen 1.
Hand-off
DS audit complete. Maturity: T3/C3/P2/G3/A2. Top leverage: invest in Patterns (brackets/scan-line + sheet/toast GlassSurface alignment). Sev ≥ 3 findings: 2. Report: .convoys/scanner-mobile-checkout/audits/design-system-20260814.md.