fix(frontend): blur active element on every tab switch path (B21 follow-up)

The previous B21 patch only blurred on user-initiated tab clicks via
onTabChange. Two other paths still set activeKey while a JSON-tab
input retained focus:

- importLink: after a successful share-link parse, setActiveKey('1')
  switched to the form tab while the user's focus was still on the
  Input.Search they just pressed Enter in. Chrome logged the same
  "Blocked aria-hidden" warning because the panel they were leaving
  became aria-hidden synchronously, with their input still focused.

- onTabChange entering the JSON tab: also did a bare setActiveKey
  with no blur, so going from a focused form input INTO the JSON
  tab could trip the warning in reverse.

Fix: centralized switchTab(key) that blurs document.activeElement
sync before calling setActiveKey. Every internal tab transition
(importLink, onTabChange both directions) now routes through it.
The single setActiveKey('1') in the open-modal useEffect is left as
a plain setter because there's no focused input at modal-open time.
This commit is contained in:
MHSanaei 2026-05-26 20:32:03 +02:00
parent d2f5f530e0
commit bb20cf506b
No known key found for this signature in database
GPG key ID: 7E4060F2FBE5AB7A

View file

@ -204,7 +204,7 @@ export default function OutboundFormModal({
setJsonDirty(false); setJsonDirty(false);
setLinkInput(''); setLinkInput('');
messageApi.success('Link imported successfully'); messageApi.success('Link imported successfully');
setActiveKey('1'); switchTab('1');
} }
const isEdit = outboundProp != null; const isEdit = outboundProp != null;
@ -358,28 +358,32 @@ export default function OutboundFormModal({
return true; return true;
} }
function onTabChange(key: string) { // Wrap every tab switch with a blur of the active element. AntD marks
if (document.activeElement instanceof HTMLElement) { // the outgoing panel `aria-hidden="true"` synchronously when the
document.activeElement.blur(); // controlled activeKey flips; if a focused input is still inside that
// panel (e.g. Input.Search on the JSON tab after user hits Enter to
// import), Chrome logs a WAI-ARIA warning. Doing the blur right
// before setActiveKey ensures the panel is unfocused by the time
// AntD applies the attribute.
function switchTab(key: string) {
if (typeof document !== 'undefined') {
(document.activeElement as HTMLElement | null)?.blur?.();
} }
setActiveKey(key);
}
function onTabChange(key: string) {
if (key === '2') { if (key === '2') {
const values = form.getFieldsValue(true) as OutboundFormValues; const values = form.getFieldsValue(true) as OutboundFormValues;
setJsonText(JSON.stringify(formValuesToWirePayload(values), null, 2)); setJsonText(JSON.stringify(formValuesToWirePayload(values), null, 2));
setJsonDirty(false); setJsonDirty(false);
setActiveKey(key); switchTab(key);
return; return;
} }
if (key === '1' && activeKey === '2') { if (key === '1' && activeKey === '2') {
if (!applyJsonToForm()) return; if (!applyJsonToForm()) return;
} }
// Blur the currently focused element before AntD marks the outgoing switchTab(key);
// tab panel aria-hidden. Without this, a focused input inside the
// hidden panel triggers a Chrome a11y warning ("Blocked aria-hidden
// on an element because its descendant retained focus").
if (typeof document !== 'undefined') {
(document.activeElement as HTMLElement | null)?.blur?.();
}
setActiveKey(key);
} }
async function onOk() { async function onOk() {