diff --git a/src/components/forms/form-code-badge.tsx b/src/components/forms/form-code-badge.tsx index ff68a01b8..0a61ea211 100644 --- a/src/components/forms/form-code-badge.tsx +++ b/src/components/forms/form-code-badge.tsx @@ -3,16 +3,15 @@ import { cn, codeText } from "@/components/ui-primitives"; export type FormCodeBadgeVariant = "sm" | "md" | "hero"; // Form codes are mostly short ("1A", "10D") but some carry a trailing qualifier -// ("6B Attachment"). Splitting on the first space lets the badge show the code -// prominently while the qualifier renders as a compact sub-label, so long codes -// no longer overflow the fixed chip. +// ("6B Attachment"). Splitting on the first whitespace run matches pathwayItems +// (which uses /\s+/) so tabs/newlines keep the same head/qualifier split as spaces. export function splitFormCode(code: string): { head: string; qualifier: string | null } { const trimmed = code.trim(); - const spaceIndex = trimmed.indexOf(" "); - if (spaceIndex === -1) return { head: trimmed, qualifier: null }; + const match = /\s+/.exec(trimmed); + if (!match || match.index === undefined) return { head: trimmed, qualifier: null }; return { - head: trimmed.slice(0, spaceIndex), - qualifier: trimmed.slice(spaceIndex + 1).trim() || null, + head: trimmed.slice(0, match.index), + qualifier: trimmed.slice(match.index + match[0].length).trim() || null, }; } diff --git a/src/components/forms/form-detail-page.tsx b/src/components/forms/form-detail-page.tsx index 1c6431820..e2f321327 100644 --- a/src/components/forms/form-detail-page.tsx +++ b/src/components/forms/form-detail-page.tsx @@ -43,7 +43,7 @@ import { toneSuccess, toneWarning, } from "@/components/ui-primitives"; -import { FormCodeBadge } from "@/components/forms/form-code-badge"; +import { FormCodeBadge, splitFormCode } from "@/components/forms/form-code-badge"; import { appModeHomeHref } from "@/lib/app-modes"; import { formCatalogDetails, type FormRecord } from "@/lib/form-ranker"; import type { ServiceChipTone, ServiceContact, ServiceCriterion, ServiceSummaryCard } from "@/lib/service-ranker"; @@ -202,6 +202,25 @@ function DetailCard({ card }: { card: ServiceSummaryCard }) { ); } +// Compact code cell for the pathway before/parallel/after lists. Visually it +// shows only the short head ("6B") so a qualifier like "6B attachment" can't +// overflow the fixed-width column, but the full code is exposed to assistive +// tech via an sr-only label (the decorative head is aria-hidden) and to sighted +// users via a tooltip — matching FormCodeBadge's pattern. +function PathwayStepCode({ code }: { code: string }) { + const { head, qualifier } = splitFormCode(code); + const fullCode = qualifier ? `${head} ${qualifier}` : head; + return ( + + {fullCode} + {head} + + ); +} + function PathwayContextCard({ form, code, @@ -252,7 +271,7 @@ function PathwayContextCard({ key={`${item.code}-${item.title}`} className="grid grid-cols-[3.25rem_minmax(0,1fr)] gap-2 border-b border-[color:var(--border)] p-2.5 last:border-b-0" > - {item.code} +

{item.title}

))} @@ -279,7 +298,7 @@ function PathwayContextCard({ key={`${item.code}-${item.title}`} className="grid grid-cols-[2.75rem_minmax(0,1fr)] gap-2 border-b border-[color:var(--border)] p-2.5 last:border-b-0" > - {item.code} +

{item.title}

))} @@ -294,7 +313,7 @@ function PathwayContextCard({ key={`${item.code}-${item.title}`} className="grid grid-cols-[2.75rem_minmax(0,1fr)] gap-2 border-b border-[color:var(--border)] p-2.5 last:border-b-0" > - {item.code} +

{item.title}

))} diff --git a/tests/form-code-badge.test.ts b/tests/form-code-badge.test.ts new file mode 100644 index 000000000..46c022b93 --- /dev/null +++ b/tests/form-code-badge.test.ts @@ -0,0 +1,12 @@ +import { describe, expect, it } from "vitest"; + +import { splitFormCode } from "@/components/forms/form-code-badge"; + +describe("splitFormCode", () => { + it("splits on spaces and other whitespace separators used by pathwayItems", () => { + expect(splitFormCode("6B attachment")).toEqual({ head: "6B", qualifier: "attachment" }); + expect(splitFormCode("6B\tattachment")).toEqual({ head: "6B", qualifier: "attachment" }); + expect(splitFormCode("6B\nattachment")).toEqual({ head: "6B", qualifier: "attachment" }); + expect(splitFormCode(" 10H ")).toEqual({ head: "10H", qualifier: null }); + }); +});