Skip to content
1 change: 0 additions & 1 deletion src/components/clinical-dashboard/answer-status.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ export function SharedHomeEmptyState({
<ModeHomeTemplate
testId="shared-home-empty-state"
title={presentation.title}
subtitle={presentation.subtitle}
icon={appModeIcons[modeId]}
headingLevel={2}
stabilizePhoneCopy
Expand Down
22 changes: 12 additions & 10 deletions src/components/mode-home-template.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export type ModeHomePill = {
type ModeHomeTemplateProps = {
testId?: string;
title: string;
subtitle: string;
subtitle?: string;
icon: LucideIcon;
actions: ModeHomeAction[];
actionsLabel: string;
Expand Down Expand Up @@ -64,7 +64,7 @@ export function ModeHomeHero({
}: {
testId?: string;
title: string;
subtitle: string;
subtitle?: string;
icon: LucideIcon;
headingLevel?: 1 | 2;
stabilizePhoneCopy?: boolean;
Expand Down Expand Up @@ -94,14 +94,16 @@ export function ModeHomeHero({
>
{title}
</Heading>
<p
className={cn(
"mx-auto max-w-2xl text-pretty text-sm font-medium leading-5 text-[color:var(--text-muted)] sm:text-base-minus sm:leading-5 lg:text-base lg:leading-6",
stabilizePhoneCopy && "max-sm:grid max-sm:min-h-[2lh] max-sm:place-items-center",
)}
>
{subtitle}
</p>
{subtitle ? (
<p
className={cn(
"mx-auto max-w-2xl text-pretty text-sm font-medium leading-5 text-[color:var(--text-muted)] sm:text-base-minus sm:leading-5 lg:text-base lg:leading-6",
stabilizePhoneCopy && "max-sm:grid max-sm:min-h-[2lh] max-sm:place-items-center",
)}
>
{subtitle}
</p>
) : null}
</div>
</section>
);
Expand Down
40 changes: 13 additions & 27 deletions src/lib/ui-copy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,47 @@ import type { AppModeId } from "@/lib/app-modes";

export type SharedHomePresentation = {
title: string;
subtitle: string;
};

export const sharedHomePresentation = {
answer: {
title: "What can I help with?",
subtitle: "Ask a source-backed clinical question.",
title: "Clinical Answers",
},
documents: {
title: "Find a source?",
subtitle: "Search documents and evidence passages.",
title: "Clinical Documents",
},
services: {
title: "Find a service?",
subtitle: "Search services and referral pathways.",
title: "Clinical Services",
},
forms: {
title: "Find a form?",
subtitle: "Search clinical forms and pathways.",
title: "Clinical Forms",
},
favourites: {
title: "Find a saved item?",
subtitle: "Search your saved clinical items.",
title: "Clinical Favourites",
},
differentials: {
title: "What else could it be?",
subtitle: "Compare causes and clinical clues.",
title: "Differential Diagnosis",
},
dsm: {
title: "Check DSM-5 criteria?",
subtitle: "Search diagnoses, criteria, and codes.",
title: "DSM-5 Diagnosis",
},
specifiers: {
title: "Which specifier fits?",
subtitle: "Refine diagnostic wording and episode patterns.",
title: "Diagnostic Specifiers",
},
formulation: {
title: "What explains the pattern?",
subtitle: "Explore mechanisms behind the presentation.",
title: "Clinical Formulation",
},
prescribing: {
title: "Check a medication?",
subtitle: "Check dosing, safety, and monitoring.",
title: "Medication Guidance",
},
tools: {
title: "Find a clinical tool?",
subtitle: "Search clinical tools and applications.",
title: "Clinical Tools",
},
"therapy-compass": {
title: "Which therapy fits?",
subtitle: "Explore source-grounded therapy guidance.",
title: "Therapy Compass",
},
factsheets: {
title: "Find a patient factsheet?",
subtitle: "Search clear patient information to share.",
title: "Patient Factsheets",
},
} as const satisfies Record<AppModeId, SharedHomePresentation>;

Expand Down
64 changes: 23 additions & 41 deletions tests/shared-home-empty-state.dom.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,86 +7,72 @@ import { appModeIds, type AppModeId } from "@/lib/app-modes";
const expectedPresentations = [
{
modeId: "answer",
title: "What can I help with?",
subtitle: "Ask a source-backed clinical question.",
title: "Clinical Answers",
iconClass: "lucide-sparkles",
},
{
modeId: "documents",
title: "Find a source?",
subtitle: "Search documents and evidence passages.",
title: "Clinical Documents",
iconClass: "lucide-file-text",
},
{
modeId: "services",
title: "Find a service?",
subtitle: "Search services and referral pathways.",
title: "Clinical Services",
iconClass: "lucide-route",
},
{
modeId: "forms",
title: "Find a form?",
subtitle: "Search clinical forms and pathways.",
title: "Clinical Forms",
iconClass: "lucide-file-pen-line",
},
{
modeId: "favourites",
title: "Find a saved item?",
subtitle: "Search your saved clinical items.",
title: "Clinical Favourites",
iconClass: "lucide-heart",
},
{
modeId: "differentials",
title: "What else could it be?",
subtitle: "Compare causes and clinical clues.",
title: "Differential Diagnosis",
iconClass: "lucide-brain-circuit",
},
{
modeId: "dsm",
title: "Check DSM-5 criteria?",
subtitle: "Search diagnoses, criteria, and codes.",
title: "DSM-5 Diagnosis",
iconClass: "lucide-book-open-check",
},
{
modeId: "specifiers",
title: "Which specifier fits?",
subtitle: "Refine diagnostic wording and episode patterns.",
title: "Diagnostic Specifiers",
iconClass: "lucide-tags",
},
{
modeId: "formulation",
title: "What explains the pattern?",
subtitle: "Explore mechanisms behind the presentation.",
title: "Clinical Formulation",
iconClass: "lucide-network",
},
{
modeId: "prescribing",
title: "Check a medication?",
subtitle: "Check dosing, safety, and monitoring.",
title: "Medication Guidance",
iconClass: "lucide-pill",
},
{
modeId: "tools",
title: "Find a clinical tool?",
subtitle: "Search clinical tools and applications.",
title: "Clinical Tools",
iconClass: "lucide-wrench",
},
{
modeId: "therapy-compass",
title: "Which therapy fits?",
subtitle: "Explore source-grounded therapy guidance.",
title: "Therapy Compass",
iconClass: "lucide-compass",
},
{
modeId: "factsheets",
title: "Find a patient factsheet?",
subtitle: "Search clear patient information to share.",
title: "Patient Factsheets",
iconClass: "lucide-book-open-text",
},
] as const satisfies ReadonlyArray<{
modeId: AppModeId;
title: string;
subtitle: string;
iconClass: string;
}>;

Expand All @@ -95,20 +81,17 @@ describe("SharedHomeEmptyState", () => {
expect(expectedPresentations.map(({ modeId }) => modeId)).toEqual(appModeIds);
});

it.each(expectedPresentations)(
"renders the canonical $modeId presentation",
({ modeId, title, subtitle, iconClass }) => {
const { container } = render(<SharedHomeEmptyState modeId={modeId} />);
it.each(expectedPresentations)("renders the canonical $modeId presentation", ({ modeId, title, iconClass }) => {
const { container } = render(<SharedHomeEmptyState modeId={modeId} />);

expect(screen.getByTestId("shared-home-empty-state")).toBeInTheDocument();
expect(screen.getByRole("heading", { level: 2, name: title })).toBeInTheDocument();
expect(screen.getByText(subtitle, { exact: true })).toBeInTheDocument();
expect(screen.getByTestId("shared-home-empty-state")).toBeInTheDocument();
expect(screen.getByRole("heading", { level: 2, name: title })).toBeInTheDocument();
expect(container.querySelector("h2 + p")).not.toBeInTheDocument();

const icon = container.querySelector(".mode-home-icon svg");
expect(icon).toHaveClass(iconClass);
expect(icon).toHaveAttribute("aria-hidden", "true");
},
);
const icon = container.querySelector(".mode-home-icon svg");
expect(icon).toHaveClass(iconClass);
expect(icon).toHaveAttribute("aria-hidden", "true");
});

it("updates the same shared-home root when the active mode changes", () => {
const { rerender } = render(<SharedHomeEmptyState modeId="answer" />);
Expand All @@ -119,8 +102,7 @@ describe("SharedHomeEmptyState", () => {
rerender(<SharedHomeEmptyState modeId="services" />);

expect(screen.getByTestId("shared-home-empty-state")).toBe(sharedHomeRoot);
expect(screen.getByRole("heading", { level: 2, name: "Find a service?" })).toBeInTheDocument();
expect(screen.getByText("Search services and referral pathways.", { exact: true })).toBeInTheDocument();
expect(screen.getByRole("heading", { level: 2, name: "Clinical Services" })).toBeInTheDocument();
expect(sharedHomeRoot.querySelector(".mode-home-icon svg")).toHaveClass("lucide-route");
expect(screen.queryByText("What can I help with?", { exact: true })).not.toBeInTheDocument();
});
Expand Down
2 changes: 1 addition & 1 deletion tests/ui-accessibility.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ async function expectNoPageHorizontalOverflow(page: Page) {

async function expectDashboardUsable(page: Page) {
await expect(page.getByRole("heading", { level: 1, name: "Clinical Guide" })).toHaveCount(1);
await expect(page.getByRole("heading", { name: "Answer" })).toBeVisible();
await expect(page.getByRole("heading", { name: "Clinical Answers", exact: true })).toBeVisible();
await expect(page.locator('[aria-label^="Search indexed guidelines by question or keyword"]:visible')).toBeVisible();
await expect(page.getByRole("button", { name: "Open answer options" })).toBeVisible();
await expectNoPageHorizontalOverflow(page);
Expand Down
Loading
Loading