From 6803430ad3e34c06e2885009f3102b2f171b4fa9 Mon Sep 17 00:00:00 2001 From: Hannah Brooks Date: Tue, 17 Mar 2026 13:15:56 -0400 Subject: [PATCH 1/2] added EuiScreenReaderLive for toast announcement --- .../public/exceptions/pages/shared_lists/index.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx index 058b37dc34262..bbb2b2a85276e 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx @@ -19,6 +19,7 @@ import { EuiPageHeader, EuiPagination, EuiPopover, + EuiScreenReaderLive, EuiSpacer, EuiText, } from '@elastic/eui'; @@ -152,6 +153,7 @@ export const SharedLists = React.memo(() => { const [exportDownload, setExportDownload] = useState<{ name?: string; blob?: Blob }>({}); const [displayImportListFlyout, setDisplayImportListFlyout] = useState(false); + const [screenReaderMessage, setScreenReaderMessage] = useState(''); const { addError, addSuccess } = useAppToasts(); // Loading states @@ -206,7 +208,9 @@ export const SharedLists = React.memo(() => { const handleExportSuccess = useCallback( (listId: string, name: string) => (blob: Blob): void => { - addSuccess(i18n.EXCEPTION_LIST_EXPORTED_SUCCESSFULLY(name)); + const message = i18n.EXCEPTION_LIST_EXPORTED_SUCCESSFULLY(name); + addSuccess(message); + setScreenReaderMessage(message); setExportDownload({ name: listId, blob }); }, [addSuccess] @@ -468,6 +472,7 @@ export const SharedLists = React.memo(() => { return ( <> + {screenReaderMessage} Date: Tue, 17 Mar 2026 16:17:21 -0400 Subject: [PATCH 2/2] make annoucement more assertive and add comment for info --- .../exceptions/pages/shared_lists/index.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx index bbb2b2a85276e..4b3d34f452113 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx @@ -210,7 +210,16 @@ export const SharedLists = React.memo(() => { (blob: Blob): void => { const message = i18n.EXCEPTION_LIST_EXPORTED_SUCCESSFULLY(name); addSuccess(message); - setScreenReaderMessage(message); + // If the same list is exported twice in a row, React won't re-render + // since state hasn't changed, so the live region won't re-announce. + // Clearing to '' first ensures VoiceOver sees a new change on the next frame. + setScreenReaderMessage((current) => { + if (current === message) { + requestAnimationFrame(() => setScreenReaderMessage(message)); + return ''; + } + return message; + }); setExportDownload({ name: listId, blob }); }, [addSuccess] @@ -472,7 +481,9 @@ export const SharedLists = React.memo(() => { return ( <> - {screenReaderMessage} + + {screenReaderMessage} +