From b90e215d9b4a1462c8cb3be692bcc44edda1e6b8 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 14 Mar 2024 18:02:50 +0200 Subject: [PATCH] fix: [Rules > Shared exception lists][AXE-CORE]: Interactive controls must not be nested (#178023) Closes: https://github.com/elastic/security-team/issues/8611 ## Description The [axe browser plugin](https://deque.com/axe) is reporting a nested button (interactive control)in the shared exception list accordion(s). The accordion has a button to open/close and a link to the list detail view. Screenshot attached below. ### Steps to recreate 1. Open the Security Dashboards, then click Rules > Shared Exception Lists 2. Run an axe browser scan in Chrome, Edge, or Firefox 3. Verify the nested control error ### What was done? 1. Solution proposed by EUI team was applied. See https://github.com/elastic/eui/issues/7545 2. The component `ExceptionsListCard` has been slightly changed to make it more responsive. Before: After: https://github.com/elastic/kibana/assets/20072247/dd6c6681-980c-40ed-98cf-29a71f896bc2 ### Screen #### AXE Report ![image](https://github.com/elastic/kibana/assets/20072247/43313005-b7ec-49d1-9eed-30bfacbb5ecc) --- .../components/exceptions_list_card/index.tsx | 208 +++++++++--------- .../exceptions/pages/shared_lists/index.tsx | 29 ++- 2 files changed, 120 insertions(+), 117 deletions(-) diff --git a/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx b/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx index 00b97308c28c6..c084a84b3784f 100644 --- a/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/components/exceptions_list_card/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { memo } from 'react'; +import React, { memo, useMemo } from 'react'; import { EuiLink, @@ -15,7 +15,8 @@ import { EuiPanel, EuiText, EuiAccordion, - EuiButtonIcon, + useEuiTheme, + useEuiShadow, } from '@elastic/eui'; import { css } from '@emotion/css'; import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; @@ -72,13 +73,7 @@ interface ExceptionsListCardProps { }) => () => Promise; readOnly: boolean; } -const buttonCss = css` - z-index: 100; - .euiAccordion__buttonContent { - cursor: pointer; - width: 100%; - } -`; + const ExceptionPanel = styled(EuiPanel)` margin: -${euiThemeVars.euiSizeS} ${euiThemeVars.euiSizeM} 0 ${euiThemeVars.euiSizeM}; `; @@ -98,6 +93,25 @@ export const ExceptionsListCard = memo( onCancelManageRules, onRuleSelectionChange, } = useListDetailsView(exceptionsList.list_id); + const { euiTheme } = useEuiTheme(); + const panelShadow = useEuiShadow(); + + const euiAccordionStyles = useMemo( + () => css` + .euiAccordion__buttonContent { + flex: 1 1 auto; + cursor: pointer; + } + .euiAccordion__triggerWrapper { + z-index: 100; + position: relative; + border-radius: ${euiTheme.border.radius.medium}; + padding: ${euiTheme.size.base}; + ${panelShadow} + } + `, + [euiTheme.border.radius.medium, euiTheme.size.base, panelShadow] + ); const { listId, @@ -140,104 +154,86 @@ export const ExceptionsListCard = memo( }); return ( - - - - setToggleAccordion(!toggleAccordion)} - buttonContent={ - - - - - - - - - - - {listName} - - - - - - {listDescription} - - - - + <> + setToggleAccordion(!toggleAccordion)} + buttonContent={ + + + + + + + {listName} + + + + + + {listDescription} + + + + - - - - - - - - - - - - - - - - - - - - - - } - data-test-subj={`exceptionsManagementListCard-${listId}`} - > - - + + + + + + + + + + + + + + + + + - - - - + + + } + data-test-subj={`exceptionsManagementListCard-${listId}`} + > + + + + {showAddExceptionFlyout ? ( ( action={showIncludeExpiredExceptionsModal} /> ) : null} - + ); } ); diff --git a/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx b/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx index 3c0fab0343a36..480aa9aca0d2b 100644 --- a/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx +++ b/x-pack/plugins/security_solution/public/exceptions/pages/shared_lists/index.tsx @@ -28,6 +28,8 @@ import { ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types'; import { useApi, useExceptionLists } from '@kbn/securitysolution-list-hooks'; import { EmptyViewerState, ViewerStatus } from '@kbn/securitysolution-exception-list-components'; +import styled from 'styled-components'; +import { euiThemeVars } from '@kbn/ui-theme'; import { AutoDownload } from '../../../common/components/auto_download/auto_download'; import { useKibana } from '../../../common/lib/kibana'; import { useAppToasts } from '../../../common/hooks/use_app_toasts'; @@ -79,6 +81,10 @@ const SORT_FIELDS: Array<{ field: string; label: string; defaultOrder: 'asc' | ' }, ]; +const ExceptionsTable = styled(EuiFlexGroup)` + padding: ${euiThemeVars.euiSizeL} 0; +`; + export const SharedLists = React.memo(() => { const [{ loading: userInfoLoading, canUserCRUD, canUserREAD }] = useUserData(); @@ -587,19 +593,20 @@ export const SharedLists = React.memo(() => { sortFields={SORT_FIELDS} /> {exceptionListsWithRuleRefs.length > 0 && ( -
+ {exceptionListsWithRuleRefs.map((excList) => ( - + + + ))} -
+ )} )}