diff --git a/src/components/ClaimDrawer/ClaimDrawerHeader.test.tsx b/src/components/ClaimDrawer/ClaimDrawerHeader.test.tsx index 1d66981..e965990 100644 --- a/src/components/ClaimDrawer/ClaimDrawerHeader.test.tsx +++ b/src/components/ClaimDrawer/ClaimDrawerHeader.test.tsx @@ -131,14 +131,17 @@ describe("ClaimDrawerHeader", () => { it("test_renders_claim_id_label_and_value", () => { const { container, unmount } = renderHeader({ id: "CLM-42" }); - // The eyebrow label "Claim" is rendered as uppercase text. + // The eyebrow label "Claim" is rendered as uppercase text by + // DrillDrawerHeader. const text = (container.textContent ?? "").toLowerCase(); expect(text).toContain("claim"); - // The claim id sits in a node tagged with data-testid="header-id". - const idEl = container.querySelector('[data-testid="header-id"]'); - expect(idEl).not.toBeNull(); - expect(idEl?.textContent).toBe("CLM-42"); + // SP21 Phase 5 Task 5.10: the claim id is now the title passed + // to DrillDrawerHeader, which renders it inside an

. Find + // the h2 and assert its text matches the claim id. + const titleEl = container.querySelector("h2"); + expect(titleEl).not.toBeNull(); + expect(titleEl?.textContent).toBe("CLM-42"); unmount(); }); @@ -212,8 +215,11 @@ describe("ClaimDrawerHeader", () => { const onClose = vi.fn(); const { container, unmount } = renderHeader({}, onClose); + // SP21 Phase 5 Task 5.10: the close button is now rendered by + // DrillDrawerHeader (no `data-testid`); find it via its + // accessible name instead. const closeBtn = container.querySelector( - '[data-testid="header-close"]' + 'button[aria-label="Close drawer"]' ) as HTMLButtonElement | null; expect(closeBtn).not.toBeNull(); expect(onClose).not.toHaveBeenCalled(); @@ -226,18 +232,25 @@ describe("ClaimDrawerHeader", () => { unmount(); }); - it("test_uses_modern_palette_surface", () => { - // The drawer header anchors itself on the light surface palette - // token (matches ClaimDrawerSkeleton / ClaimDrawerError). The root - //
element is tagged with data-testid="claim-drawer-header" - // so we can sniff its className without coupling to the badge - // or close-button wrappers. - const { container, unmount } = renderHeader({}); + it("test_uses_shared_drilldrawerheader_shell", () => { + // SP21 Phase 5 Task 5.10: the header is now a thin wrapper + // around DrillDrawerHeader — verify the wrapper is present and + // that the underlying shell is the shared one (an h2 with the + // expected Tailwind treatment). The "Claim" eyebrow + claim id + // title prove the shell rendered. + const { container, unmount } = renderHeader({ id: "CLM-42" }); const root = container.querySelector('[data-testid="claim-drawer-header"]'); expect(root).not.toBeNull(); - const cls = root?.className ?? ""; - expect(cls).toContain("bg-[color:var(--m-surface)]"); + + // The h2 is DrillDrawerHeader's title slot. + const titleEl = root?.querySelector("h2"); + expect(titleEl).not.toBeNull(); + expect(titleEl?.textContent).toBe("CLM-42"); + // The className pattern DrillDrawerHeader uses for the title. + const cls = titleEl?.className ?? ""; + expect(cls).toContain("text-[18px]"); + expect(cls).toContain("font-semibold"); unmount(); }); diff --git a/src/components/ClaimDrawer/ClaimDrawerHeader.tsx b/src/components/ClaimDrawer/ClaimDrawerHeader.tsx index 5194042..29055ea 100644 --- a/src/components/ClaimDrawer/ClaimDrawerHeader.tsx +++ b/src/components/ClaimDrawer/ClaimDrawerHeader.tsx @@ -1,11 +1,11 @@ import { useState } from "react"; -import { Download, X } from "lucide-react"; +import { Download } from "lucide-react"; import { Badge, type BadgeProps } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; +import { DrillDrawerHeader } from "@/components/drill/DrillDrawerHeader"; import { api } from "@/lib/api"; import { downloadTextFile } from "@/lib/download"; import { fmt } from "@/lib/format"; -import { cn } from "@/lib/utils"; import type { ClaimDetail } from "@/types"; type ClaimDrawerHeaderProps = { @@ -47,12 +47,19 @@ function badgeVariantFor(state: string): BadgeProps["variant"] { } /** - * Header band for the claim detail drawer (SP4). + * Header band for the claim detail drawer (SP4 → refactored SP21 + * Phase 5 Task 5.10). * - * Top-left: instrument-style "Claim" eyebrow + large mono ID. - * Top-right: state badge + total billed amount + close button. The - * badge color encodes state so the user can read the drawer's status - * at a glance without scrolling. + * The shell is now the shared `DrillDrawerHeader` (same as + * `ProviderDrawer` / `AckDrawer`) — eyebrow + title on the left, + * close button on the right. The right-side `action` slot carries + * the state badge, total billed amount, and the "Download 837" + * button, all of which used to live in a custom
block. + * + * Top-left: instrument-style "Claim" eyebrow + the claim ID. + * Top-right: state badge + total billed amount + download button. + * The badge color encodes state so the user can read the drawer's + * status at a glance without scrolling. */ export function ClaimDrawerHeader({ claim, @@ -80,66 +87,48 @@ export function ClaimDrawerHeader({ } } - return ( -
- {/* Left: eyebrow + mono claim ID */} -
- - Claim - + // The action slot is rendered by DrillDrawerHeader to the left of + // the close button. Group the three action pieces (badge, amount, + // download) in a single flex row so they read as a unit. + const action = ( +
+
+ + {claim.stateLabel} + - {claim.id} + {fmt.usdPrecise(claim.billedAmount)}
+ +
+ ); - {/* Right: state badge + total amount + download + close */} -
-
- - {claim.stateLabel} - - - {fmt.usdPrecise(claim.billedAmount)} - -
- - -
+ return ( +
+
); }