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 e00e8dfd280e5..fd0b893238132 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';
@@ -145,6 +146,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
@@ -199,7 +201,18 @@ 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);
+ // 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]
@@ -462,6 +475,9 @@ export const SharedLists = React.memo(() => {
return (
<>
+
+ {screenReaderMessage}
+