setSelectedType(e.target.value)}
- className="w-full mt-1 px-2.5 py-1.5 text-xs rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] text-[color:var(--text)] focus:border-[color:var(--primary)] focus:outline-none"
+ className={cn(fieldControlPlain, "mt-1 text-xs")}
aria-label="Filter by document type"
>
- All Types
+ All source types
{allTypes.map((t) => (
{t.charAt(0).toUpperCase() + t.slice(1)}
@@ -787,7 +788,7 @@ export function DocumentDrawer({
id="browse-filter-site"
value={selectedSite}
onChange={(e) => setSelectedSite(e.target.value)}
- className="w-full mt-1 px-2.5 py-1.5 text-xs rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] text-[color:var(--text)] focus:border-[color:var(--primary)] focus:outline-none"
+ className={cn(fieldControlPlain, "mt-1 text-xs")}
aria-label="Filter by site"
>
All Sites
@@ -809,7 +810,7 @@ export function DocumentDrawer({
id="browse-filter-topic"
value={selectedTopic}
onChange={(e) => setSelectedTopic(e.target.value)}
- className="w-full mt-1 px-2.5 py-1.5 text-xs rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] text-[color:var(--text)] focus:border-[color:var(--primary)] focus:outline-none"
+ className={cn(fieldControlPlain, "mt-1 text-xs")}
aria-label="Filter by topic"
>
All Topics
@@ -831,7 +832,7 @@ export function DocumentDrawer({
id="browse-filter-population"
value={selectedPopulation}
onChange={(e) => setSelectedPopulation(e.target.value)}
- className="w-full mt-1 px-2.5 py-1.5 text-xs rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] text-[color:var(--text)] focus:border-[color:var(--primary)] focus:outline-none"
+ className={cn(fieldControlPlain, "mt-1 text-xs")}
aria-label="Filter by population"
>
All Populations
@@ -853,7 +854,7 @@ export function DocumentDrawer({
id="browse-filter-designation"
value={selectedDesignation}
onChange={(e) => setSelectedDesignation(e.target.value as SourceDesignation | "all")}
- className="w-full mt-1 px-2.5 py-1.5 text-xs rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] text-[color:var(--text)] focus:border-[color:var(--primary)] focus:outline-none"
+ className={cn(fieldControlPlain, "mt-1 text-xs")}
aria-label="Filter by source provenance designation"
>
All provenance
diff --git a/src/components/clinical-dashboard/document-search-results.tsx b/src/components/clinical-dashboard/document-search-results.tsx
index 002f8f5ec..5de716c5e 100644
--- a/src/components/clinical-dashboard/document-search-results.tsx
+++ b/src/components/clinical-dashboard/document-search-results.tsx
@@ -8,7 +8,6 @@ import {
FileImage,
FileText,
Filter,
- FolderOpen,
ListChecks,
Loader2,
Pill,
@@ -29,7 +28,7 @@ import { documentDisplayTitle } from "@/components/DocumentOrganizationBadges";
import { isDeployedClinicalKb } from "@/lib/deployed-app";
import { ModeHomeTemplate, ModeHomeVerificationFooter } from "@/components/mode-home-template";
import { ScopeAndGovernanceNotice } from "@/components/clinical-dashboard/answer-content";
-import { ResultSortControl } from "@/components/clinical-dashboard/search-results-header-band";
+import { SearchResultsHeaderBand } from "@/components/clinical-dashboard/search-results-header-band";
import { UniversalSearchAlsoMatches } from "@/components/clinical-dashboard/universal-search-also-matches";
import { useResultSort } from "@/components/use-result-sort";
import { SafeBoldText } from "@/components/SafeBoldText";
@@ -63,7 +62,7 @@ import type { ServiceSearchMatch } from "@/lib/services";
import type { FormSearchMatch } from "@/lib/forms";
import type { ClinicalDocument, DocumentMatch, SearchResult, SearchScopeSummary } from "@/lib/types";
import type { RegistryRequestStatus } from "@/lib/use-registry-records";
-import { sortResultItems, type ResultSortValue } from "@/lib/result-sort";
+import { sortResultItems } from "@/lib/result-sort";
import { documentRelevancePercent } from "./relevance-score";
type SearchFacet = { value: string; count: number };
@@ -327,9 +326,9 @@ function DocumentSearchHome({
action: onOpenRecentDocuments,
},
{
- label: "Browse library",
- description: "All indexed sources.",
- icon: FolderOpen,
+ label: "Browse sources",
+ description: "Filter all indexed sources.",
+ icon: BookOpen,
action: onOpenLibrary,
},
{
@@ -360,7 +359,7 @@ function DocumentSearchHome({
{documentCount > 0 ? (
@@ -373,117 +372,57 @@ function DocumentSearchHome({
);
}
-function SearchResultsHeader({
- resultLabel,
- trimmedQuery,
- sortValue,
- onSortChange,
- showSort = true,
-}: {
- resultLabel: string;
- trimmedQuery: string;
- sortValue: ResultSortValue;
- onSortChange: (value: ResultSortValue) => void;
- showSort?: boolean;
-}) {
- return (
-
-
-
-
-
-
-
-
{resultLabel}
- {trimmedQuery ? (
-
- Results for {" "}
-
- {trimmedQuery}
-
-
- ) : null}
-
-
-
- {showSort ? : null}
-
- );
-}
-
-function DocumentResultsControls({
+function DocumentSourceTypeFilters({
resultTabs,
activeResultType,
onResultTypeChange,
- sortValue,
- onSortChange,
- onOpenLibrary,
}: {
resultTabs: Array<{ key: ResultTypeFilter; label: string; count: number }>;
activeResultType: ResultTypeFilter;
onResultTypeChange: (value: ResultTypeFilter) => void;
- sortValue: ResultSortValue;
- onSortChange: (value: ResultSortValue) => void;
- onOpenLibrary: () => void;
}) {
- const showTypeFilters = resultTabs.length > 1;
+ const resultTypeIcons: Record = {
+ all: BookOpen,
+ tables: ListChecks,
+ images: FileImage,
+ pdfs: FileText,
+ };
return (
-
- {showTypeFilters ? (
-
- {resultTabs.map((tab) => {
- const active = tab.key === activeResultType;
- return (
- onResultTypeChange(tab.key)}
- className={cn(
- "inline-flex min-h-tap shrink-0 items-center gap-1.5 rounded-md px-2.5 text-2xs font-bold transition motion-reduce:transition-none",
- "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]",
- active
- ? "bg-[color:var(--clinical-accent-soft)] text-[color:var(--clinical-accent)]"
- : "text-[color:var(--text-muted)] hover:bg-[color:var(--surface-subtle)] hover:text-[color:var(--text)]",
- )}
- >
- {tab.label}
- {tab.count}
-
- );
- })}
-
- ) : (
-
- )}
-
-
-
-
- Library
-
+
+
+ Source type
+
+
+ {resultTabs.map((tab) => {
+ const active = tab.key === activeResultType;
+ const Icon = resultTypeIcons[tab.key];
+ return (
+ onResultTypeChange(tab.key)}
+ className={cn(
+ "inline-flex min-h-tap shrink-0 items-center gap-1.5 rounded-lg border px-2.5 text-2xs font-bold transition motion-reduce:transition-none sm:min-h-9 sm:text-xs",
+ "focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]",
+ active
+ ? "border-[color:var(--clinical-accent-border)] bg-[color:var(--clinical-accent-soft)] text-[color:var(--clinical-accent)] shadow-[var(--shadow-inset)]"
+ : "border-[color:var(--border)] bg-[color:var(--surface)] text-[color:var(--text-muted)] hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)]",
+ )}
+ >
+
+ {tab.label}
+ {tab.count}
+
+ );
+ })}
-
+
);
}
@@ -907,7 +846,6 @@ function DocumentSearchResultsPanelImpl({
const selectedDocument =
sortedMatches.find((document) => document.document_id === selectedDocumentId) ?? sortedMatches[0] ?? null;
const recordMatchCount = recordMatches.length;
- const recordCopy = searchRecordConfig[recordMode];
const shouldShowHome = showHome || !trimmedQuery;
function toggleTagFacet(facet: SmartDocumentTagFacet) {
@@ -929,23 +867,6 @@ function DocumentSearchResultsPanelImpl({
: !realDataReady
? setupWarning || "Complete the search setup before using Documents mode."
: null;
- const resultLabel = (() => {
- if (loading) {
- return showRecordMatches
- ? `Finding matching ${recordCopy.recordLabel}${recordMatchCount === 1 ? "" : "s"}`
- : "Finding matching documents";
- }
- if (recordMatchCount > 0 && matches.length > 0) {
- return `${recordMatchCount} ${recordCopy.recordLabel}${recordMatchCount === 1 ? "" : "s"} and ${
- sortedMatches.length
- } document${sortedMatches.length === 1 ? "" : "s"}`;
- }
- if (recordMatchCount > 0)
- return `${recordMatchCount} ${recordCopy.recordLabel}${recordMatchCount === 1 ? "" : "s"}`;
- if (matches.length) return `${sortedMatches.length} document${sortedMatches.length === 1 ? "" : "s"}`;
- if (trimmedQuery) return "No matching documents";
- return `${documentCount} document${documentCount === 1 ? "" : "s"}`;
- })();
const showResultsControls = matches.length > 0 && !loading;
const showIdentityHeader =
recordMatchCount > 0 ||
@@ -957,23 +878,40 @@ function DocumentSearchResultsPanelImpl({
return (
{showIdentityHeader ? (
-
- ) : null}
-
- {showResultsControls ? (
-
0 ? setSortValue : undefined}
+ utilityControls={
+ !loading && !shouldShowHome ? (
+
+
+ Sources
+
+ ) : null
+ }
+ filterLabel="Filter documents by source type"
+ filterControls={
+ showResultsControls && resultTabs.length > 1 ? (
+
+ ) : null
+ }
/>
) : null}
diff --git a/src/components/clinical-dashboard/favourites-command-library-page.tsx b/src/components/clinical-dashboard/favourites-command-library-page.tsx
index 4e2baf8d0..13fc3a2f9 100644
--- a/src/components/clinical-dashboard/favourites-command-library-page.tsx
+++ b/src/components/clinical-dashboard/favourites-command-library-page.tsx
@@ -312,6 +312,7 @@ function ActiveFilterChips({
onClearType,
onClearSet,
onClearViewMode,
+ includeSearch = true,
}: {
searchTerm: string;
selectedTypeId: string;
@@ -321,11 +322,14 @@ function ActiveFilterChips({
onClearType: () => void;
onClearSet: () => void;
onClearViewMode: () => void;
+ includeSearch?: boolean;
}) {
const typeLabel = favouriteTabs.find((tab) => tab.id === selectedTypeId)?.label;
const chips: { key: string; label: string; onClear: () => void }[] = [];
- if (searchTerm.trim()) chips.push({ key: "search", label: `Search: ${searchTerm.trim()}`, onClear: onClearSearch });
+ if (includeSearch && searchTerm.trim()) {
+ chips.push({ key: "search", label: `Search: ${searchTerm.trim()}`, onClear: onClearSearch });
+ }
if (selectedSet) chips.push({ key: "set", label: selectedSet.title, onClear: onClearSet });
if (selectedTypeId !== "all" && typeLabel) chips.push({ key: "type", label: typeLabel, onClear: onClearType });
if (viewMode === "source-backed") chips.push({ key: "view", label: "Source-backed", onClear: onClearViewMode });
@@ -1186,7 +1190,27 @@ export function FavouritesCommandLibraryPage({ query = "", demoMode }: { query?:
className="mode-home-composer-slot hidden w-full max-w-3xl [&:not(:empty)]:block"
/>
-
+ setSelectedTypeId("all")}
+ onClearSet={() => setSelectedSetId(null)}
+ onClearViewMode={() => setViewMode("all")}
+ includeSearch={false}
+ />
+ ) : null
+ }
+ />
- setSelectedTypeId("all")}
- onClearSet={() => setSelectedSetId(null)}
- onClearViewMode={() => setViewMode("all")}
- />
-
{showContinueStrip && continueItem ? : null}
{query.trim() && scopedItems.length === 0 ? (
diff --git a/src/components/clinical-dashboard/medication-prescribing-workspace.tsx b/src/components/clinical-dashboard/medication-prescribing-workspace.tsx
index 96f0fd5d7..d44baa3a7 100644
--- a/src/components/clinical-dashboard/medication-prescribing-workspace.tsx
+++ b/src/components/clinical-dashboard/medication-prescribing-workspace.tsx
@@ -461,12 +461,17 @@ function MedicationResults({
return (
-
+
}
+ />
-
-
{catalog.loading || catalog.error ? (
{catalog.loading ? (
diff --git a/src/components/clinical-dashboard/mode-action-popup.tsx b/src/components/clinical-dashboard/mode-action-popup.tsx
index dfb1e872f..9df6758b4 100644
--- a/src/components/clinical-dashboard/mode-action-popup.tsx
+++ b/src/components/clinical-dashboard/mode-action-popup.tsx
@@ -157,7 +157,7 @@ const modeActionSets = {
icon: MessageSquarePlus,
primary: true,
},
- { id: "documents-upload", label: "Add document", description: "Upload a source to the library", icon: UploadCloud },
+ { id: "documents-upload", label: "Add document", description: "Upload a source", icon: UploadCloud },
{ id: "documents-scope", label: "Scope", description: "Limit answers to chosen sources", icon: Filter },
{
id: "answer-evidence-map",
@@ -165,14 +165,14 @@ const modeActionSets = {
description: "Trace quotes and source support",
icon: ListChecks,
},
- { id: "documents-search", label: "Search library", description: "Find indexed sources", icon: Search },
+ { id: "documents-search", label: "Search sources", description: "Find indexed sources", icon: Search },
{ id: "tools-browse", label: "Clinical tools", description: "Open clinical tools", icon: Wrench },
],
documents: [
{
id: "documents-upload",
label: "Upload PDF",
- description: "Add a source to the library",
+ description: "Add an indexed source",
icon: UploadCloud,
primary: true,
},
diff --git a/src/components/clinical-dashboard/search-results-header-band.tsx b/src/components/clinical-dashboard/search-results-header-band.tsx
index 83fe52082..02fd49504 100644
--- a/src/components/clinical-dashboard/search-results-header-band.tsx
+++ b/src/components/clinical-dashboard/search-results-header-band.tsx
@@ -1,6 +1,7 @@
"use client";
import { Bookmark, CheckCircle2, ChevronsUpDown, LayoutList, LoaderCircle, Search, Table2, X } from "lucide-react";
+import type { ReactNode } from "react";
import { searchCommandSurfaceConfig } from "@/lib/search-command-surface";
import { cn } from "@/components/ui-primitives";
@@ -21,6 +22,10 @@ export function SearchResultsHeaderBand({
sortValue = "relevance",
onSortChange,
onSaveSearch,
+ utilityControls,
+ filterControls,
+ filterLabel = "Filter search results",
+ headingLevel = 2,
className,
}: {
modeId: AppModeId;
@@ -32,6 +37,13 @@ export function SearchResultsHeaderBand({
sortValue?: ResultSortValue;
onSortChange?: (value: ResultSortValue) => void;
onSaveSearch?: () => void;
+ /** Page-specific actions that belong beside sort/view controls. */
+ utilityControls?: ReactNode;
+ /** Page-specific filters rendered as a full-width row within the shared ribbon. */
+ filterControls?: ReactNode;
+ filterLabel?: string;
+ /** Use level 1 when the ribbon is the route's primary page heading. */
+ headingLevel?: 1 | 2;
className?: string;
}) {
const command = useSearchCommand();
@@ -43,7 +55,9 @@ export function SearchResultsHeaderBand({
});
const displayQuery = query.trim() || "All";
const statusLabel = loading ? "Searching…" : `${matchCount} ${matchCount === 1 ? "match" : "matches"}`;
- const hasUtilities = visibleScopes.length > 0 || Boolean(onSortChange || onViewChange || onSaveSearch);
+ const hasUtilities =
+ visibleScopes.length > 0 || Boolean(onSortChange || onViewChange || onSaveSearch || utilityControls);
+ const QueryHeading = headingLevel === 1 ? "h1" : "h2";
return (
Query
{loading ? "Searching for" : "Results for"}
-
{displayQuery}
-
+
command?.onRemoveScope(scope.id)}
aria-label={`Remove ${scope.label} filter`}
className={cn(
- "inline-flex min-h-10 max-w-full items-center gap-1 rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] px-2.5 text-xs font-bold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)]",
+ "inline-flex min-h-tap max-w-full items-center gap-1 rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] px-2.5 text-xs font-bold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)] sm:min-h-10",
focusRing,
)}
>
@@ -127,9 +141,10 @@ export function SearchResultsHeaderBand({
className="min-w-[8.5rem] flex-1 sm:flex-none"
/>
) : null}
+ {utilityControls}
{onViewChange ? (
@@ -138,7 +153,7 @@ export function SearchResultsHeaderBand({
aria-pressed={view === "table"}
onClick={() => onViewChange("table")}
className={cn(
- "grid min-h-10 min-w-10 place-items-center",
+ "grid min-h-tap min-w-tap place-items-center sm:min-h-10 sm:min-w-10",
focusRing,
view === "table"
? "bg-[color:var(--clinical-accent-soft)] text-[color:var(--clinical-accent)]"
@@ -153,7 +168,7 @@ export function SearchResultsHeaderBand({
aria-pressed={view === "list"}
onClick={() => onViewChange("list")}
className={cn(
- "grid min-h-10 min-w-10 place-items-center border-l border-[color:var(--border)]",
+ "grid min-h-tap min-w-tap place-items-center border-l border-[color:var(--border)] sm:min-h-10 sm:min-w-10",
focusRing,
view === "list"
? "bg-[color:var(--clinical-accent-soft)] text-[color:var(--clinical-accent)]"
@@ -170,7 +185,7 @@ export function SearchResultsHeaderBand({
type="button"
onClick={onSaveSearch}
className={cn(
- "inline-flex min-h-10 items-center gap-1.5 rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] px-2.5 text-xs font-extrabold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)]",
+ "inline-flex min-h-tap items-center gap-1.5 rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] px-2.5 text-xs font-extrabold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)] sm:min-h-10",
focusRing,
)}
>
@@ -181,6 +196,16 @@ export function SearchResultsHeaderBand({
) : null}
+ {filterControls ? (
+
+ {filterControls}
+
+ ) : null}
);
}
@@ -200,7 +225,7 @@ export function ResultSortControl({
return (
-
-
- {activeCategory ? (
-
-
- Clear filter
-
- ) : null}
-
+
+
+ {activeCategory ? (
+
+
+ Clear category
+
+ ) : null}
+
+ }
+ />
{results.length ? (
diff --git a/src/components/factsheets/factsheets-search-page.tsx b/src/components/factsheets/factsheets-search-page.tsx
index be68e32b1..5e5a48ac0 100644
--- a/src/components/factsheets/factsheets-search-page.tsx
+++ b/src/components/factsheets/factsheets-search-page.tsx
@@ -4,6 +4,7 @@ import Link from "next/link";
import { ChevronRight, Info, LayoutGrid, List, SearchX } from "lucide-react";
import { useState } from "react";
+import { SearchResultsHeaderBand } from "@/components/clinical-dashboard/search-results-header-band";
import {
categoryTheme,
factsheetCategories,
@@ -40,12 +41,6 @@ export function FactsheetsSearchPage({
const [view, setView] = useState
("list");
const activeCategory = factsheetCategories.find((entry) => entry === category);
- const resultLine = query
- ? `${results.length} result${results.length === 1 ? "" : "s"} for “${query}”${
- activeCategory ? ` in ${activeCategory}` : ""
- }`
- : `${results.length} factsheet${results.length === 1 ? "" : "s"}${activeCategory ? ` in ${activeCategory}` : ""}`;
-
return (
-
- Filter:
- {filterChips.map((chip) => {
- const isActive = chip.key ? activeCategory === chip.key : !activeCategory;
- return (
-
- {chip.label}
-
- );
- })}
-
-
-
-
{resultLine}
-
- {(["list", "cards"] as const).map((mode) => {
- const isActive = view === mode;
- return (
- setView(mode)}
- aria-pressed={isActive}
- className={cn(
- "inline-flex min-h-8 items-center gap-1.5 rounded-md px-2.5 text-xs font-bold capitalize transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]",
- isActive
- ? "bg-[color:var(--surface)] text-[color:var(--text-heading)] shadow-[var(--shadow-tight)]"
- : "text-[color:var(--text-muted)] hover:text-[color:var(--text)]",
- )}
- >
- {mode === "list" ? (
-
- ) : (
-
- )}
- {mode}
-
- );
- })}
-
-
+
+ {(["list", "cards"] as const).map((mode) => {
+ const isActive = view === mode;
+ return (
+ setView(mode)}
+ aria-pressed={isActive}
+ className={cn(
+ "inline-flex min-h-tap items-center gap-1.5 px-2.5 text-xs font-bold capitalize transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)] sm:min-h-10",
+ mode === "cards" && "border-l border-[color:var(--border)]",
+ isActive
+ ? "bg-[color:var(--clinical-accent-soft)] text-[color:var(--clinical-accent)]"
+ : "text-[color:var(--text-muted)] hover:text-[color:var(--text)]",
+ )}
+ >
+ {mode === "list" ? (
+
+ ) : (
+
+ )}
+ {mode}
+
+ );
+ })}
+
+ }
+ filterLabel="Filter factsheets by category"
+ filterControls={
+
+
+ Category
+
+ {filterChips.map((chip) => {
+ const isActive = chip.key ? activeCategory === chip.key : !activeCategory;
+ return (
+
+ {chip.label}
+
+ );
+ })}
+
+ }
+ />
{results.length === 0 ? (
diff --git a/src/components/forms/forms-search-results-page.tsx b/src/components/forms/forms-search-results-page.tsx
index 1e3e8f6bd..22e43b1c5 100644
--- a/src/components/forms/forms-search-results-page.tsx
+++ b/src/components/forms/forms-search-results-page.tsx
@@ -650,6 +650,21 @@ function FormsSearchResultsPageContent({ query }: FormsSearchResultsPageProps) {
matchCount={displayedMatches.length}
sortValue={sortValue}
onSortChange={setSortValue}
+ filterLabel="Filter form results"
+ filterControls={
+
+
+
+
+ {supportsPathwayClaims ? (
+
setRefineOpen((open) => !open)}
+ panelId={refinePanelId}
+ />
+ ) : null}
+
+ }
/>
{query.trim() && deferredQuery === query && displayedMatches.length === 0 ? (
) : (
<>
-
-
-
-
-
- {supportsPathwayClaims ? (
- setRefineOpen((open) => !open)}
- panelId={refinePanelId}
- />
- ) : null}
-
-
{supportsPathwayClaims ? : null}
diff --git a/src/components/formulation/formulation-home-page.tsx b/src/components/formulation/formulation-home-page.tsx
index f8ec73edc..348c5a111 100644
--- a/src/components/formulation/formulation-home-page.tsx
+++ b/src/components/formulation/formulation-home-page.tsx
@@ -23,6 +23,7 @@ import {
formulationCard,
} from "@/components/formulation/formulation-ui";
import { ModeHomeMain, ModeHomeTemplate, ModeHomeVerificationFooter } from "@/components/mode-home-template";
+import { SearchResultsHeaderBand } from "@/components/clinical-dashboard/search-results-header-band";
import { cn, eyebrowText } from "@/components/ui-primitives";
import { appModeHomeHref } from "@/lib/app-modes";
import {
@@ -195,53 +196,49 @@ function FormulationResults({ query }: { query: string }) {
-
-
-
Mechanism search
-
- Mechanisms matching “{query}”
-
-
- Matches use patient language, clinical clues, domains, symptoms, and formulation context. Open a mechanism
- to test fit and competing explanations.
-
-
-
- {results.length} {results.length === 1 ? "match" : "matches"}
-
-
+
+
+ {formulationSearchPresets.slice(0, 4).map((preset) => (
+
+ {preset.label}
+
+ ))}
+
+
+ Filter by formulation domain
+ setDomain(event.target.value)}
+ className="min-h-tap rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] px-3 text-xs font-semibold text-[color:var(--text)] shadow-[var(--shadow-inset)] outline-none focus:border-[color:var(--focus)] focus:ring-4 focus:ring-[color:var(--focus)]/20 sm:min-h-10"
+ >
+ All formulation domains
+ {formulationDomains.map((item) => (
+
+ {item}
+
+ ))}
+
+
+
+ }
+ />
-
-
- {formulationSearchPresets.slice(0, 4).map((preset) => (
-
- {preset.label}
-
- ))}
-
-
- Filter by formulation domain
- setDomain(event.target.value)}
- className="min-h-tap rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)] px-3 text-sm font-semibold text-[color:var(--text)] shadow-[var(--shadow-inset)] outline-none focus:border-[color:var(--focus)] focus:ring-4 focus:ring-[color:var(--focus)]/20"
- >
- All formulation domains
- {formulationDomains.map((item) => (
-
- {item}
-
- ))}
-
-
-
+
+ Matches use patient language, clinical clues, domains, symptoms, and formulation context. Open a mechanism to
+ test fit and competing explanations.
+
{results.length === 0 && rankingReady ? (
diff --git a/src/components/services/services-navigator-page.tsx b/src/components/services/services-navigator-page.tsx
index 04f6dc740..be7d27357 100644
--- a/src/components/services/services-navigator-page.tsx
+++ b/src/components/services/services-navigator-page.tsx
@@ -42,6 +42,14 @@ import { UniversalSearchAlsoMatches } from "@/components/clinical-dashboard/univ
import { useResultSort } from "@/components/use-result-sort";
const defaultQuery = "13YARN crisis Aboriginal Torres Strait Islander phone";
+const serviceQuickFilters = [
+ { label: "Best fit", query: defaultQuery },
+ { label: "Crisis", query: "crisis" },
+ { label: "Culturally safe", query: "Aboriginal Torres Strait Islander" },
+ { label: "Phone referral", query: "phone referral" },
+ { label: "Free", query: "free" },
+ { label: "WA", query: "WA" },
+];
function text(value: string | null | undefined, fallback = "Confirm locally") {
return value?.trim() ? value.trim() : fallback;
@@ -611,6 +619,41 @@ export function ServicesNavigatorPage() {
loading={registryLoading}
sortValue={sortValue}
onSortChange={setSortValue}
+ filterLabel="Quick service filters"
+ filterControls={
+
+
+
+ Quick filters
+
+
+ {serviceQuickFilters.map((filter) => (
+ applyServiceQuery(filter.query)}
+ aria-pressed={query.trim().toLowerCase() === filter.query.toLowerCase()}
+ className={cn(
+ "inline-flex min-h-tap shrink-0 items-center rounded-lg border px-2.5 text-2xs font-bold transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)] sm:min-h-9 sm:text-xs",
+ query.trim().toLowerCase() === filter.query.toLowerCase()
+ ? "border-[color:var(--clinical-accent-border)] bg-[color:var(--clinical-accent-soft)] text-[color:var(--clinical-accent)]"
+ : "border-[color:var(--border)] bg-[color:var(--surface)] text-[color:var(--text-muted)] hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)]",
+ )}
+ >
+ {filter.label}
+
+ ))}
+
+
setLocalQuery({ urlQuery, value: "" })}
+ aria-label="Clear quick filters"
+ className="inline-flex min-h-tap shrink-0 items-center rounded-lg px-2 text-xs font-bold text-[color:var(--clinical-accent)] hover:bg-[color:var(--clinical-accent-soft)] sm:min-h-9"
+ >
+ Clear
+
+
+ }
/>
>
}
@@ -672,56 +715,6 @@ export function ServicesNavigatorPage() {
-
-
-
- Filters
-
-
- Advanced service filters are coming soon. Use the quick filters below for now.
-
-
-
-
-
- {[
- { label: "Best fit", query: defaultQuery },
- { label: "Crisis", query: "crisis" },
- { label: "Culturally safe", query: "Aboriginal Torres Strait Islander" },
- { label: "Phone referral", query: "phone referral" },
- { label: "Free", query: "free" },
- { label: "WA", query: "WA" },
- ].map((chip, index) => (
- applyServiceQuery(chip.query)}
- className={cn(
- "min-h-8 rounded-full border px-3 text-xs font-bold transition hover:-translate-y-px hover:shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[color:var(--focus)]",
- index > 2 ? "max-sm:hidden" : "",
- index === 0
- ? "border-[color:var(--clinical-accent)] bg-[color:var(--clinical-accent)] text-[color:var(--clinical-accent-contrast)] shadow-[var(--shadow-tight)]"
- : "border-[color:var(--border)] bg-[color:var(--surface-subtle)] text-[color:var(--text-muted)] hover:border-[color:var(--clinical-accent-border)] hover:bg-[color:var(--clinical-accent-soft)] hover:text-[color:var(--clinical-accent)]",
- )}
- >
- {chip.label}
-
- ))}
-
-
setLocalQuery({ urlQuery, value: "" })}
- className="min-h-8 shrink-0 rounded-full px-2 text-xs font-bold text-[color:var(--clinical-accent)] hover:bg-[color:var(--clinical-accent-soft)] hover:text-[color:var(--clinical-accent-hover)] max-sm:hidden"
- >
- Clear all
-