Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
02ce93e
fix(ui): implement orientation adaptive design audit recommendations
BigSimmo Jul 24, 2026
bbc16cc
Merge remote-tracking branch 'origin/main' into HEAD
cursoragent Jul 24, 2026
c2494b3
fix: remove duplicate command dropdown height cap
cursoragent Jul 24, 2026
864f738
chore: note review reply permission denial
cursoragent Jul 24, 2026
4bd3630
docs: record PR babysit sweep
cursoragent Jul 24, 2026
f33a824
Merge remote-tracking branch 'origin/main' into HEAD
cursoragent Jul 24, 2026
a5de573
Merge remote-tracking branch 'origin/main' into HEAD
cursoragent Jul 24, 2026
5aec89d
Merge remote-tracking branch 'origin/main' into implement-audit-recom…
cursoragent Jul 24, 2026
b5f8959
Merge remote-tracking branch 'origin/main' into HEAD
BigSimmo Jul 24, 2026
70814a8
docs: record Run PR behind-main sweep for #1141
BigSimmo Jul 24, 2026
7cd9d42
Merge remote-tracking branch 'origin/main' into implement-audit-recom…
BigSimmo Jul 24, 2026
04d07f2
docs: ledger re-sync sweep for PR #1141
BigSimmo Jul 24, 2026
a1cf29a
Merge branch 'main' into implement-audit-recommendations-fix
cursoragent Jul 24, 2026
0aaf441
fix(ui): collapse dock child safe-area padding
BigSimmo Jul 24, 2026
d0b988a
docs: record PR 1141 maintenance
BigSimmo Jul 24, 2026
61d9ba1
Merge branch 'main' into implement-audit-recommendations-fix
cursoragent Jul 24, 2026
8c179aa
Merge branch 'main' into implement-audit-recommendations-fix
cursoragent Jul 24, 2026
f6cef6d
Merge branch 'main' into implement-audit-recommendations-fix
BigSimmo Jul 24, 2026
6216716
Merge remote-tracking branch 'origin/main' into implement-audit-recom…
cursoragent Jul 24, 2026
4fb23cc
Merge remote-tracking branch 'origin/main' into implement-audit-recom…
cursoragent Jul 24, 2026
04733b7
Merge cursor/pr-queue-hygiene-72ec for postcss audit + PR branch sync
cursoragent Jul 24, 2026
ad4ac1e
Merge branch 'main' into implement-audit-recommendations-fix
github-actions[bot] Jul 24, 2026
6ea9585
merge origin/main into implement-audit-recommendations-fix
BigSimmo Jul 25, 2026
a305329
Merge branch 'main' into implement-audit-recommendations-fix
github-actions[bot] Jul 25, 2026
5236f2d
Merge branch 'main' into implement-audit-recommendations-fix
github-actions[bot] Jul 25, 2026
8265805
merge origin/main into implement-audit-recommendations-fix
BigSimmo Jul 25, 2026
b2b3fd5
fix(ui): avoid Sheet max-height racing caller caps
BigSimmo Jul 25, 2026
3b578d3
test(ui): poll guide dialog focus trap across viewport sizes
BigSimmo Jul 25, 2026
589f0a5
merge origin/main into implement-audit-recommendations-fix
BigSimmo Jul 25, 2026
d213b8a
fix(ui): do not steal focus from a newly opened sheet on restore retry
BigSimmo Jul 25, 2026
76a6eef
merge origin/main into implement-audit-recommendations-fix
BigSimmo Jul 25, 2026
8102d51
fix(ui): retry Sheet autofocus when open races a closing sibling
BigSimmo Jul 25, 2026
7b04442
merge origin/main
BigSimmo Jul 25, 2026
b9230b7
test(ui): harden Sources opener focus restore assertion after Escape
BigSimmo Jul 25, 2026
95f3345
docs(review): record babysit merges for #1140 #1171 #1180 #1158
BigSimmo Jul 25, 2026
1ff9ca2
merge origin/main into implement-audit-recommendations-fix
BigSimmo Jul 25, 2026
bf091d9
fix(ui): stabilize Sources sheet autofocus on open
BigSimmo Jul 25, 2026
d62933a
Merge branch 'main' into implement-audit-recommendations-fix
github-actions[bot] Jul 25, 2026
79da125
Merge branch 'main' into implement-audit-recommendations-fix
github-actions[bot] Jul 25, 2026
05373f1
ci: retrigger PR policy check on tip
BigSimmo Jul 25, 2026
8b5673b
Merge branch 'main' into implement-audit-recommendations-fix
github-actions[bot] Jul 25, 2026
da35104
merge origin/main after #1157 landed
BigSimmo Jul 25, 2026
82efa0d
fix(ui): stop stacked Sheet focus steal; assert Escape restore honestly
BigSimmo Jul 25, 2026
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
9 changes: 9 additions & 0 deletions docs/branch-review-ledger.md

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/components/AccessibleTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function AccessibleTableMarkup({
<div
className={cn(
"overflow-hidden rounded-lg border border-[color:var(--border)] bg-[color:var(--surface)]",
expanded && "max-h-[calc(100dvh-8.5rem)] rounded-none border-0 sm:rounded-lg sm:border",
expanded && "max-h-[calc(100dvh-8.5rem)] flex flex-col rounded-none border-0 sm:rounded-lg sm:border",
)}
>
{caption && !(hidePreviewCaption && !expanded) ? (
Expand All @@ -112,7 +112,7 @@ function AccessibleTableMarkup({
{caption}
</div>
) : null}
<div className="overflow-x-auto">
<div className={cn("overflow-x-auto", expanded && "flex-1 min-h-0")}>
<table
aria-label={caption ?? undefined}
className={cn(
Expand Down Expand Up @@ -460,7 +460,7 @@ export function AccessibleTable({
contentClassName="sm:max-w-none"
bodyClassName="py-3 pb-[max(1rem,env(safe-area-inset-bottom))] modal-landscape-container sm:p-3"
>
<div>
<div className="flex flex-col h-full">
{lowConfidence ? (
<p data-testid="table-low-confidence-note" className={cn("mb-1 text-xs", textMuted)}>
{showFallback
Expand Down
4 changes: 3 additions & 1 deletion src/components/clinical-dashboard/dashboard-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ export function UtilityDrawer({
sheetReturnFocusRef?: RefObject<HTMLElement | null>;
}) {
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
const [usesSheet, setUsesSheet] = useState(false);
// `all` always matches; default true so the first open does not mount drawer
// children in the hidden <details> (browser autoFocus) then remount into Sheet.
const [usesSheet, setUsesSheet] = useState(sheetBreakpoint === "all");
const mobileTriggerRef = useRef<HTMLButtonElement>(null);
const open = controlledOpen ?? uncontrolledOpen;
const sheetTriggerClassName =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ function CommandDropdown({
role="listbox"
aria-label={`${mode.label} search suggestions`}
className={cn(
"max-h-[min(55dvh,26rem)] overflow-y-auto overscroll-contain p-2",
"max-h-[calc(100dvh-5rem)] overflow-y-auto overscroll-contain p-2",
opensUpward ? "sm:max-h-[min(38dvh,20rem)]" : "sm:max-h-[min(42dvh,24rem)]",
)}
>
Expand Down
77 changes: 71 additions & 6 deletions src/components/ui/sheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,14 @@ export function Sheet({
// Pending focus-restore timers from the previous close. Cleared on the next
// open and on unmount so a torn-down jsdom environment cannot throw from a
// stale 50ms retry under Vitest coverage workers.
const restoreTimersRef = useRef<{ frame: number | null; timeout: number | null }>({
const restoreTimersRef = useRef<{
frame: number | null;
timeout: number | null;
openFocusRetry: number | null;
}>({
frame: null,
timeout: null,
openFocusRetry: null,
});
const unmountingRef = useRef(false);
const titleId = useId();
Expand All @@ -146,6 +151,10 @@ export function Sheet({
window.clearTimeout(restoreTimers.timeout);
restoreTimers.timeout = null;
}
if (restoreTimers.openFocusRetry != null) {
window.clearInterval(restoreTimers.openFocusRetry);
restoreTimers.openFocusRetry = null;
}
};
}, []);

Expand Down Expand Up @@ -188,13 +197,54 @@ export function Sheet({

const explicitReturnElement = returnFocusRef?.current ?? null;
const previousActiveElement = document.activeElement instanceof HTMLElement ? document.activeElement : null;
const restoreTimers = restoreTimersRef.current;
if (restoreTimers.openFocusRetry != null) {
window.clearInterval(restoreTimers.openFocusRetry);
restoreTimers.openFocusRetry = null;
}
pushSheet(sheetId);
const focusFrame = window.requestAnimationFrame(() => {
const focusTarget =
const resolveFocusTarget = () =>
initialFocusRef?.current ??
panelRef.current?.querySelector<HTMLElement>('[data-sheet-autofocus="true"]') ??
closeRef.current;
focusTarget?.focus({ preventScroll: true });
const focusIfNeeded = () => {
// Never reclaim focus once a newer Sheet is stacked above this one.
if (!isTopmostSheet(sheetId)) return null;
const focusTarget = resolveFocusTarget();
if (!focusTarget?.isConnected) return null;
if (document.activeElement === focusTarget) return focusTarget;
// Reclaim when focus is outside the panel (or still on body after a
// remount). Do not steal from another in-panel control the user tabbed to.
const active = document.activeElement;
if (
active == null ||
active === document.body ||
(panelRef.current != null && !panelRef.current.contains(active))
) {
focusTarget.focus({ preventScroll: true });
}
return focusTarget;
};
focusIfNeeded();
// Retries cover sibling-sheet teardown and late-mounted autofocus inputs
// (UtilityDrawer media sync / deferred drawer children).
let attempts = 0;
const retryTimer = window.setInterval(() => {
attempts += 1;
const focusTarget = focusIfNeeded();
if (
attempts >= 8 ||
!isTopmostSheet(sheetId) ||
(focusTarget != null && document.activeElement === focusTarget)
) {
window.clearInterval(retryTimer);
if (restoreTimers.openFocusRetry === retryTimer) {
restoreTimers.openFocusRetry = null;
}
}
}, 50);
restoreTimers.openFocusRetry = retryTimer;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
});

function onKeyDown(event: KeyboardEvent) {
Expand Down Expand Up @@ -235,7 +285,6 @@ export function Sheet({
}

window.addEventListener("keydown", onKeyDown);
const restoreTimers = restoreTimersRef.current;
return () => {
window.cancelAnimationFrame(focusFrame);
window.removeEventListener("keydown", onKeyDown);
Expand All @@ -247,6 +296,10 @@ export function Sheet({
if (restoreTimers.timeout != null) {
window.clearTimeout(restoreTimers.timeout);
}
if (restoreTimers.openFocusRetry != null) {
window.clearInterval(restoreTimers.openFocusRetry);
restoreTimers.openFocusRetry = null;
}
if (unmountingRef.current) return;
// Focus restore is best-effort. Under Vitest coverage workers the jsdom
// `document` can be torn down before this rAF/setTimeout pair fires; bare
Expand All @@ -259,7 +312,14 @@ export function Sheet({
restoreTimers.timeout = window.setTimeout(() => {
restoreTimers.timeout = null;
if (typeof document === "undefined") return;
if (!restoreTarget.isConnected || document.activeElement === restoreTarget) {
// Only retry when focus fell through to the document body. If another
// surface (e.g. a Guide dialog opened from a phone menu sheet) already
// took focus, do not steal it back.
if (
!restoreTarget.isConnected ||
document.activeElement === restoreTarget ||
(document.activeElement !== document.body && document.activeElement != null)
) {
return;
}
restoreTarget.focus({ preventScroll: true });
Expand Down Expand Up @@ -335,7 +395,12 @@ export function Sheet({
"rounded-t-2xl motion-safe:animate-sheet-up",
defaultSheetUsesViewportSize
? "min-h-[calc(100dvh-2rem)] max-h-[calc(100dvh-1rem)] sm:min-h-0"
: "max-h-[88dvh]",
: // Skip a default max-h when the caller already caps height via
// contentClassName — cn() does not last-win Tailwind utilities,
// so two unprefixed max-h-* classes race in CSS source order.
/\bmax-h-/.test(contentClassName ?? "")
? undefined
: "max-h-[calc(100dvh-2rem)] sm:max-h-[88dvh]",
),
),
),
Expand Down
2 changes: 1 addition & 1 deletion src/components/universal-search-command-mockups.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ function SmartDropdown({
id={listboxId}
role="listbox"
aria-label={`${mode.label} search suggestions`}
className="max-h-[26rem] overflow-y-auto p-2"
className="max-h-[calc(100dvh-5rem)] sm:max-h-[26rem] overflow-y-auto p-2"
>
{sections.map((section) =>
section.items.length ? (
Expand Down
1 change: 1 addition & 0 deletions tests/clinical-dashboard-merge-artifacts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ describe("ClinicalDashboard merge-artifact guards", () => {
expect(clinicalDashboardSource).toContain("resolveMobileComposerReserve(");
expect(clinicalDashboardSource).toContain('from "@/components/clinical-dashboard/mobile-composer-reserve"');
expect(clinicalDashboardSource).not.toContain('bottomComposerHidden ? "max(0.75rem, env(safe-area-inset-bottom))"');
expect(clinicalDashboardSource).not.toMatch(/pb-\[max\([^"']*safe-area-inset-bottom/);
expect(clinicalDashboardSource).toContain(
'"max-sm:pb-[var(--mobile-composer-reserve)] max-sm:[scroll-padding-bottom:var(--mobile-composer-reserve)] sm:mb-24"',
);
Expand Down
11 changes: 11 additions & 0 deletions tests/search-command-surface.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { describe, expect, it } from "vitest";
import { readFileSync } from "node:fs";

import {
commandDropdownCanDisplay,
Expand Down Expand Up @@ -139,4 +140,14 @@ describe("search command surface", () => {
expect(differentialRedFlagTerms).toContain("confusion");
expect(differentialRedFlagTerms.length).toBeGreaterThan(3);
});

it("keeps one sm max-height cap per command dropdown placement", () => {
const source = readFileSync(
new URL("../src/components/clinical-dashboard/universal-search-command-surface.tsx", import.meta.url),
"utf8",
);

expect(source).not.toContain("sm:max-h-[min(55dvh,26rem)]");
expect(source).toContain('opensUpward ? "sm:max-h-[min(38dvh,20rem)]" : "sm:max-h-[min(42dvh,24rem)]"');
});
});
11 changes: 8 additions & 3 deletions tests/ui-smoke.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3120,7 +3120,11 @@ test.describe("Clinical KB UI smoke coverage", () => {
await expect(page.locator("details#dashboard-documents-drawer")).not.toHaveAttribute("open", "");
await page.keyboard.press("Escape");
await expect(resultsLibraryDialog).toHaveCount(0);
await expect.poll(async () => openSourcesButton.evaluate((el) => el === document.activeElement)).toBe(true);
await expect
.poll(async () => openSourcesButton.evaluate((el) => el === document.activeElement), {
timeout: 15_000,
})
.toBe(true);
Comment thread
coderabbitai[bot] marked this conversation as resolved.

await page.reload({ waitUntil: "domcontentloaded" });
await expect(documentResults).toBeVisible();
Expand Down Expand Up @@ -3984,10 +3988,11 @@ test.describe("Clinical KB UI smoke coverage", () => {
await gotoApp(page, "/");

const dialog = await openGuide(page);
await expect.poll(async () => dialog.evaluate((element) => element.contains(document.activeElement))).toBe(true);
await page.keyboard.press("Shift+Tab");
expect(await dialog.evaluate((element) => element.contains(document.activeElement))).toBe(true);
await expect.poll(async () => dialog.evaluate((element) => element.contains(document.activeElement))).toBe(true);
await page.keyboard.press("Tab");
expect(await dialog.evaluate((element) => element.contains(document.activeElement))).toBe(true);
await expect.poll(async () => dialog.evaluate((element) => element.contains(document.activeElement))).toBe(true);
await dialog.getByRole("button", { name: "Close guide" }).click();
await expect(dialog).toBeHidden();

Expand Down
Loading