diff --git a/mockups/README.md b/mockups/README.md index 690fd4e85e..63d267e2c7 100644 --- a/mockups/README.md +++ b/mockups/README.md @@ -45,7 +45,7 @@ Some document-search mockups include live handoff routes (for example `document- ## Phone Choose mode sheet YES comps -Runnable study at [`/mockups/phone-mode-sheet-yes`](../src/app/mockups/phone-mode-sheet-yes/page.tsx): design review of the shipping phone mode sheet plus **YES 01 perfected** (sectioned clinical list — shipping recommendation) and YES 02 (icon deck alternate). Shared mockup chrome is suppressed so only the in-frame sheet is judged. +Runnable study at [`/mockups/phone-mode-sheet-yes`](../src/app/mockups/phone-mode-sheet-yes/page.tsx): design review plus **YES 01 dense glance list** (flat title-only catalogue, no Find/Diagnose/Care lanes — shipping recommendation). Organised icon-deck is shown as a rejected contrast. Shared mockup chrome is suppressed so only the in-frame sheet is judged. ## Mode-page redesign comps (2026-07-31) diff --git a/src/app/mockups/phone-mode-sheet-yes/page.tsx b/src/app/mockups/phone-mode-sheet-yes/page.tsx index d8c475c253..5059ce273f 100644 --- a/src/app/mockups/phone-mode-sheet-yes/page.tsx +++ b/src/app/mockups/phone-mode-sheet-yes/page.tsx @@ -3,9 +3,9 @@ import type { Metadata } from "next"; import { PhoneModeSheetYesMockups } from "@/components/phone-mode-sheet-yes-mockups"; export const metadata: Metadata = { - title: "Phone mode sheet YES 01 perfected - Clinical KB", + title: "Phone mode sheet dense glance list - Clinical KB", description: - "Perfected phone Choose mode sheet: sectioned clinical list with all review findings closed, plus the icon-deck alternate.", + "Phone Choose mode sheet redesigned for glance picking: dense title-only flat list without Find/Diagnose/Care organisation.", }; export default function PhoneModeSheetYesMockupPage() { diff --git a/src/components/phone-mode-sheet-yes-mockups.tsx b/src/components/phone-mode-sheet-yes-mockups.tsx index 914e0f3118..11d4820c50 100644 --- a/src/components/phone-mode-sheet-yes-mockups.tsx +++ b/src/components/phone-mode-sheet-yes-mockups.tsx @@ -18,9 +18,9 @@ import { appModeDefinitions, visibleAppModeDefinitions, type AppModeId } from "@ /** * Design scratch: phone "Choose mode" sheet — review + YES comps. * - * YES 01 (sectioned list) is the perfected master: every review finding closed, - * sticky offset debt removed, current mode folded into the sheet header, and - * selection is interactive so the study can be judged as a real switcher. + * YES 01 is a dense glance list: no Find/Diagnose/Care sections. Organisation + * slowed picking; height goes to modes. Keyboard roving, contained preview + * scroll, and lifted selection into the phone frame stay. */ type GroupId = "find" | "diagnose" | "care"; @@ -64,60 +64,45 @@ function modeOf(id: AppModeId) { const reviewFindings = [ { severity: "P1", - title: "Flat list, no clinical intent", + title: "Hard to pick at a glance", detail: - "Thirteen equal-weight rows force linear scanning. Answer, DSM, and Medication compete visually even though they serve different jobs.", + "Section headers, hints, counts, and roomy rows spend height on organisation. On a phone sheet that means fewer modes visible and more scrolling before you can choose.", }, { severity: "P1", title: "Descriptions truncate on phone", detail: - "Live rows use `truncate` on a single line, so the subtitle that differentiates modes disappears on a 390 px sheet.", + "Live rows use `truncate` on a single line — fine for density if the title carries the choice. Titles must stay fully readable.", }, { severity: "P2", - title: "Selected state is easy to miss mid-scroll", - detail: - "Soft fill + check is correct, but there is no sticky ‘current mode’ context above the list, so returning from a long scroll loses place.", - }, - { - severity: "P2", - title: "Thumb targets are dense for a primary switcher", - detail: - "32 px icon wells inside 52 px rows pack the sheet, but the mode switcher is a high-frequency control — it should feel larger than a desktop menu ported down.", + title: "Selected state is easy to miss", + detail: "Soft fill alone is weak mid-list. A left rail + check keeps place without a second sticky card.", }, { severity: "P3", title: "Header copy is generic", detail: - "‘Choose mode / Switch the clinical workspace mode’ names the UI, not the clinician’s current place. A current-mode line orients faster.", + "‘Choose mode / Switch the clinical workspace mode’ names the UI. A one-line Currently · {mode} orients faster.", }, ] as const; const perfectedResolutions = [ { - issue: "Flat catalogue", - fix: "Find / Diagnose / Care sections with sticky labels and counts — scan by clinical job.", + issue: "Organisation tax", + fix: "No Find / Diagnose / Care sections, sticky labels, or count badges — one flat list.", }, { - issue: "Truncated subtitles", - fix: "Two-line `line-clamp-2` descriptions; inactive titles stay full `--text-heading` weight.", + issue: "Wasted vertical space", + fix: "Title-only min-h-12 rows (32 px icons) so the full production catalogue fits in one glance.", }, { - issue: "Lost place mid-scroll", - fix: "Current mode lives in the non-scrolling sheet header; section labels stick at `top-0` — no fragile offset.", + issue: "Lost selection", + fix: "Header Currently · {mode} plus soft fill, left rail, and check — no bulky current card.", }, { - issue: "Dense thumb targets", - fix: "`min-h-12` rows, 44 px icon wells, 10 px row gap rhythm — primary switcher, not a desktop menu port.", - }, - { - issue: "Generic header", - fix: "Header reads “Currently · Answer” with the live icon; updates when you pick another mode.", - }, - { - issue: "Duplicate current chrome", - fix: "Removed the bulky sticky “Now in” card that stole first-viewport height and repeated the selected row.", + issue: "Keyboard / scroll a11y", + fix: "Arrow/Home/End roving focus; preview scroll stays inside the sheet body.", }, ] as const; @@ -130,28 +115,28 @@ const variants: Array<{ }> = [ { id: "sections", - title: "Sectioned clinical list — perfected", - verdict: "YES · Master for intent", + title: "Dense glance list", + verdict: "YES · Fastest pick", description: - "Every review finding closed. Current mode sits in the sheet header, section labels are the only sticky layer, rows are phone-native, and selection is interactive. This is the direction to land.", + "Flat catalogue, no clinical lanes. Most modes visible at once; pick by name without scrolling through section chrome. This is the shipping recommendation.", changes: [ - "Header carries “Currently · {mode}” — orients without a second card.", - "Sticky section labels only (`top-0`); no magic `4.6rem` offset under a strip.", - "`min-h-12` rows, 44 px wells, two-line descriptions, readable inactive titles.", - "Tap a mode: header and selection update together — proven in the Switched frame.", + "No Find / Diagnose / Care headers, hints, or counts.", + "Title-only min-h-12 rows — descriptions stay in aria-label, not the scan line.", + "Header carries Currently · {mode}; selection lifts into the top-bar pill.", + "Arrow/Home/End roving focus; proof-frame scroll stays inside the sheet.", ], }, { id: "deck", title: "Icon deck with lane chips", - verdict: "YES · Best overview", + verdict: "Not recommended", description: - "Two-column mode cards plus Find / Diagnose / Care filter chips. Prefer this if browsing all modes matters more than a vertical reading order. YES 01 remains the shipping recommendation.", + "Find / Diagnose / Care organisation plus roomy cards. Shown only to contrast why glance picking loses with this layout.", changes: [ - "Lane chips filter the deck without opening a second surface.", - "Current mode sits in a full-width identity card above the grid.", - "Cards are icon-forward with two-line labels; selected card uses accent ring + check.", - "Same Sheet chrome (grip, title, close, safe-area) so the concept can drop into the live Sheet.", + "Lane chips and section labels spend height on organisation.", + "Current-mode identity card and two-line card copy add more chrome.", + "Fewer modes visible before scroll — harder to choose at a glance.", + "Kept as a rejected alternate, not a shipping candidate.", ], }, ]; @@ -368,61 +353,53 @@ function ModeRow({ type="button" role="menuitemradio" aria-checked={active} + aria-label={`${mode.label}. ${mode.description}`} tabIndex={tabIndex} onClick={() => onSelect(modeId)} onKeyDown={(event) => onKeyDown(event, index)} style={{ animationDelay: `${Math.min(index, 8) * 28}ms` }} className={cn( - "relative grid min-h-12 w-full grid-cols-[2.75rem_minmax(0,1fr)_1.75rem] items-center gap-2.5 rounded-xl px-2.5 py-2.5 text-left transition-[background-color,color,box-shadow] duration-[var(--duration-fast)] ease-[var(--ease-out-soft)] motion-safe:animate-[cascade-fade-up_var(--duration-moderate)_var(--ease-out-soft)_both] motion-reduce:animate-none motion-reduce:transition-none", + "relative grid min-h-12 w-full grid-cols-[2rem_minmax(0,1fr)_1.25rem] items-center gap-2 rounded-lg px-2 py-1 text-left transition-[background-color,color] duration-[var(--duration-fast)] ease-[var(--ease-out-soft)] motion-reduce:transition-none", focusRing, active - ? "bg-[color:var(--clinical-accent-soft)] text-[color:var(--text)] shadow-[var(--shadow-inset)]" + ? "bg-[color:var(--clinical-accent-soft)] text-[color:var(--text)]" : "text-[color:var(--text)] hover:bg-[color:var(--surface-subtle)]", )} > {active ? (