From 9b17d444b6587cb3258d9acab5eb6ebf0565690a Mon Sep 17 00:00:00 2001 From: BigSimmo <87357024+BigSimmo@users.noreply.github.com> Date: Sat, 11 Jul 2026 03:09:22 +0800 Subject: [PATCH 1/3] feat: redesign documents search page - Compact "Also in your library" into a slim chip row (opt-in compact variant of CrossModeLinksStrip; answer surface keeps existing cards) - Remove the decorative inner icon sidebar (dead chrome, no handlers) - Make the category rail a real source-category filter with live counts, mirrored as chips below xl - De-noise the results table: single evidence badge with page, no chunk slugs or negative pills, one review line, labeled accent Open button, meta line without mid-word truncation - Distinct Best match badge (filled accent + sparkles) with gradient featured-row wash; align mobile cards with the same treatment - Drop disabled "coming soon" header controls; results count on all breakpoints Co-Authored-By: Claude Fable 5 --- .../clinical-dashboard/cross-mode-links.tsx | 69 ++- .../master-document-flow-mockups.tsx | 478 ++++++++---------- 2 files changed, 279 insertions(+), 268 deletions(-) diff --git a/src/components/clinical-dashboard/cross-mode-links.tsx b/src/components/clinical-dashboard/cross-mode-links.tsx index 0030ad7e5..c37754930 100644 --- a/src/components/clinical-dashboard/cross-mode-links.tsx +++ b/src/components/clinical-dashboard/cross-mode-links.tsx @@ -33,6 +33,8 @@ function badgeChipTone(tone: CrossModeLinkBadge["tone"]): SemanticChipTone | nul return tone === "clinical" ? "info" : tone; } +type CrossModeLinksVariant = "card" | "compact"; + type CrossModeLinkCardProps = { link: CrossModeLink; Icon: LucideIcon; @@ -133,6 +135,46 @@ function CrossModeLinkCard({ link, Icon, query, onModeSearch }: CrossModeLinkCar ); } +// Compact one-line variant of the card: a small rectangle with the entity +// name and mode label linking to the reference, plus a square trailing +// button that re-runs the search inside that mode. Used where vertical +// space matters (e.g. the documents search page). +function CrossModeLinkChip({ link, Icon, query, onModeSearch }: CrossModeLinkCardProps) { + return ( +
+ logCrossModeLinkOpen(query, link)} + className="inline-flex min-h-11 min-w-0 items-center gap-2 px-2.5 transition hover:text-[color:var(--clinical-accent)] focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-[color:var(--focus)] md:min-h-9" + > + + + + + {link.title} + + + {link.modeLabel} + + + +
+ ); +} + // Self-contained cross-mode links surface: owns the catalog fetching (same // owner-scoped APIs the modes use; fixtures in demo mode), entity matching, // and the strip. Mount it under any search-results surface and pass the @@ -141,11 +183,13 @@ export function CrossModeLinksSection({ queries, enabled = true, onModeSearch, + variant = "card", }: { queries: Array; enabled?: boolean; // Defaults to navigating to the target mode with the search pre-run. onModeSearch?: (mode: AppModeId, query: string) => void; + variant?: CrossModeLinksVariant; }) { const router = useRouter(); const services = useRegistryRecords("service", { enabled }); @@ -187,28 +231,38 @@ export function CrossModeLinksSection({ router.push(appModeHomeHref(mode, { query, focus: true, run: true })); }); - return ; + return ( + + ); } export function CrossModeLinksStrip({ links, onModeSearch, query = "", + variant = "card", }: { links: CrossModeLink[]; onModeSearch: (mode: AppModeId, query: string) => void; // The search text that produced the links; used only for click telemetry. query?: string; + variant?: CrossModeLinksVariant; }) { if (links.length === 0) return null; + const compact = variant === "compact"; + const LinkItem = compact ? CrossModeLinkChip : CrossModeLinkCard; + return (
-

+

Also in your library {links.length > 1 ? ( @@ -222,13 +276,18 @@ export function CrossModeLinksStrip({ role="list" tabIndex={links.length > 1 ? 0 : undefined} aria-label={links.length > 1 ? "Related library matches; scroll horizontally for more" : undefined} - className="cross-mode-links-rail polished-scroll grid gap-2 overflow-x-auto overscroll-x-contain pb-1 md:flex md:w-max md:max-w-full md:gap-2.5" + className={cn( + "cross-mode-links-rail polished-scroll overflow-x-auto overscroll-x-contain pb-1", + compact + ? "flex min-w-0 items-center gap-2 md:pb-0" + : "grid gap-2 md:flex md:w-max md:max-w-full md:gap-2.5", + )} data-testid="cross-mode-links-rail" > {links.map((link) => { const Icon = appModeIcons[link.modeId]; return ( - > = { + "Clinical Guidelines": "Guidelines", + "Guideline Summary": "Guidelines", + Procedure: "Procedures", + Reference: "Reference", + "Clinical Review": "Reference", +}; + +function documentMatchesCategory(document: DocumentFixture, category: SourceCategory) { + return category === "All sources" || sourceCategoryMap[document.source] === category; +} const monitoringTableHeadings = ["Treatment duration", "Frequency", "Test", "Action threshold"] as const; const monitoringTableRows = [ ["0 - 18 weeks", "Weekly", "Full Blood Count (ANC)", "ANC < 1.5 x10^9/L"], @@ -349,6 +351,15 @@ function Pill({ ); } +function BestMatchBadge() { + return ( + + + ); +} + function IconButton({ label, icon: Icon, active = false }: { label: string; icon: LucideIcon; active?: boolean }) { return ( - ); - })} -

- ); -} - -function DocumentSearchCategoryRail() { - return ( -