From 5272440a218546a1441436044d64ca17e6caf400 Mon Sep 17 00:00:00 2001 From: arc53-machine <232052973+arc53-machine@users.noreply.github.com> Date: Wed, 23 Sep 2026 21:08:27 +0100 Subject: [PATCH] Return focus to View trace when the drawer closes The drawer is opened from a Logs row rather than a SheetTrigger, so Radix had nothing to restore focus to. It now remembers what had focus when it opened and returns there on close; the e2e spec checks it. --- frontend/src/settings/traces/TraceSheet.tsx | 19 ++++++++++++++++++- .../e2e/specs/tier-a/execution-traces.spec.ts | 5 +++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/frontend/src/settings/traces/TraceSheet.tsx b/frontend/src/settings/traces/TraceSheet.tsx index f459527f..eb7e2385 100644 --- a/frontend/src/settings/traces/TraceSheet.tsx +++ b/frontend/src/settings/traces/TraceSheet.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; @@ -39,6 +39,9 @@ export default function TraceSheet({ const [traces, setTraces] = useState([]); const [loading, setLoading] = useState(false); const [failed, setFailed] = useState(false); + // The sheet is opened from a Logs row, not a SheetTrigger, so Radix has no + // trigger to return focus to on close; remember what had focus instead. + const returnFocusRef = useRef(null); useEffect(() => { if (!traceRef) return; @@ -76,6 +79,20 @@ export default function TraceSheet({ side="right" title={t('settings.logs.trace.title')} aria-describedby={undefined} + onOpenAutoFocus={() => { + returnFocusRef.current = + document.activeElement instanceof HTMLElement + ? document.activeElement + : null; + }} + onCloseAutoFocus={(event) => { + const target = returnFocusRef.current; + returnFocusRef.current = null; + if (target?.isConnected) { + event.preventDefault(); + target.focus(); + } + }} className="w-full overflow-y-auto sm:max-w-3xl" >
diff --git a/tests/e2e/specs/tier-a/execution-traces.spec.ts b/tests/e2e/specs/tier-a/execution-traces.spec.ts index e355b43d..709585bb 100644 --- a/tests/e2e/specs/tier-a/execution-traces.spec.ts +++ b/tests/e2e/specs/tier-a/execution-traces.spec.ts @@ -114,6 +114,11 @@ test.describe('tier-a ยท execution traces', () => { if (process.env.TRACE_SCREENSHOT) { await page.screenshot({ path: process.env.TRACE_SCREENSHOT, fullPage: false }); } + + // Closing returns focus to the button that opened the drawer. + await page.keyboard.press('Escape'); + await expect(sheet).toBeHidden(); + await expect(page.getByRole('button', { name: 'View trace' })).toBeFocused(); } finally { await api.dispose(); await context.close();