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
69 changes: 35 additions & 34 deletions docs/branch-review-ledger.md

Large diffs are not rendered by default.

142 changes: 42 additions & 100 deletions src/components/AccessibleTable.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"use client";

import { Maximize2, X } from "lucide-react";
import { type ReactNode, useCallback, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
import { Maximize2 } from "lucide-react";
import { type ReactNode, useCallback, useMemo, useRef, useState, useSyncExternalStore } from "react";
import { cn, textMuted } from "@/components/ui-primitives";
import { Sheet } from "@/components/ui/sheet";
import { normalizeAccessibleTable, type NormalizedAccessibleTable } from "@/lib/accessible-table-normalization";
import { normalizeExtractedGlyphs } from "@/lib/source-text-sanitizer";

Expand Down Expand Up @@ -144,7 +145,7 @@ function AccessibleTableMarkup({
: "whitespace-normal break-words",
index > 0 && "border-l border-[color:var(--border)]/70",
renderDensePreview
? "px-2 py-1.5 text-3xs uppercase tracking-[0.06em]"
? "px-2 py-1.5 text-2xs uppercase tracking-[0.06em]"
: expanded
? "px-4 py-3 text-sm"
: "px-3 py-2 text-xs",
Expand All @@ -162,7 +163,7 @@ function AccessibleTableMarkup({
? "overflow-hidden text-ellipsis whitespace-nowrap"
: "whitespace-normal break-words",
renderDensePreview
? "px-2 py-1.5 text-3xs uppercase tracking-[0.06em]"
? "px-2 py-1.5 text-2xs uppercase tracking-[0.06em]"
: expanded
? "px-4 py-3 text-sm"
: "px-3 py-2 text-xs",
Expand Down Expand Up @@ -215,7 +216,7 @@ function AccessibleTableMarkup({
className={cn(
renderDensePreview
? "sr-only"
: "mb-1 block text-3xs font-bold uppercase tracking-[0.08em] md:hidden",
: "mb-1 block text-2xs font-bold uppercase tracking-[0.08em] md:hidden",
textMuted,
)}
>
Expand Down Expand Up @@ -249,7 +250,7 @@ function AccessibleTableMarkup({
className={cn(
renderDensePreview
? "sr-only"
: "mb-1 block text-3xs font-bold uppercase tracking-[0.08em] md:hidden",
: "mb-1 block text-2xs font-bold uppercase tracking-[0.08em] md:hidden",
textMuted,
)}
>
Expand Down Expand Up @@ -356,9 +357,6 @@ export function AccessibleTable({
// can pass it here to show the real table screenshot instead of that grid.
lowConfidenceFallback?: ReactNode;
}) {
const dialogId = useId();
const closeButtonRef = useRef<HTMLButtonElement>(null);
const dialogRef = useRef<HTMLDivElement>(null);
const restoreFocusRef = useRef<HTMLElement | null>(null);
const [open, setOpen] = useState(false);
const canExpand = useMobileTableExpansion(expandOnMobile);
Expand All @@ -383,47 +381,6 @@ export function AccessibleTable({

const dialogOpen = open;

useEffect(() => {
if (!dialogOpen) return;
const previousOverflow = document.body.style.overflow;
document.body.style.overflow = "hidden";
const focusTimer = window.setTimeout(() => closeButtonRef.current?.focus(), 0);
const handleKeyDown = (event: globalThis.KeyboardEvent) => {
if (event.key === "Escape") {
event.preventDefault();
setOpen(false);
return;
}
if (event.key !== "Tab") return;
const focusable = Array.from(
dialogRef.current?.querySelectorAll<HTMLElement>(
'a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), summary, [tabindex]:not([tabindex="-1"])',
) ?? [],
).filter((element) => element.getAttribute("aria-hidden") !== "true");
if (focusable.length === 0) return;

const first = focusable[0];
const last = focusable[focusable.length - 1];
if (!dialogRef.current?.contains(document.activeElement)) {
event.preventDefault();
(event.shiftKey ? last : first).focus();
} else if (event.shiftKey && document.activeElement === first) {
event.preventDefault();
last.focus();
} else if (!event.shiftKey && document.activeElement === last) {
event.preventDefault();
first.focus();
}
};
document.addEventListener("keydown", handleKeyDown);
return () => {
window.clearTimeout(focusTimer);
document.body.style.overflow = previousOverflow;
document.removeEventListener("keydown", handleKeyDown);
restoreFocusRef.current?.focus();
};
}, [dialogOpen]);

if (!normalized) return null;

const { header, body } = normalized;
Expand Down Expand Up @@ -479,7 +436,6 @@ export function AccessibleTable({
aria-label={`Open ${title} full screen`}
aria-haspopup="dialog"
aria-expanded={dialogOpen}
aria-controls={dialogOpen ? dialogId : undefined}
onClick={(event) => {
event.stopPropagation();
openDialog(event.currentTarget);
Expand All @@ -491,56 +447,42 @@ export function AccessibleTable({
</button>
) : null}
</div>
{dialogOpen ? (
<div
ref={dialogRef}
id={dialogId}
data-testid="table-fullscreen-dialog"
role="dialog"
aria-modal="true"
aria-labelledby={`${dialogId}-title`}
className="fixed inset-0 z-[85] bg-[color:var(--background)] text-[color:var(--text)]"
onClick={() => setOpen(false)}
>
<div className="flex h-full min-w-0 flex-col" onClick={(event) => event.stopPropagation()}>
<div className="flex min-h-[64px] shrink-0 items-center justify-between gap-3 border-b border-[color:var(--border)] bg-[color:var(--surface-raised)] px-3 pb-2 pt-[max(0.75rem,env(safe-area-inset-top))] shadow-[var(--shadow-tight)]">
<div className="min-w-0">
<p className={cn("text-2xs font-bold uppercase tracking-[0.08em]", textMuted)}>Clinical table</p>
<h2
id={`${dialogId}-title`}
className="truncate text-base font-semibold text-[color:var(--text-heading)]"
>
{title}
</h2>
</div>
<button
type="button"
ref={closeButtonRef}
aria-label="Close full-screen table"
onClick={() => setOpen(false)}
className="grid h-11 w-11 shrink-0 place-items-center rounded-lg border border-[color:var(--border-lux)] bg-[color:var(--surface)] text-[color:var(--text)] shadow-[var(--shadow-inset)] transition hover:border-[color:var(--border-strong)] focus-visible:outline-none focus-visible:ring-4 focus-visible:ring-[color:var(--focus)]/25"
>
<X className="h-5 w-5" aria-hidden />
</button>
</div>
<div className="min-h-0 flex-1 overflow-auto p-3 pb-[max(1rem,env(safe-area-inset-bottom))]">
{showFallback ? (
<div data-testid="table-source-image-fallback">{lowConfidenceFallback}</div>
) : (
<AccessibleTableMarkup
caption={displayCaption}
header={header}
body={body}
compact={false}
expanded
rowActions={rowActions}
actionsHeader={actionsHeader}
/>
)}
</div>
</div>
<Sheet
open={dialogOpen}
onClose={() => setOpen(false)}
title={title}
description="Clinical table"
closeLabel="Close full-screen table"
returnFocusRef={restoreFocusRef}
mobilePlacement="fullscreen"
portal
testId="table-fullscreen-dialog"
contentClassName="sm:max-w-none"
bodyClassName="p-3 pb-[max(1rem,env(safe-area-inset-bottom))] sm:p-3"
>
<div>
{lowConfidence ? (
<p data-testid="table-low-confidence-note" className={cn("mb-1 text-xs", textMuted)}>
{showFallback
? "Table structure could not be confidently reconstructed — showing the source document image instead."
: "Table structure could not be confidently reconstructed — verify values against the source document."}
</p>
) : null}
{showFallback ? (
<div data-testid="table-source-image-fallback">{lowConfidenceFallback}</div>
) : (
<AccessibleTableMarkup
caption={displayCaption}
header={header}
body={body}
compact={false}
expanded
rowActions={rowActions}
actionsHeader={actionsHeader}
/>
)}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</div>
) : null}
</Sheet>
</>
);
}
2 changes: 1 addition & 1 deletion src/components/DocumentOrganizationBadges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function DocumentOrganizationBadges({
const needsReview = profile?.review_status === "needs_review";
const manualOverride = profile?.review_status === "manual_override";
const candidateCount = profile?.site?.candidates?.length ?? 0;
const sizeClass = compact ? "min-h-6 px-2 text-3xs" : "min-h-7 px-2 text-2xs";
const sizeClass = compact ? "min-h-6 px-2 text-2xs" : "min-h-7 px-2 text-2xs";

if (!siteLabel && !typeLabel && !needsReview && !manualOverride) return null;

Expand Down
8 changes: 4 additions & 4 deletions src/components/DocumentTagCloud.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ function DocumentTagChip({
const Icon = groupIcon[tag.group];
const tagClassName = cn(
"inline-flex max-w-full items-center gap-1 rounded-md border font-semibold shadow-[var(--shadow-inset)]",
compact ? "min-h-6 px-2 text-3xs" : "min-h-7 px-2 text-2xs",
compact ? "min-h-6 px-2 text-2xs" : "min-h-7 px-2 text-2xs",
groupToneClass(tag.group),
tag.queryMatched && "ring-2 ring-[color:var(--focus)]/25",
selected && "ring-2 ring-[color:var(--primary)]/35",
Expand Down Expand Up @@ -161,7 +161,7 @@ export function DocumentTagCloud({
onClick={() => setExpanded(true)}
className={cn(
"w-fit rounded-md border border-[color:var(--border-lux)] bg-[color:var(--surface-raised)] font-semibold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] transition hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)]",
compact ? "min-h-6 px-2 text-3xs" : "min-h-7 px-2 text-2xs",
compact ? "min-h-6 px-2 text-2xs" : "min-h-7 px-2 text-2xs",
)}
aria-label={`Show ${hiddenCount} more document tags`}
>
Expand Down Expand Up @@ -189,7 +189,7 @@ export function DocumentTagCloud({
onClick={() => setExpanded(true)}
className={cn(
"inline-flex items-center rounded-md border border-[color:var(--border-lux)] bg-[color:var(--surface-raised)] font-semibold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)] transition hover:border-[color:var(--border-strong)] hover:text-[color:var(--text)]",
compact ? "min-h-6 px-2 text-3xs" : "min-h-7 px-2 text-2xs",
compact ? "min-h-6 px-2 text-2xs" : "min-h-7 px-2 text-2xs",
)}
aria-label={`Show ${hiddenCount} more document tags`}
>
Expand All @@ -199,7 +199,7 @@ export function DocumentTagCloud({
<span
className={cn(
"inline-flex items-center rounded-md border border-[color:var(--border-lux)] bg-[color:var(--surface-raised)] font-semibold text-[color:var(--text-muted)] shadow-[var(--shadow-inset)]",
compact ? "min-h-6 px-2 text-3xs" : "min-h-7 px-2 text-2xs",
compact ? "min-h-6 px-2 text-2xs" : "min-h-7 px-2 text-2xs",
)}
>
+{hiddenCount}
Expand Down
4 changes: 2 additions & 2 deletions src/components/DocumentViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -571,7 +571,7 @@ function DocumentImage({ image }: { image: ImageRow }) {
{displayLabels.map((label) => (
<span
key={`${image.id}:${label}`}
className="inline-flex min-h-6 items-center rounded-md border border-[color:var(--border)] bg-[color:var(--surface-subtle)] px-2 text-3xs font-semibold text-[color:var(--text-muted)]"
className="inline-flex min-h-6 items-center rounded-md border border-[color:var(--border)] bg-[color:var(--surface-subtle)] px-2 text-2xs font-semibold text-[color:var(--text-muted)]"
>
{label}
</span>
Expand Down Expand Up @@ -1091,7 +1091,7 @@ function IndexedTextPanel({
{chunk.matchedTerms.slice(0, 5).map((term) => (
<span
key={`${chunk.id}:${term}`}
className="inline-flex min-h-6 items-center rounded-md border border-[color:var(--clinical-accent)]/20 bg-[color:var(--clinical-accent-soft)] px-2 text-3xs font-bold text-[color:var(--clinical-accent)]"
className="inline-flex min-h-6 items-center rounded-md border border-[color:var(--clinical-accent)]/20 bg-[color:var(--clinical-accent-soft)] px-2 text-2xs font-bold text-[color:var(--clinical-accent)]"
>
{term}
</span>
Expand Down
4 changes: 2 additions & 2 deletions src/components/applications-launcher-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ function QuickActions({ onSelect, mobile }: { onSelect: (id: string) => void; mo
<span
className={cn(
"block truncate font-bold leading-tight text-[color:var(--text-heading)]",
mobile ? "text-3xs" : "text-sm",
mobile ? "text-2xs" : "text-sm",
)}
>
{mobile ? action.label : action.desktopLabel}
Expand Down Expand Up @@ -374,7 +374,7 @@ function FilterTabs({
aria-controls="launcher-results-panel"
onClick={() => onFilterChange(filter.id)}
className={cn(
"inline-flex min-h-11 shrink-0 items-center justify-center gap-0.5 whitespace-nowrap rounded-lg border px-2 text-4xs font-bold transition",
"inline-flex min-h-11 shrink-0 items-center justify-center gap-0.5 whitespace-nowrap rounded-lg border px-2 text-2xs font-bold transition",
active
? "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-lux)] text-[color:var(--text-muted)]",
Expand Down
8 changes: 4 additions & 4 deletions src/components/clinical-dashboard/DocumentManagerPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -682,16 +682,16 @@ export function IngestionQualityConsole({
<div className="grid gap-3 sm:grid-cols-[minmax(0,1fr)_auto] sm:items-start">
<div className="min-w-0">
<div className="flex flex-wrap items-center gap-2">
<span className={cn(metadataPill, "min-h-6 px-2 text-3xs", qualityReviewTone(item.severity))}>
<span className={cn(metadataPill, "min-h-6 px-2 text-2xs", qualityReviewTone(item.severity))}>
{qualityReviewLabels[item.type]}
</span>
{item.qualityScore !== null ? (
<span className={cn(metadataPill, "nums min-h-6 px-2 text-3xs")}>
<span className={cn(metadataPill, "nums min-h-6 px-2 text-2xs")}>
index {item.qualityScore.toFixed(2)}
</span>
) : null}
{item.extractionQuality ? (
<span className={cn(metadataPill, "min-h-6 px-2 text-3xs")}>
<span className={cn(metadataPill, "min-h-6 px-2 text-2xs")}>
extraction:{item.extractionQuality}
</span>
) : null}
Expand Down Expand Up @@ -842,7 +842,7 @@ export function LibraryHealthStrip({
)}
aria-label={item.actionLabel}
>
<p className="text-3xs font-bold uppercase tracking-[0.06em] opacity-80">{item.label}</p>
<p className="text-2xs font-bold uppercase tracking-[0.06em]">{item.label}</p>
<p className="mt-1 text-xs font-semibold">{item.value}</p>
</button>
))}
Expand Down
4 changes: 2 additions & 2 deletions src/components/clinical-dashboard/clinical-badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,8 @@ export function ClinicalBadge({
<span
title={label}
className={cn(
"inline-flex h-[1.375rem] max-w-full shrink-0 items-center gap-1 rounded-md border px-1.5 text-3xs font-semibold leading-none shadow-[var(--shadow-inset)]",
compact && "h-5 px-1.5 text-3xs",
"inline-flex h-[1.375rem] max-w-full shrink-0 items-center gap-1 rounded-md border px-1.5 text-2xs font-semibold leading-none shadow-[var(--shadow-inset)]",
compact && "h-5 px-1.5 text-2xs",
clinicalBadgeToneClass(tone),
)}
>
Expand Down
2 changes: 1 addition & 1 deletion src/components/clinical-dashboard/dashboard-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export function MobileSectionFab({
<span
aria-hidden="true"
className={cn(
"absolute right-0 top-0 grid min-h-5 min-w-5 translate-x-1/4 -translate-y-1/4 place-items-center rounded-full border px-1 text-3xs font-bold leading-4 shadow-[var(--shadow-tight)]",
"absolute right-0 top-0 grid min-h-5 min-w-5 translate-x-1/4 -translate-y-1/4 place-items-center rounded-full border px-1 text-2xs font-bold leading-4 shadow-[var(--shadow-tight)]",
fabToneClassName(state.badgeTone),
)}
>
Expand Down
Loading
Loading