Skip to content

Commit cec25e5

Browse files
authored
[Security Solution][A11Y] add aria labels to flyout panels to support screen readers (elastic#250824)
## Summary [Issue 1](elastic#250130) [Issue 2](elastic#250337) This is a partial fix for issue 1, and full fix for issue 2. It does not address the history button popover (issue 1), which will be a separate PR. This PR adds an aria label to the the security solution flyout based on the panel it hosts. Used AI to generate the `panel_aria_labels.ts` file. It looks reasonable to me but not sure if the default descriptions are entirely correct (might be lacking some context). https://github.com/user-attachments/assets/0d1203e0-5f47-44dd-92c6-73b344bf816c ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This was checked for breaking HTTP API changes, and any breaking changes have been approved by the breaking-change committee. The `release_note:breaking` label should be applied in these situations. - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) - [ ] Review the [backport guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing) and apply applicable `backport:*` labels.
1 parent c19ed52 commit cec25e5

4 files changed

Lines changed: 226 additions & 1 deletion

File tree

x-pack/solutions/security/packages/expandable-flyout/src/components/container.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ export const Container: React.FC<ContainerProps> = memo(
170170
type,
171171
]);
172172

173+
const flyoutAriaLabel = useMemo(() => {
174+
const registeredPanel = registeredPanels.find((panel) => panel.key === right?.id);
175+
return registeredPanel?.['aria-label'];
176+
}, [registeredPanels, right?.id]);
177+
173178
// callback function called when user changes the flyout's width
174179
const onResize = useCallback(
175180
(width: number) => {
@@ -219,6 +224,7 @@ export const Container: React.FC<ContainerProps> = memo(
219224
css={customStyles}
220225
onResize={onResize}
221226
minWidth={minFlyoutWidth}
227+
aria-label={flyoutAriaLabel}
222228
>
223229
<ResizableContainer
224230
leftComponent={leftComponent as React.ReactElement}

x-pack/solutions/security/packages/expandable-flyout/src/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ export interface Panel {
8585
* Component to be rendered
8686
*/
8787
component: (props: FlyoutPanelProps) => React.ReactElement;
88+
/**
89+
* Human-readable label for the panel
90+
*/
91+
'aria-label'?: string;
8892
}
8993

9094
export interface FlyoutPanelHistory {

x-pack/solutions/security/plugins/security_solution/public/flyout/index.tsx

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,37 @@ import type { ServicePanelExpandableFlyoutProps } from './entity_details/service
7474
import { ServicePanel } from './entity_details/service_right';
7575
import type { ServiceDetailsExpandableFlyoutProps } from './entity_details/service_details_left';
7676
import { ServiceDetailsPanel, ServiceDetailsPanelKey } from './entity_details/service_details_left';
77+
import {
78+
ATTACK_DETAILS_RIGHT_PANEL_ARIA_LABEL,
79+
DOCUMENT_DETAILS_ALERT_REASON_PANEL_ARIA_LABEL,
80+
DOCUMENT_DETAILS_ANALYZER_PANEL_ARIA_LABEL,
81+
DOCUMENT_DETAILS_ISOLATE_HOST_PANEL_ARIA_LABEL,
82+
DOCUMENT_DETAILS_LEFT_PANEL_ARIA_LABEL,
83+
DOCUMENT_DETAILS_PREVIEW_PANEL_ARIA_LABEL,
84+
DOCUMENT_DETAILS_RIGHT_PANEL_ARIA_LABEL,
85+
DOCUMENT_DETAILS_SESSION_VIEW_PANEL_ARIA_LABEL,
86+
EASE_PANEL_ARIA_LABEL,
87+
GENERIC_ENTITY_DETAILS_PANEL_ARIA_LABEL,
88+
GENERIC_ENTITY_PANEL_ARIA_LABEL,
89+
GRAPH_GROUPED_NODE_PREVIEW_PANEL_ARIA_LABEL,
90+
HOST_DETAILS_PANEL_ARIA_LABEL,
91+
HOST_PANEL_ARIA_LABEL,
92+
HOST_PREVIEW_PANEL_ARIA_LABEL,
93+
IOC_RIGHT_PANEL_ARIA_LABEL,
94+
MISCONFIGURATION_FINDINGS_PREVIEW_PANEL_ARIA_LABEL,
95+
MISCONFIGURATION_PANEL_ARIA_LABEL,
96+
NETWORK_PANEL_ARIA_LABEL,
97+
NETWORK_PREVIEW_PANEL_ARIA_LABEL,
98+
RULE_PANEL_ARIA_LABEL,
99+
RULE_PREVIEW_PANEL_ARIA_LABEL,
100+
SERVICE_DETAILS_PANEL_ARIA_LABEL,
101+
SERVICE_PANEL_ARIA_LABEL,
102+
USER_DETAILS_PANEL_ARIA_LABEL,
103+
USER_PANEL_ARIA_LABEL,
104+
USER_PREVIEW_PANEL_ARIA_LABEL,
105+
VULNERABILITY_FINDINGS_PANEL_ARIA_LABEL,
106+
VULNERABILITY_FINDINGS_PREVIEW_PANEL_ARIA_LABEL,
107+
} from './panel_aria_labels';
77108
import {
78109
MisconfigurationFindingsPanelKey,
79110
MisconfigurationFindingsPreviewPanelKey,
@@ -104,14 +135,15 @@ const GraphGroupedNodePreviewPanel = React.lazy(() =>
104135
* List of all panels that will be used within the document details expandable flyout.
105136
* This needs to be passed to the expandable flyout registeredPanels property.
106137
*/
107-
const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels'] = [
138+
export const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels'] = [
108139
{
109140
key: DocumentDetailsRightPanelKey,
110141
component: (props) => (
111142
<DocumentDetailsProvider {...(props as DocumentDetailsProps).params}>
112143
<RightPanel path={props.path as DocumentDetailsProps['path']} />
113144
</DocumentDetailsProvider>
114145
),
146+
'aria-label': DOCUMENT_DETAILS_RIGHT_PANEL_ARIA_LABEL,
115147
},
116148
{
117149
key: DocumentDetailsLeftPanelKey,
@@ -120,6 +152,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
120152
<LeftPanel path={props.path as DocumentDetailsProps['path']} />
121153
</DocumentDetailsProvider>
122154
),
155+
'aria-label': DOCUMENT_DETAILS_LEFT_PANEL_ARIA_LABEL,
123156
},
124157
{
125158
key: DocumentDetailsPreviewPanelKey,
@@ -128,6 +161,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
128161
<PreviewPanel path={props.path as DocumentDetailsProps['path']} />
129162
</DocumentDetailsProvider>
130163
),
164+
'aria-label': DOCUMENT_DETAILS_PREVIEW_PANEL_ARIA_LABEL,
131165
},
132166
{
133167
key: DocumentDetailsAlertReasonPanelKey,
@@ -136,6 +170,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
136170
<AlertReasonPanel />
137171
</AlertReasonPanelProvider>
138172
),
173+
'aria-label': DOCUMENT_DETAILS_ALERT_REASON_PANEL_ARIA_LABEL,
139174
},
140175
{
141176
key: GraphGroupedNodePreviewPanelKey,
@@ -144,16 +179,19 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
144179
const params = props.params as unknown as GraphGroupedNodePreviewPanelProps;
145180
return <GraphGroupedNodePreviewPanel {...params} />;
146181
},
182+
'aria-label': GRAPH_GROUPED_NODE_PREVIEW_PANEL_ARIA_LABEL,
147183
},
148184
{
149185
key: RulePanelKey,
150186
component: (props) => <RulePanel {...(props as RulePanelExpandableFlyoutProps).params} />,
187+
'aria-label': RULE_PANEL_ARIA_LABEL,
151188
},
152189
{
153190
key: RulePreviewPanelKey,
154191
component: (props) => (
155192
<RulePanel {...(props as RulePanelExpandableFlyoutProps).params} isPreviewMode />
156193
),
194+
'aria-label': RULE_PREVIEW_PANEL_ARIA_LABEL,
157195
},
158196
{
159197
key: DocumentDetailsIsolateHostPanelKey,
@@ -162,12 +200,14 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
162200
<IsolateHostPanel path={props.path as IsolateHostPanelProps['path']} />
163201
</IsolateHostPanelProvider>
164202
),
203+
'aria-label': DOCUMENT_DETAILS_ISOLATE_HOST_PANEL_ARIA_LABEL,
165204
},
166205
{
167206
key: DocumentDetailsAnalyzerPanelKey,
168207
component: (props) => (
169208
<AnalyzerPanel {...(props as AnalyzerPanelExpandableFlyoutProps).params} />
170209
),
210+
'aria-label': DOCUMENT_DETAILS_ANALYZER_PANEL_ARIA_LABEL,
171211
},
172212
{
173213
key: DocumentDetailsSessionViewPanelKey,
@@ -176,71 +216,84 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
176216
<SessionViewPanel path={props.path as SessionViewPanelProps['path']} />
177217
</SessionViewPanelProvider>
178218
),
219+
'aria-label': DOCUMENT_DETAILS_SESSION_VIEW_PANEL_ARIA_LABEL,
179220
},
180221
{
181222
key: UserPanelKey,
182223
component: (props) => <UserPanel {...(props as UserPanelExpandableFlyoutProps).params} />,
224+
'aria-label': USER_PANEL_ARIA_LABEL,
183225
},
184226
{
185227
key: UserDetailsPanelKey,
186228
component: (props) => (
187229
<UserDetailsPanel {...(props as UserDetailsExpandableFlyoutProps).params} />
188230
),
231+
'aria-label': USER_DETAILS_PANEL_ARIA_LABEL,
189232
},
190233
{
191234
key: UserPreviewPanelKey,
192235
component: (props) => (
193236
<UserPanel {...(props as UserPanelExpandableFlyoutProps).params} isPreviewMode />
194237
),
238+
'aria-label': USER_PREVIEW_PANEL_ARIA_LABEL,
195239
},
196240
{
197241
key: HostPanelKey,
198242
component: (props) => <HostPanel {...(props as HostPanelExpandableFlyoutProps).params} />,
243+
'aria-label': HOST_PANEL_ARIA_LABEL,
199244
},
200245
{
201246
key: HostDetailsPanelKey,
202247
component: (props) => (
203248
<HostDetailsPanel {...(props as HostDetailsExpandableFlyoutProps).params} />
204249
),
250+
'aria-label': HOST_DETAILS_PANEL_ARIA_LABEL,
205251
},
206252
{
207253
key: HostPreviewPanelKey,
208254
component: (props) => (
209255
<HostPanel {...(props as HostPanelExpandableFlyoutProps).params} isPreviewMode />
210256
),
257+
'aria-label': HOST_PREVIEW_PANEL_ARIA_LABEL,
211258
},
212259
{
213260
key: NetworkPanelKey,
214261
component: (props) => <NetworkPanel {...(props as NetworkExpandableFlyoutProps).params} />,
262+
'aria-label': NETWORK_PANEL_ARIA_LABEL,
215263
},
216264
{
217265
key: NetworkPreviewPanelKey,
218266
component: (props) => (
219267
<NetworkPanel {...(props as NetworkExpandableFlyoutProps).params} isPreviewMode />
220268
),
269+
'aria-label': NETWORK_PREVIEW_PANEL_ARIA_LABEL,
221270
},
222271

223272
{
224273
key: ServicePanelKey,
225274
component: (props) => <ServicePanel {...(props as ServicePanelExpandableFlyoutProps).params} />,
275+
'aria-label': SERVICE_PANEL_ARIA_LABEL,
226276
},
227277
{
228278
key: ServiceDetailsPanelKey,
229279
component: (props) => (
230280
<ServiceDetailsPanel {...(props as ServiceDetailsExpandableFlyoutProps).params} />
231281
),
282+
'aria-label': SERVICE_DETAILS_PANEL_ARIA_LABEL,
232283
},
233284
{
234285
key: GenericEntityPanelKey,
235286
component: (props) => (
236287
<GenericEntityPanel {...(props as GenericEntityPanelExpandableFlyoutProps).params} />
237288
),
289+
'aria-label': GENERIC_ENTITY_PANEL_ARIA_LABEL,
238290
},
239291
{
240292
key: GenericEntityDetailsPanelKey,
241293
component: (props) => (
242294
<GenericEntityDetailsPanel {...(props as GenericEntityDetailsExpandableFlyoutProps).params} />
243295
),
296+
'aria-label': GENERIC_ENTITY_DETAILS_PANEL_ARIA_LABEL,
244297
},
245298
{
246299
key: MisconfigurationFindingsPanelKey,
@@ -249,6 +302,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
249302
{...(props as FindingsMisconfigurationPanelExpandableFlyoutPropsNonPreview).params}
250303
/>
251304
),
305+
'aria-label': MISCONFIGURATION_PANEL_ARIA_LABEL,
252306
},
253307
{
254308
key: EasePanelKey,
@@ -257,6 +311,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
257311
<EasePanel />
258312
</EaseDetailsProvider>
259313
),
314+
'aria-label': EASE_PANEL_ARIA_LABEL,
260315
},
261316
{
262317
key: AttackDetailsRightPanelKey,
@@ -265,6 +320,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
265320
<AttackDetailsPanel path={props.path as AttackDetailsProps['path']} />
266321
</AttackDetailsProvider>
267322
),
323+
'aria-label': ATTACK_DETAILS_RIGHT_PANEL_ARIA_LABEL,
268324
},
269325
{
270326
key: MisconfigurationFindingsPreviewPanelKey,
@@ -273,6 +329,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
273329
{...(props as FindingsMisconfigurationPanelExpandableFlyoutPropsPreview).params}
274330
/>
275331
),
332+
'aria-label': MISCONFIGURATION_FINDINGS_PREVIEW_PANEL_ARIA_LABEL,
276333
},
277334
{
278335
key: VulnerabilityFindingsPanelKey,
@@ -281,6 +338,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
281338
{...(props as FindingsVulnerabilityPanelExpandableFlyoutPropsNonPreview).params}
282339
/>
283340
),
341+
'aria-label': VULNERABILITY_FINDINGS_PANEL_ARIA_LABEL,
284342
},
285343
{
286344
key: VulnerabilityFindingsPreviewPanelKey,
@@ -289,6 +347,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
289347
{...(props as FindingsVulnerabilityPanelExpandableFlyoutPropsPreview).params}
290348
/>
291349
),
350+
'aria-label': VULNERABILITY_FINDINGS_PREVIEW_PANEL_ARIA_LABEL,
292351
},
293352
{
294353
key: IOCRightPanelKey,
@@ -297,6 +356,7 @@ const expandableFlyoutDocumentsPanels: ExpandableFlyoutProps['registeredPanels']
297356
<IOCPanel path={props.path as IOCDetailsProps['path']} />
298357
</IOCDetailsProvider>
299358
),
359+
'aria-label': IOC_RIGHT_PANEL_ARIA_LABEL,
300360
},
301361
];
302362

0 commit comments

Comments
 (0)