From 67a290f393702f36021a470e6b00b0d1aa335227 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 10:45:47 +0000 Subject: [PATCH 1/3] feat(dictionary): retitle the search route, strip page search bars, and rebuild the sources page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four surface changes across Dictionary mode, all UI-only. Topics: the page-level topic search and the descriptive subtitle are gone. Twelve collections fit on one screen and the universal composer already searches the whole dictionary; kind filtering and sort stay as a compact toolbar carrying the visible collection count. Compare: the descriptive subtitle under the title is removed, so the header sits level with its action row. Sources: the governance page is now a read-only surface. The universal composer no longer mounts on /dictionary/sources (the route declares searchComposerVisible: false, which also releases the phone dock reserve), the source-index search field is gone, and the introductory paragraph is replaced by a four-tile stat strip carrying the same facts in checkable form. The layout is rebuilt as five numbered sections in one full-width column — the previous 20rem right rail carried only organisation coverage and left two thirds of the viewport empty beside a thirteen-row index. Coverage is now its own card section, the index splits into two columns from lg, and the page dropped "use client" since nothing on it is stateful. Search: the results band was the first element under the mode nav, so its card edge sat flush against the tab rule with no page title and no breathing room. The route now opens with its own titled header, the four result lenses moved out of the band's filter row (which the band hides below sm whenever a phone control is supplied, so they were unreachable on a phone) into a wrapping rail visible at every width, and the filter trigger rides the band's utility rail beside sort instead of a row of its own. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01QMJ4s1H93vDAUjK3KudBzZ --- .../dictionary/dictionary-catalogue-pages.tsx | 103 +++-- .../dictionary/dictionary-compare-page.tsx | 3 - .../dictionary/dictionary-sources-page.tsx | 395 ++++++++++-------- src/lib/search-shell-props.ts | 10 +- tests/search-shell-props.test.ts | 12 + 5 files changed, 300 insertions(+), 223 deletions(-) diff --git a/src/components/dictionary/dictionary-catalogue-pages.tsx b/src/components/dictionary/dictionary-catalogue-pages.tsx index 7152cc15ba..f993531047 100644 --- a/src/components/dictionary/dictionary-catalogue-pages.tsx +++ b/src/components/dictionary/dictionary-catalogue-pages.tsx @@ -168,8 +168,11 @@ export function DictionarySearchPage() { })), ]; + // The lens rail lives on the page, not in the band's `filterControls` row: the + // band hides that row below `sm` whenever a phone control is supplied, so the + // four result lenses were unreachable on a phone. One rail, every width. const lensControls = ( -
+
{lensOptions.map((option) => ( ))}
@@ -204,28 +214,40 @@ export function DictionarySearchPage() { return ( <> - setOne("sort", value === "alpha" ? "az" : "relevance", "relevance")} - filterControls={ -
- {lensControls} - {trigger("desktop")} -
- } - mobileControls={trigger("phone")} - mobileControlsPlacement="inline" - appliedFilters={appliedFilters} - onClearFilters={activeCount ? clearFilters : undefined} - /> -
+ {/* The band used to be the first thing under the mode nav, so its card + edge sat flush against the tab rule with no page title and no + breathing room. The route now opens with its own titled header, and + the band is what it is elsewhere: the result spine below the title. */} +
+

+ Clinical dictionary +

+

+ Search terms +

+
{lensControls}
+
+
+ setOne("sort", value === "alpha" ? "az" : "relevance", "relevance")} + utilityControls={
{trigger("desktop")}
} + mobileControls={trigger("phone")} + mobileControlsPlacement="inline" + appliedFilters={appliedFilters} + onClearFilters={activeCount ? clearFilters : undefined} + /> +
+
{hits.length ? ( -
+
{hits.map((hit) => { const key = hit.type === "entry" @@ -474,39 +496,34 @@ export function DictionaryTopicsPage() {

Topics

-

- Discover clinical terminology through {dictionaryTopics.length} scoped collections. -

-
- + {/* The page-level topic search was removed: twelve collections fit on + one screen, and the universal composer already searches the whole + dictionary. Kind filtering and sort stay, as a compact toolbar. */} +
+

+ {visible.length}{" "} + {visible.length === 1 ? "collection" : "collections"} +

-
+
{visible.map((topic) => { const entries = dictionaryTopicEntries(topic); return ( diff --git a/src/components/dictionary/dictionary-compare-page.tsx b/src/components/dictionary/dictionary-compare-page.tsx index e1371df91a..799a3c6875 100644 --- a/src/components/dictionary/dictionary-compare-page.tsx +++ b/src/components/dictionary/dictionary-compare-page.tsx @@ -115,9 +115,6 @@ export function DictionaryComparePage({ a, b }: { a: DictionaryEntry | null; b:

Compare terms

-

- Align two source-linked entries field by field without generating clinical advice. -

+ +
+ +
- ) : null} -
+ + + {source.title} + + {source.organisation} + + + {source.region} + + Accessed {formatAccessedOn(source.accessedOn)} + + + + + ))} + - +
- -
-
-

-

-

- Published entries carry a checked date and a scheduled review date. A source change, broken link or - material correction can trigger an earlier review. Source checks and specialist approval remain separate - states. -

-
-
-

Corrections

-

- Potential errors are triaged against the cited source, corrected with an audit trail, and returned to the - independent review queue when wording or scope changes. Do not include patient-identifying information in - a correction report. -

-
-
Reference terminology · Not patient-specific guidance · Source checking is not specialist approval diff --git a/src/lib/search-shell-props.ts b/src/lib/search-shell-props.ts index 8590ecd627..a4fa850ae3 100644 --- a/src/lib/search-shell-props.ts +++ b/src/lib/search-shell-props.ts @@ -88,7 +88,15 @@ export function searchShellPropsForPathname(pathname: string): SearchShellPathPr } if (pathname.startsWith("/dictionary")) { - return { initialMode: "dictionary", desktopSearchPlacement: "hero" }; + // `/dictionary/sources` is a read-only governance page — the source method, + // the authority hierarchy, the index and the review cadence. Nothing on it + // is searched, so it carries no composer (the mode nav still reaches every + // other dictionary surface). Every other dictionary route keeps one. + return { + initialMode: "dictionary", + desktopSearchPlacement: "hero", + ...(pathname === "/dictionary/sources" ? { searchComposerVisible: false } : {}), + }; } return { initialMode: "answer" }; diff --git a/tests/search-shell-props.test.ts b/tests/search-shell-props.test.ts index b39b076779..720fd702c9 100644 --- a/tests/search-shell-props.test.ts +++ b/tests/search-shell-props.test.ts @@ -46,6 +46,18 @@ describe("searchShellPropsForPathname", () => { expect(searchShellPropsForPathname("/")).toEqual({ initialMode: "answer" }); }); + it("keeps the composer on dictionary search surfaces and drops it on the governance page", () => { + expect(searchShellPropsForPathname("/dictionary/search")).toEqual({ + initialMode: "dictionary", + desktopSearchPlacement: "hero", + }); + expect(searchShellPropsForPathname("/dictionary/sources")).toEqual({ + initialMode: "dictionary", + desktopSearchPlacement: "hero", + searchComposerVisible: false, + }); + }); + it("assigns calculator home and results search to the shared shell", () => { expect(searchShellPropsForPathname("/calculators")).toEqual({ initialMode: "calculators", From a40827ad71f1f133c9fc25b09a651243fe130ac8 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 10:50:00 +0000 Subject: [PATCH 2/3] docs(ledger): record the dictionary UI review Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01QMJ4s1H93vDAUjK3KudBzZ --- ...513501ba8e6a5088ccb5e089481047931ea74fd8400f3f390a3.record.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/branch-review-records/3cefd0b317247513501ba8e6a5088ccb5e089481047931ea74fd8400f3f390a3.record.md diff --git a/docs/branch-review-records/3cefd0b317247513501ba8e6a5088ccb5e089481047931ea74fd8400f3f390a3.record.md b/docs/branch-review-records/3cefd0b317247513501ba8e6a5088ccb5e089481047931ea74fd8400f3f390a3.record.md new file mode 100644 index 0000000000..053588280d --- /dev/null +++ b/docs/branch-review-records/3cefd0b317247513501ba8e6a5088ccb5e089481047931ea74fd8400f3f390a3.record.md @@ -0,0 +1 @@ +| 2026-08-18 | claude/dictionary-mode-ui-updates-uwoicy | 67a290f393702f36021a470e6b00b0d1aa335227 | Dictionary UI: topics/compare copy removal, sources page rebuild + composer suppression, search route header | approved | lint, typecheck, test (670 files/7149 tests), ui-dictionary + ui-mode-nav-density + ui-route-coverage Chromium (70 passed) | From 61c04debe0b46e15e92e0d1fe6ef7ed5d38c8127 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 18 Aug 2026 11:50:07 +0000 Subject: [PATCH 3/3] docs: record Run PR sweep review for PR #2114 Run PR sweep found this PR already clean (all required checks green, no unresolved review threads); the only action was syncing the branch from main via GitHub's update-branch API. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_015qDHwBNZYyRLdJHqSkiYTg --- ...2726b0e31499f86e26f9e51b9ab0d231421d15e91bed9e13665.record.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/branch-review-records/2def7e3195b192726b0e31499f86e26f9e51b9ab0d231421d15e91bed9e13665.record.md diff --git a/docs/branch-review-records/2def7e3195b192726b0e31499f86e26f9e51b9ab0d231421d15e91bed9e13665.record.md b/docs/branch-review-records/2def7e3195b192726b0e31499f86e26f9e51b9ab0d231421d15e91bed9e13665.record.md new file mode 100644 index 0000000000..6e78cc358d --- /dev/null +++ b/docs/branch-review-records/2def7e3195b192726b0e31499f86e26f9e51b9ab0d231421d15e91bed9e13665.record.md @@ -0,0 +1 @@ +| 2026-08-18 | claude/dictionary-mode-ui-updates-uwoicy (PR #2114) | 189df34d69c01fe08f17df5e49dc0cf2ca37d9c6 | Run PR sweep: CI fix + threads + drift | Before: all required checks already green (PR required success), 0 unresolved review threads, 3 bot-only PR comments (Codex usage limit, Supabase no-op, CodeRabbit rate limit) needing no action. Branch was behind main (mergeable_state: behind). Action: synced via GitHub update-branch API (clean merge, no conflicts) -> new head 189df34d69c01fe08f17df5e49dc0cf2ca37d9c6. After: fresh CI running on synced head, no code changes made, no threads to resolve. | No local gates run — PR already had npm run lint/typecheck/test/verify:ui results in its own description and no code was touched by this sweep; only a GitHub-side branch sync was performed. No provider-backed checks run. |