Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/components/forms/form-code-badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
}

Expand Down
27 changes: 23 additions & 4 deletions src/components/forms/form-detail-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
Comment thread
cursor[bot] marked this conversation as resolved.
return (
<span
className={cn("truncate text-sm font-bold text-[color:var(--text-heading)]", codeText)}
title={qualifier ? fullCode : undefined}
>
<span className="sr-only">{fullCode}</span>
<span aria-hidden>{head}</span>
</span>
);
}

function PathwayContextCard({
form,
code,
Expand Down Expand Up @@ -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"
>
<span className={cn("text-sm font-bold text-[color:var(--text-heading)]", codeText)}>{item.code}</span>
<PathwayStepCode code={item.code} />
<p className={cn("text-xs font-medium leading-5", textMuted)}>{item.title}</p>
</div>
))}
Expand All @@ -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"
>
<span className={cn("text-sm font-bold text-[color:var(--text-heading)]", codeText)}>{item.code}</span>
<PathwayStepCode code={item.code} />
<p className={cn("text-xs font-medium leading-5", textMuted)}>{item.title}</p>
</div>
))}
Expand All @@ -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"
>
<span className={cn("text-sm font-bold text-[color:var(--text-heading)]", codeText)}>{item.code}</span>
<PathwayStepCode code={item.code} />
<p className={cn("text-xs font-medium leading-5", textMuted)}>{item.title}</p>
</div>
))}
Expand Down
12 changes: 12 additions & 0 deletions tests/form-code-badge.test.ts
Original file line number Diff line number Diff line change
@@ -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 });
});
});