Extensions like ColorZilla inject attributes (cz-shortcut-listen) into
<body> before React hydrates, causing a benign hydration mismatch.
suppressHydrationWarning on <body> is the standard fix; it only ignores
attribute diffs on <body> itself, not its children.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- chat-input: new "Add patient" pill (UserPlus) opens an intake dialog;
remounts it via a key each open for a fresh file # / cleared form. On
create it runs /patient <new#> so the record's cards open in the chat.
- add-patient-dialog: controlled Dialog + form — generated file # (with
regenerate), identity (name/age/sex/status/PCP), current vitals, and
repeatable allergies & medications. Save builds a Patient and adds it
to the store. Save disabled until a name is entered.
- lib/patients: generateFileNumber() (unique) + addPatient() (session
store; swap point for a real create API).
- patient-cards: graceful empty states (no labs / meds / problems /
visits / trend) so a brand-new sparse chart renders cleanly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
scroll-snap-align:start snapped the first card flush to the scroll-port
start, hiding the row's left padding and making the card look cut off on
the left. Drop snap-x/snap-start; the p-2 breathing room now shows on
both ends.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Each patient card is now a Dialog trigger (nativeButton=false for
accessible click/keyboard) that opens a roomier detail dialog with
expanded per-topic info (full demographics, vitals/labs min·max·latest
with a larger chart, all labs with dates, full visit notes).
- Sparkline shows the value (dot + tooltip) at the nearest reading on
mousemove; reused larger in the dialogs.
- Row padding pb-2 → p-2 so card tops and the first/last card edges
(ring/shadow/rounded corners) are no longer clipped by the scroller.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Split the overloaded card into 7 single-topic cards (Summary, Vitals,
Labs, Medications, Problems, Allergies & alerts, Visits) so the
equal-height row is evenly filled instead of stretched-and-empty.
- Add a dependency-free inline-SVG shaded-area Sparkline; Vitals shows a
heart-rate trend and Labs a headline-lab trend, fed by new vitalsTrend/
labTrend series in the fixture.
- Lighten the chat input's two surfaces so it reads as a raised layer
above the new (lighter) page background.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- globals.css: lighten --background (content panel) and deepen --sidebar so
the panel reads as a lighter neutral charcoal floating on a near-black rail,
matching the Polar reference. Pure lightness change; panel stays below
--card so cards still pop.
- patient-cards.tsx: row uses items-stretch so all cards share one height
(no more ragged/taller cards); add no-scrollbar to hide the horizontal
scrollbar while keeping scroll.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- globals.css: thin dark-themed scrollbar (Firefox + WebKit) so scroll
areas no longer show the white default; `no-scrollbar` regions still win.
- patient-cards.tsx: render the cards in a horizontal scroll row (each
w-80 shrink-0 snap-start), loading skeletons included.
- chat-input.tsx: wire the controls — Attach opens a file picker with
removable chips; Access / response mode / specialty / facility / time
range are real DropdownMenu radio selectors (via a SelectPill helper)
that remember the choice. Mic stays visual-only for now. Layout/styling
unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- chat-panel.tsx: `/10293` now triggers a lookup, not just `/patient 10293`
(regex accepts an optional `patient` keyword; matches digits only so
`/help` etc. still fall through to the normal reply).
- app/layout.tsx: make <body> a fixed h-dvh, overflow-hidden shell so the
page no longer shows its own scrollbar; each route's SidebarInset already
scrolls internally (chat = overflow-hidden, settings = overflow-y-auto).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Type `/patient <fileNumber>` to pull up a patient: a skeleton card set
appears, then fills in with summary, allergies & alerts, medications &
problems, and vitals/labs/visits — composed from existing Card/Badge/
Avatar/Separator/Skeleton primitives (no new design).
- lib/patients.ts: typed mock fixture + async getPatient() (swap point
for a real API later).
- components/chat/patient-cards.tsx: PatientResult (loading/ready/
not-found).
- chat-panel.tsx: discriminated-union message model, strict /patient
parse, async lookup with update-by-id, clinical heading.
- chat-input.tsx: relabel leftover coding-assistant controls to clinical
copy + clinical icons; layout/styling unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Base UI's Menu.GroupLabel requires a surrounding Menu.Group (unlike
Radix's standalone Label), so using DropdownMenuLabel as a bare heading
threw "MenuGroupContext is missing" at runtime. Render a <div> directly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>