diff --git a/.design-sync/conventions.md b/.design-sync/conventions.md index 7a726287f..e466ef2ee 100644 --- a/.design-sync/conventions.md +++ b/.design-sync/conventions.md @@ -30,19 +30,28 @@ Dark mode is automatic via the `.dark` class — the variables flip; never write ## Class-string vocabulary (exported constants) The bundle exports ready-made class strings — compose them instead of -re-deriving surfaces: `panel`, `quietPanel`, `glassPanel`, `raisedCard`, -`insetCard`, `sourceCard`, `evidenceSurface`, `primaryControl`, -`floatingControl`, `toolbarButton`, `navPill`, `metadataPill`, `shellChip`, -`fieldLabel`, `fieldControl`, `fieldControlPlain`, `eyebrowText`, `textMuted`, -`proseMeasure`, `codeText`, `compactMetadataRow`, `iconTile`, `clinicalDivider`. -Join with the exported `cn(...)` helper. +re-deriving surfaces: `panel`, `panelSubtle`, `raisedCard`, `sourceCard`, +`answerSurface`, `primaryControl`, `floatingControl`, `toolbarButton`, +`navPill`, `metadataPill`, `subtleStatusPill`, `shellChip`, `fieldLabel`, +`fieldControl`, `fieldControlWithIcon`, `fieldControlPlain`, `fieldIcon`, +`eyebrowText`, `textMuted`, `proseMeasure`, `codeText`, `iconTilePremium`, +`clinicalDivider`, `tableCard`, `tableCardHeader`, plus the chat/search +composer and tone recipes documented in +`docs/redesign/09-ui-primitives-recipes.md`. Join with the exported `cn(...)` +helper. + +Module-private helpers (`insetCard`, `iconTile`, `compactMetadataRow`, +`toneWarningQuiet`, `controlBase`, `statusDotBase`, `chatComposerShellDelta`) +power components inside `ui-primitives.tsx` and are **not** part of the import +surface — use the exported components (`LoadingPanel`, `PanelHeading`, +`SourceProvenance`, `SourceStatusBadge`, …) or the exported recipes above. ## Example ```tsx -import { PanelHeading, quietPanel, primaryControl, cn, FileText } from ""; +import { PanelHeading, panelSubtle, primaryControl, cn, FileText } from ""; -
+
; diff --git a/docs/branch-review-ledger.md b/docs/branch-review-ledger.md index 67c97ac14..fb043ed6b 100644 --- a/docs/branch-review-ledger.md +++ b/docs/branch-review-ledger.md @@ -1047,19 +1047,20 @@ This file is append-only. Never rewrite or delete an existing review record; app | 2026-07-25 | PR #1217 / `cursor/sheet-focus-hardening-c6d3` | head `65f7580ce4f4821f8d1ad55aa2c84b7e11ca62fe` / squash `20300bb9f60dee09632fdce27d1191dde19e92b5` | prlanded after squash merge | LANDED. Two-dot content diff of `src`/`tests` vs `origin/main` empty; `sheet-focus.ts` on main carries `canRestoreFocusTo`, `MAX_CONSECUTIVE_RECLAIMS`, the 10s event-driven settle window and no `setInterval`; `sheet.tsx` restores through `canRestoreFocusTo` at both call sites. Hosted PR required SUCCESS (Static/Safety/Unit/Build/Production UI/Advisory UI); post-merge push CI on `20300bb9` SUCCESS (CI, Docker image build, SAST, Secret Scan). Remote feature branch deleted by merge. The one red rollup entry was a `pull_request_target` PR Policy run cancelled by its own successor, which reported SUCCESS. | `gh pr view` state=MERGED mergedBy=BigSimmo; `git diff origin/main HEAD -- src tests` empty; `git show origin/main:...` symbol checks; `gh run list --branch main` on the squash commit. No provider-backed checks. | | 2026-07-26 | PR #1192 / `cursor/fix-mobile-composer-edge-scroll-5b1d` | head `2597dd305fd61e4e16166cccd109ff6f8eae0a33` / squash `c4d5f47a39` | prlanded after squash merge | LANDED. Phone Answer edge-dock hide/reveal, layout-clamp versus upward-intent detection, and composer focus binding, reconciled against the #1222 cross-breakpoint header. `git diff c4d5f47a 2597dd30` empty, so the content landed intact; remote branch deleted at merge; required contexts Gitleaks, PR required and PR policy all SUCCESS on the merged head. Two things worth keeping: merging `main` made the ledger's `union` driver re-append records both sides already carried, failing `check:branch-review-ledger` twice in one hour (see #082), and the final head was a `coderabbitai[bot]` auto-fix swapping an inline two-step upward scroll for the shared `scrollPrimarySurface` helper in `tests/ui-smoke.spec.ts` � an identical earlier auto-fix had been reverted on this branch, so it was re-proven rather than trusted. | `npm run verify:ui` 285/285 Chromium on the production build; `npm run verify:cheap` pass except the pre-existing `tests/pdf-extractor.test.ts` Python-OCR case, whose subject is absent from the diff (3437/3439 otherwise); `ui-chrome-scroll` + `ui-phone-scroll` 30/30 across phone, tablet and desktop; `use-hide-on-scroll` + `header-scroll-hide-contract` + `mobile-composer-reserve` 39/39; the CodeRabbit-modified in-flow collapse test re-run 3/3. No provider-backed checks. | | 2026-07-25 | origin/execute-audit-remediation-plan (PR #1188 closed tip) | `8b8639113925601e1687bfe4f1f29c44a4308b61` | branch-cleanup | DELETED remote. Tip rejected (conflict markers + parse breakers); intentional maintainability work already on main via #1213 (`8e3a49d0`). IMP-04 mockup/export prune from tip commit `3bc391dff` was not ported (knip-only unexports; optional follow-up). Local Antigravity worktrees left untouched. | Content proof: notices/utils/Sheet autofocus on origin/main; tip marker count 12; `git push origin --delete execute-audit-remediation-plan`. No provider calls. | +| 2026-07-25 | `cursor/imp04-prune-dead-exports-01f2` | `4739510e8650e38e3c3a3cd2d8866dcf3abb8ab6` | IMP-04 safe port from rejected #1188 tip | READY. Ports dead-export prune for calculator/factsheet mockups + unused ui-primitives tokens. Deletes truly unused locals (not just unexport) so eslint max-warnings=0 stays green. Keeps Skeleton + commandInput focus shadow (tip incorrectly removed/changed those). Supersedes optional follow-up noted on #1188 branch-cleanup row. | typecheck; eslint on touched files. No provider calls. | | 2026-07-25 | PR #1195 / `subagent-Asset-Optimization-Implementer-self-b295a5bb` | `c612c88aae386a29715cadfb5dbd2b95163e1dc9` | prlanded after squash merge | MERGED. Squash tip `c612c88aa` on main; remote feature branch deleted. Product content verified on main (`check:assets`, icon Cache-Control, SignedImage/non-PDF a11y). Local review worktree retained for optional cleanup. | gh pr view MERGED; two-dot product-file diff empty vs origin/main; no provider checks. | - +| 2026-07-26 | PR #1238 / `cursor/header-hide-top-bar-only-4fd7` | `fdc20bfedb61a2c267c22a3d78ccc8214e6c0087` | Continue-executing: top-bar-only hide + CI green | APPROVE / MERGEABLE. Root cause fixed: collapse wraps only `header#search` (+ Therapy addon); sticky hosts pin outer [top bar \| search] below `chrome-safe-area-top` without translating search away; sticky-stack composers stay `relative`. Services rail overlay hardened (testids + center scrollIntoView); ui-tools accepts sticky ancestor; Therapy nav assert uses collapse-host top under safe-area spacer. Merged main safe-area + submitted-result focus rules. | Hosted PR required + Production UI SUCCESS on tip; contract 14/14; focused Playwright services/desktop composers 6/6, chrome-scroll 12/12, therapy-nav 1/1. No provider-backed checks. | +| 2026-07-26 | PR #1238 / `cursor/header-hide-top-bar-only-4fd7` | head `db4390b3814910d0210497e2982414904f2e0704` / squash `cdbe0e662366f9308813e8d5fe8951ca11a47d6b` | prlanded after squash merge | LANDED. Top-bar-only hide-on-scroll with sticky search stack below `chrome-safe-area-top`; two-dot content diff empty vs `origin/main`. Remote feature branch deleted at merge. Required CI green at merge (PR policy, PR required, Production UI). | `gh pr view` MERGED; `git diff origin/main db4390b3` empty; no provider-backed checks. | +| 2026-07-26 | PR #1241 / `cursor/imp04-prune-dead-exports-01f2` | `ac056083bad351659cc970171c8cd62bbb3526a5` | Codex P2: sync recipe catalogs after prune | FIXED. Updated `.design-sync/conventions.md` + `docs/redesign/09-ui-primitives-recipes.md` (plus badge/design-system mentions) so catalogs no longer advertise deleted or module-private recipes (`insetCard`, `iconTile`, `compactMetadataRow`, `commandInput`, `toneWarningQuiet`, …). | Doc grep of catalogs vs `ui-primitives` export surface; `check:branch-review-ledger`. No provider calls. | +| 2026-07-26 | PR #1241 / `cursor/imp04-prune-dead-exports-01f2` | `2c6d9c96` merge of `origin/main` `5475fcfb` | Main sync after GitHub CONFLICTING | SIMPLE. `git merge-tree --write-tree` clean before merge; GitHub DIRTY was staleness behind #1227/#1245/#1200. Ledger union auto-merge. Calculator path rename `calculator-mockups`→`calculators` detected; IMP-04 dead-export prune content carried onto new paths (`calculatorById`/`useCalculatorState` still absent). No conflicting intents; no conflict markers. | merge-tree clean; merge ort; `check:branch-review-ledger`; `tsc --noEmit` clean; no stale calculator-mockups imports. No provider calls. | | 2026-07-26 | PR #1246 / `codex/standardize-header-and-footer-behavior` | `b51ee15e6961d46a14c288f621d25ab30a434c7d` | Explicit CI-failure review and focused repair | APPROVE pending hosted required CI. All three completed CI failures were the same new Playwright assertion: `/formulation/worry` legitimately omits the optional legacy dock backdrop, but the test required `display: none` and received `missing`; the downstream `PR required` failure was only the aggregate. Updated the test to accept absence or require `none` when rendered; no high-confidence product defect remains. | Focused Vitest 11/11; Prettier, ESLint and `git diff --check` pass; exact local Chromium rerun blocked by the shared heavyweight lock owned by another worktree, so hosted Production UI is the merge gate. | - | 2026-07-26 | PR #1246 / `codex/standardize-header-and-footer-behavior` | `e1f7dad583465a10231abc058ee4320177998894` | Post-review main sync and stable-CI retrigger | APPROVE pending hosted required CI. The automated branch-sync merge brought current `main` (`b91b4600171be08198e92bcf19b7d67e8207cb2f`) into the reviewed repair without content conflicts; `skip-branch-sync` was applied to prevent another bot-head cancellation while required checks run. | `git merge-tree --write-tree` clean; three-dot PR scope unchanged except the required ledger record; hosted CI retrigger pending. | - | 2026-07-26 | PR #1246 / `codex/standardize-header-and-footer-behavior` | `de4864ef06626931ecd6bd22b97387f80f529cb2` | Production UI second-failure repair | APPROVE pending final hosted required CI. The first repair exposed a second invalid assumption in the same new test: `/formulation/worry` does not own a fixed phone dock, so geometry used the `-1` missing sentinel. Replaced it with the established submitted Forms result route, explicitly waiting for the dock and unfocused composer before asserting paint and scroll-hide geometry. | Exact focused production Chromium test pass 1/1 (isolated Next build); Prettier, ESLint and `git diff --check` pass; prior hosted run had 290/291 Production UI tests pass with this single invalid-route assertion. | - | 2026-07-26 | PR #1246 / `codex/standardize-header-and-footer-behavior` | `547d3a100c73333895554cf66eb0efd8d8dde8da` | Late unresolved review-thread verification and fix | APPROVE pending final hosted required CI. Confirmed the open P2 despite a bot summary claiming it was fixed: opaque phone `.edge-glass-header` / `.universal-header` still inherited `backdrop-blur-xl`. Added standard and WebKit `backdrop-filter: none` overrides and static/computed-style guards. | Prettier, ESLint and `git diff --check` pass; focused local Vitest/browser reruns blocked by consecutive legitimate shared-lock owners, so hosted Static/Unit/Production UI remain the merge gate. | - | 2026-07-26 | PR #1256 / `codex/pr1246-header-blur-followup` | correction to `547d3a100c73333895554cf66eb0efd8d8dde8da` | CSS prefix contract correction | FIXED. Hosted Unit coverage exposed the repository guard forbidding hand-authored `-webkit-backdrop-filter`; retained the standard `backdrop-filter: none` source rule and removed the duplicate vendor declaration, which the CSS toolchain owns. This supersedes only the prior row's claim that both declarations should be authored. | Targeted `clinical-dashboard-merge-artifacts` and mobile paint contract rerun required; Production UI continued separately. | - -| 2026-07-26 | PR #1238 / `cursor/header-hide-top-bar-only-4fd7` | `fdc20bfedb61a2c267c22a3d78ccc8214e6c0087` | Continue-executing: top-bar-only hide + CI green | APPROVE / MERGEABLE. Root cause fixed: collapse wraps only `header#search` (+ Therapy addon); sticky hosts pin outer [top bar \| search] below `chrome-safe-area-top` without translating search away; sticky-stack composers stay `relative`. Services rail overlay hardened (testids + center scrollIntoView); ui-tools accepts sticky ancestor; Therapy nav assert uses collapse-host top under safe-area spacer. Merged main safe-area + submitted-result focus rules. | Hosted PR required + Production UI SUCCESS on tip; contract 14/14; focused Playwright services/desktop composers 6/6, chrome-scroll 12/12, therapy-nav 1/1. No provider-backed checks. | -| 2026-07-26 | PR #1238 / `cursor/header-hide-top-bar-only-4fd7` | head `db4390b3814910d0210497e2982414904f2e0704` / squash `cdbe0e662366f9308813e8d5fe8951ca11a47d6b` | prlanded after squash merge | LANDED. Top-bar-only hide-on-scroll with sticky search stack below `chrome-safe-area-top`; two-dot content diff empty vs `origin/main`. Remote feature branch deleted at merge. Required CI green at merge (PR policy, PR required, Production UI). | `gh pr view` MERGED; `git diff origin/main db4390b3` empty; no provider-backed checks. | | 2026-07-26 | cursor/formulation-a11y-linear2-14d4 (PR #1250) | head `14b4e80ee41b16a80c974b6a1f8201407a0df05b` / squash `b91b4600171be08198e92bcf19b7d67e8207cb2f` | prlanded after squash merge | LANDED. Formulation disabled-state accessibility (#064) on main; product two-dot diff empty vs pre-merge tip. Superseded conflicted PRs #1219, #1223, #1226, #1231, #1249 closed. Remote feature branch deleted at merge. | Focused Chromium formulation 7/7; verify:cheap 3473 tests; hosted Production UI + PR required SUCCESS; `git diff 14b4e80e origin/main -- formulation-builder-page.tsx ui-formulation.spec.ts` empty. No provider-backed checks. | +| 2026-07-26 | PR #1241 / `cursor/imp04-prune-dead-exports-01f2` | merge `origin/main` `6fd8902b` | Main sync after GitHub CONFLICTING | SIMPLE. Staleness behind #1256/#1246/#1252/#1251. `git merge-tree` clean; only overlapping path was append-only ledger. Dropped 2 exact-duplicate #1238 rows re-appended by union driver (kept earlier copies). No product conflict markers; IMP-04 prune surface unchanged. | merge-tree clean; merge ort; `check:branch-review-ledger`; no provider calls. | | 2026-07-26 | `codex/test-concurrency-20260726` | `1b1f4817b0cf932d8b43f8715725770045528f8c` | Protected-main release-readiness review of cross-worktree test concurrency | APPROVE. Shared admission is fail-closed to explicit focused Vitest selections and isolated typechecks; full suites, lint, builds, coverage and Playwright stay exclusive with queue priority and legacy-lock compatibility. Review found and fixed one blocker before approval: junctioned worktrees would have raced the shared `node_modules/.cache` TypeScript build-info file, so shared typechecks now receive a worktree-hashed temporary `.tsbuildinfo` path. Highest residual risk is Windows cross-process filesystem timing, covered by coordinator race/recovery tests and the full local gate. | `npm run verify:pr-local` PASS: format, lint, isolated typecheck, 391 files / 3489 tests passed / 2 skipped, production build (1680 static pages), client-secret scan, and 36-case offline RAG fixtures. Focused coordinator/tooling 32/32; PDF portability 3 passed / 2 platform-or-dependency skips. No provider-backed checks. | +| 2026-07-26 | PR #1241 / `cursor/imp04-prune-dead-exports-01f2` | `720fd19879f6463a87ad61309b91148f90efa23e` | PR babysit: sync main, supersede stale READY row, close review thread | APPROVE pending hosted required CI. `git merge-tree --write-tree origin/main ba799d4a3cfdcb20eb1e040b5d6e328e2fbbc147` was clean, so GitHub DIRTY/CONFLICTING was stale branch drift after main advanced to `a9920e3fc29fce9ad2ffb547811e085a708680b9`; merged `origin/main` with no content conflicts. This supersedes the older 2026-07-25 READY row rather than editing append-only history; the remaining CodeRabbit ledger-check thread is dispositioned by this row and the final merge remains gated on exact-head required CI. | `npm run check:branch-review-ledger` PASS; hosted PR required, PR policy, and GitGuardian to be waited on exact pushed head; no provider-backed evals/checks. | + +| 2026-07-26 | PR #1241 / `cursor/imp04-prune-dead-exports-01f2` | `5de2f4cdfa707ed53145b2e39a7f283995887f85` | Authorized babysit sweep | Threads: 1 CodeRabbit ledger rewrite request dispositioned (append-only policy; hosted CI already green). Merged `origin/main` (mechanical). 0 unresolved left. | Hosted required CI previously SUCCESS on prior tip; no provider-backed checks. | diff --git a/docs/clinical-badge-system-guide.md b/docs/clinical-badge-system-guide.md index fc5d02290..36a87b331 100644 --- a/docs/clinical-badge-system-guide.md +++ b/docs/clinical-badge-system-guide.md @@ -427,14 +427,14 @@ Avoid code-facing colour names such as `green`, `red`, `amber`, or `slate` for n Map semantic tones to existing tokens: -| Semantic tone | Existing style direction | -| ------------- | ------------------------------------------- | -| `neutral` | `toneNeutral` / metadata pill | -| `clinical` | clinical accent token (`--clinical-accent`) | -| `success` | `toneSuccess` | -| `warning` | `toneWarning` or `toneWarningQuiet` | -| `danger` | `toneDanger` | -| `info` | `toneInfo` | +| Semantic tone | Existing style direction | +| ------------- | --------------------------------------------------------- | +| `neutral` | `toneNeutral` / metadata pill | +| `clinical` | clinical accent token (`--clinical-accent`) | +| `success` | `toneSuccess` | +| `warning` | `toneWarning` (quiet warning is private to source badges) | +| `danger` | `toneDanger` | +| `info` | `toneInfo` | ## Accessibility Requirements diff --git a/docs/design-system.md b/docs/design-system.md index d94c2c854..8e9053868 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -95,9 +95,10 @@ Icon **glyphs** use the parallel `--spacing-icon-*` scale in `@theme`: sizes non-icons), so migrating the long tail onto `size-icon-*` is opportunistic, not enforced. - **Responsive** icons add a breakpoint variant — `size-icon-md sm:size-icon-lg`. Reserve it for a few roles (nav, composer, hero, panel headings); most icons stay one fixed size. -- **Not** for container tiles (`iconTile` h-9, empty-state tile h-10) or non-icon boxes (the - `ToggleSwitch` knob, status dots) — those keep the integer spacing scale. Icon glyph size is - independent of the 44px tap target (§3), which stays on `--spacing-tap`. +- **Not** for container tiles (`iconTilePremium` / panel-heading tile h-9, empty-state tile h-10) + or non-icon boxes (the `ToggleSwitch` knob, status dots) — those keep the integer spacing + scale. Icon glyph size is independent of the 44px tap target (§3), which stays on + `--spacing-tap`. ## 3. Spacing & tap targets diff --git a/docs/redesign/09-ui-primitives-recipes.md b/docs/redesign/09-ui-primitives-recipes.md index eb50eb4af..ae23b784d 100644 --- a/docs/redesign/09-ui-primitives-recipes.md +++ b/docs/redesign/09-ui-primitives-recipes.md @@ -15,7 +15,7 @@ gaps to reconcile. A recipe is an exported string of Tailwind utilities, composed at the call site with `cn(...)` (a `filter(Boolean).join(" ")` helper — falsey args drop out, so `cn(base, cond && extra, className)` is the standard shape). Recipes compose by -template literal (`` `${controlBase} …` `` / `` `${quietPanel} …` ``). All colour, +template literal (`` `${panelSubtle} …` `` / `` `${primaryControl}` ``). All colour, radius, shadow, and type values go through design tokens (`text-[color:var(--…)]`, `rounded-lg`, `shadow-[var(--…)]`) — never raw palette or hex (see M1/M2 in `07-token-adoption-audit.md`). @@ -23,6 +23,14 @@ or hex (see M1/M2 in `07-token-adoption-audit.md`). Recipes are **structure + resting appearance + state contract**. The call site supplies only layout deltas (width, margin, one-off padding) and behaviour. +**Export surface:** only `export const` recipes are importable. Module-private +helpers (`controlBase`, `insetCard`, `iconTile`, `compactMetadataRow`, +`toneWarningQuiet`, `statusDotBase`, `chatComposerShellDelta`) stay inside +`ui-primitives.tsx` for the React components that own them — do not re-derive +or re-export them at call sites. Prefer the exported components +(`LoadingPanel`, `PanelHeading`, `SourceProvenance`, source badges) when the +private recipe would have been the only reason to import. + ## State contract (the intended convention) Any recipe a user can click, type into, or focus should satisfy this contract. @@ -43,22 +51,20 @@ Values are tokens; the target sizes follow the `-11`/`-12` spacing scale (L6). ### Interactive controls (tap targets) -| Recipe | Purpose | Tap | Hover | Active | Focus-visible | Disabled | -| ------------------------- | --------------------------------------------- | ------------------- | ----------------- | ------ | ---------------------------------------- | -------- | -| `controlBase` | Base for buttons (composed by others) | `min-h-11` | — (subclass adds) | ✅ | ✅ | ✅ | -| `primaryControl` | Primary command button | ✅ | ✅ | ✅ | ✅ | ✅ | -| `floatingControl` | Secondary / floating button | `min-h-11` | ✅ | ❌ | ✅ | ✅ | -| `toolbarButton` | Square icon button | `h-11 w-11` | ✅ | ❌ | ✅ | ✅ | -| `navPill` | Nav / segmented pill | `min-h-11` | ✅ | ❌ | ✅ | ✅ | -| `chatMicroAction` | Small chat action (copy, retry…) | `min-h-11 min-w-11` | ✅ | ❌ | ✅ | ✅ | -| `sourceCapsuleHit` | Citation capsule tap target (button) | `min-h-11` | ✅ (drives face) | ❌ | ✅ (`.source-capsule-hit:focus-visible`) | ❌ | -| `sourceCapsule` | Compact visible pill (`.source-capsule-face`) | — (inside hit) | ✅ (via hit) | ❌ | ✅ (via hit) | ❌ | -| `sourceCapsuleCountBadge` | Inset count chip inside `sourceCapsule` | — (non-tap) | ❌ | ❌ | ❌ | ❌ | -| `chatComposerIconButton` | Composer icon button | `h-11 w-11` | ✅ | ❌ | ✅ | ✅ | -| `chatSendButton` | Composer send (accent) | `h-11 w-11` | ✅ | ❌ | ✅ | ✅ | -| `sidebarItem` | Sidebar nav row | `min-h-11` | ✅ | ❌ | ✅ | ✅ | -| `sidebarToolTile` | Sidebar tool tile | `min-h-[64px]` | ✅ | ❌ | ✅ | ❌ | -| `shellChip` | Filter / mode chip | `min-h-11` | ✅ | ❌ | ❌ | ❌ | +| Recipe | Purpose | Tap | Hover | Active | Focus-visible | Disabled | +| ------------------------- | --------------------------------------------------- | ------------------- | ---------------- | ------ | ---------------------------------------- | -------- | +| `primaryControl` | Primary command button (uses private `controlBase`) | ✅ | ✅ | ✅ | ✅ | ✅ | +| `floatingControl` | Secondary / floating button | `min-h-11` | ✅ | ❌ | ✅ | ✅ | +| `toolbarButton` | Square icon button | `h-11 w-11` | ✅ | ❌ | ✅ | ✅ | +| `navPill` | Nav / segmented pill | `min-h-11` | ✅ | ❌ | ✅ | ✅ | +| `chatMicroAction` | Small chat action (copy, retry…) | `min-h-11 min-w-11` | ✅ | ❌ | ✅ | ✅ | +| `sourceCapsuleHit` | Citation capsule tap target (button) | `min-h-11` | ✅ (drives face) | ❌ | ✅ (`.source-capsule-hit:focus-visible`) | ❌ | +| `sourceCapsule` | Compact visible pill (`.source-capsule-face`) | — (inside hit) | ✅ (via hit) | ❌ | ✅ (via hit) | ❌ | +| `sourceCapsuleCountBadge` | Inset count chip inside `sourceCapsule` | — (non-tap) | ❌ | ❌ | ❌ | ❌ | +| `chatComposerIconButton` | Composer icon button | `h-11 w-11` | ✅ | ❌ | ✅ | ✅ | +| `chatSendButton` | Composer send (accent) | `h-11 w-11` | ✅ | ❌ | ✅ | ✅ | +| `sidebarItem` | Sidebar nav row | `min-h-11` | ✅ | ❌ | ✅ | ✅ | +| `shellChip` | Filter / mode chip | `min-h-11` | ✅ | ❌ | ❌ | ❌ | ### Form fields @@ -66,30 +72,35 @@ Values are tokens; the target sizes follow the `-11`/`-12` spacing scale (L6). | -------------------------------------------- | --------------------------------------------------- | ---------------------------- | ----------------------------------------------- | | `fieldControl` | Base text input | `focus:` ring+border | `h-11`, `outline-none`, `placeholder:text-soft` | | `fieldControlWithIcon` / `fieldControlPlain` | `fieldControl` + padding for a leading icon / plain | — | compose `fieldControl` | -| `commandInput` | Large command-bar input | `focus:` ring+border | `min-h-12`, `motion-safe:transition` | | `chatComposerShell` | Composer wrapper | `focus-within:border-accent` | `min-h-[56px]` pill container | | `chatComposerInput` | Bare composer input | via shell `focus-within` | `min-h-11`, `outline-none` | | `fieldLabel` | Field label (= `eyebrowText`) | — | — | | `fieldIcon` | Absolutely-positioned leading icon | — | `pointer-events-none` | +Removed (zero importers): `commandInput`. Large search/command chrome uses +`chatComposerShell` / `chatComposerInput` (or page-owned composer classes). + ### Surfaces & cards (non-interactive unless noted) -`raisedCard`, `insetCard`, `glassPanel`, `quietPanel`, `panel`, `panelSubtle` -(= `quietPanel`), `answerSurface`, `evidenceSurface`, `tableCard`, -`tableCardHeader`. Interactive exception: **`sourceCard`** = `quietPanel` + -`hover:border-strong hover:shadow-hover` (a clickable card). -Overlay: **`sheetSurface`** / `sheetHandle` for the mobile bottom sheet -(`ui/sheet.tsx`). +**Exported:** `raisedCard`, `panel`, `panelSubtle`, `answerSurface`, `tableCard`, +`tableCardHeader`, `glassOverlaySurface`. Interactive exception: **`sourceCard`** += `panelSubtle` + `hover:border-strong hover:shadow-hover` (a clickable card). + +**Module-private:** `insetCard` (used by `LoadingPanel` only). + +Removed (zero importers): `glassPanel`, `evidenceSurface`, former aliases +`quietPanel` / `sheetSurface` / `sheetHandle`. Mobile sheet chrome lives in +`ui/sheet.tsx`, not as shared recipe exports. ### Rows | Recipe | Tap | Interactive states | | --------------------- | --------------------- | -------------------------- | -| `evidenceRow` | `min-h-12` | hover + focus-visible ✅ | -| `clinicalNotesRow` | `min-h-12` | hover + focus-visible ✅ | | `chatActionRow` | `min-h-11 sm:min-h-8` | layout row (holds actions) | | `tableMicroActionRow` | `min-h-11 sm:min-h-9` | layout row | -| `compactMetadataRow` | — | metadata line | + +Removed (zero importers): `evidenceRow`, `clinicalNotesRow`. Metadata lines use +`SourceProvenance` (private `compactMetadataRow` inside that component). ### Pills, badges, dots, tones @@ -98,16 +109,19 @@ Overlay: **`sheetSurface`** / `sheetHandle` for the mobile bottom sheet `sourceCapsuleCountBadge` for the answer sources disclosure (icon, label, tabular count, chevron). The visible pill reads compact while the hit target keeps the WCAG touch size. -- **Status dots:** `statusDotBase` + `statusDotReady` (success) / `statusDotReview` - (warning) / `statusDotMuted`. -- **Semantic tone triads** (border+bg+text, dark-mode-safe): `toneSuccess`, - `toneDanger`, `toneInfo`, `toneWarning`, `toneWarningQuiet`, `toneNeutral`. - These are the canonical tone source — hand-rolled palette tone helpers were - removed in M2; reuse these instead of re-deriving. +- **Status dots (exported):** `statusDotReady` (success) / `statusDotReview` + (warning) / `statusDotMuted`. Shared `statusDotBase` is module-private. +- **Semantic tone triads** (border+bg+text, dark-mode-safe, exported): + `toneSuccess`, `toneDanger`, `toneInfo`, `toneWarning`, `toneNeutral`. + Quieter warning (`toneWarningQuiet`) is module-private and only consumed by + `SourceDesignationBadge` / `SourceStatusBadge` — import those components + instead of re-deriving the quiet tone. These remain the canonical tone source + — hand-rolled palette tone helpers were removed in M2. ### Icon tiles & text -- **Icon tiles** (decorative, `h-9 w-9`): `iconTile`, `iconTilePremium`. +- **Icon tiles:** export **`iconTilePremium`** for call sites. Plain `iconTile` + is module-private (`PanelHeading` only). - **Text:** `textMuted`, `eyebrowText` (2xs uppercase, `tracking-[0.06em]`), `proseMeasure` (`max-w-[68ch]`), `codeText` (mono tabular for clinical codes/IDs), `chatAnswerText`. @@ -115,13 +129,13 @@ Overlay: **`sheetSurface`** / `sheetHandle` for the mobile bottom sheet ### React components -| Component | Variants / states | -| ------------------- | ------------------------------------------------------------------------------------------------------------------------ | -| `SourceStatusBadge` | tone chosen from `document_status`: `current`→success, `outdated`→danger, `review_due`→warning, else `toneWarningQuiet`. | -| `SourceProvenance` | dot-separated validation / review-date / jurisdiction / extraction-quality line; drops unknown segments. | -| `PanelHeading` | `icon` + `title` + optional `description`. | -| `LoadingPanel` | `variant: "spinner" \| "skeleton"`, `lines` (skeleton count); `role="status"` + `aria-label`. | -| `EmptyState` | `icon` + `title` + `body`. | +| Component | Variants / states | +| ------------------- | --------------------------------------------------------------------------------------------------------------------------- | +| `SourceStatusBadge` | tone chosen from `document_status`: `current`→success, `outdated`→danger, `review_due`→warning, else private quiet warning. | +| `SourceProvenance` | dot-separated validation / review-date / jurisdiction / extraction-quality line; drops unknown segments. | +| `PanelHeading` | `icon` + `title` + optional `description`. | +| `LoadingPanel` | `variant: "spinner" \| "skeleton"`, `lines` (skeleton count); `role="status"` + `aria-label`. | +| `EmptyState` | `icon` + `title` + `body`. | ## Gaps to reconcile (follow-ups, not yet fixed) @@ -129,13 +143,13 @@ Documenting the contract surfaces where recipes don't meet it. These are **a11y/consistency debts**, not covered by this doc's change: 1. ✅ **FIXED (2026-07-03).** `focus-visible` was missing on the core button family - — `controlBase`, `primaryControl`, `floatingControl`, `toolbarButton`, `navPill`. + — private `controlBase`, `primaryControl`, `floatingControl`, `toolbarButton`, `navPill`. Added the standard `focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]` block to `controlBase` (inherited by `primaryControl`), `floatingControl`, `toolbarButton`, and `navPill`. Keyboard users now get a visible focus ring on the primary buttons, matching the newer recipes (`chatSendButton`, etc.). -2. **`active:translate-y-px` only on the `controlBase` family** — other buttons +2. **`active:translate-y-px` only on the private `controlBase` family** — other buttons (`toolbarButton`, `chatSendButton`, icon buttons) have no press feedback. 3. ✅ **FIXED (2026-07-03).** Added `disabled:cursor-not-allowed disabled:opacity-50` to `navPill`, `chatMicroAction`, `chatComposerIconButton`, `sidebarItem` — they now @@ -144,10 +158,10 @@ focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]` block 4. ✅ **FIXED (2026-07-03).** `shellChip` bumped `min-h-10` → `min-h-11` (40→44px) to meet the WCAG tap minimum — it's used on a real `