From 65dcd682f412a7349b169152c78c6763f87022f1 Mon Sep 17 00:00:00 2001 From: Hannah Brooks Date: Wed, 6 May 2026 10:19:12 -0400 Subject: [PATCH] [Security Solution][Detection Engine][A11y] Announce shared exception list creation to screen readers (#267588) Fixes #247067 When a shared exception list is created, the user is navigated to the detail page with no screen reader announcement. **Fix:** pass the list name as router state on navigation; on the detail page, derive a message from that state and render it in `EuiScreenReaderLive` with `focusRegionOnTextChange`. The `focusRegionOnTextChange` prop is required - the default aria-live toggle path fails silently in VoiceOver+Safari (noted in EUI source). The component is conditionally rendered to avoid stealing focus on page mounts where no list was just created. (cherry picked from commit 687055eeafe64a82a3eeb91e2cca4a6c78f25e30) --- .../create_shared_exception_list/index.tsx | 3 ++- .../exceptions/pages/list_detail_view/index.tsx | 12 ++++++++++-- .../exceptions/translations/list_details_view.ts | 6 ++++++ 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx index bf345daa1aea1..20ce2212acd9b 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/exceptions/components/create_shared_exception_list/index.tsx @@ -86,9 +86,10 @@ export const CreateSharedListFlyout = memo( navigateToApp(APP_UI_ID, { deepLinkId: SecurityPageName.exceptions, path: `/details/${createSharedExceptionListState.result.list_id}`, + state: { justCreated: newListDetails.name }, }); } - }, [createSharedExceptionListState, navigateToApp]); + }, [createSharedExceptionListState, navigateToApp, newListDetails.name]); const handleCreateSharedExceptionList = useCallback(() => { if (!createSharedExceptionListState.loading && newListDetails.name !== '') { diff --git a/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx b/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx index 065648c53840d..004ad8f3a101d 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/exceptions/pages/list_detail_view/index.tsx @@ -12,8 +12,8 @@ import { ExceptionListHeader, ViewerStatus, } from '@kbn/securitysolution-exception-list-components'; -import { EuiSkeletonText } from '@elastic/eui'; -import { useParams } from 'react-router-dom'; +import { EuiScreenReaderLive, EuiSkeletonText } from '@elastic/eui'; +import { useLocation, useParams } from 'react-router-dom'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import { SecurityPageName } from '../../../../common/constants'; import { SpyRoute } from '../../../common/utils/route/spy_routes'; @@ -64,6 +64,11 @@ export const ListsDetailViewComponent: FC = () => { handleReferenceDelete, } = useListDetailsView(exceptionListId); + const location = useLocation<{ justCreated?: string }>(); + const screenReaderMessage = location.state?.justCreated + ? i18n.SHARED_EXCEPTION_LIST_CREATED_SUCCESSFULLY(location.state.justCreated) + : ''; + const [showIncludeExpiredExceptionItemsModal, setShowIncludeExpiredExceptionItemsModal] = useState(null); @@ -190,6 +195,9 @@ export const ListsDetailViewComponent: FC = () => { ]); return ( <> + {screenReaderMessage && ( + {screenReaderMessage} + )} {detailsViewContent} diff --git a/x-pack/solutions/security/plugins/security_solution/public/exceptions/translations/list_details_view.ts b/x-pack/solutions/security/plugins/security_solution/public/exceptions/translations/list_details_view.ts index 8838c66be65bf..d480c743a87a9 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/exceptions/translations/list_details_view.ts +++ b/x-pack/solutions/security/plugins/security_solution/public/exceptions/translations/list_details_view.ts @@ -162,3 +162,9 @@ export const EXCEPTION_DUPLICATE_ERROR_DESCRIPTION = i18n.translate( defaultMessage: 'An error occurred duplicating a list', } ); + +export const SHARED_EXCEPTION_LIST_CREATED_SUCCESSFULLY = (listName: string) => + i18n.translate('xpack.securitySolution.exceptions.list.createdSuccessfully', { + values: { listName }, + defaultMessage: 'Exception list "{listName}" was created successfully.', + });