Skip to content

Commit 0b29898

Browse files
committed
[refactor] clean up focus trap aria-describedby text
- aria-describedby text doesn't need to be visible at all, we can just use `hidden`, which removes it from the copy clipboard + condense down to a single element
1 parent f53c710 commit 0b29898

4 files changed

Lines changed: 45 additions & 69 deletions

File tree

packages/eui/src/components/datagrid/body/cell/focus_utils.test.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,8 @@ describe('FocusTrappedChildren', () => {
143143
data-focus-lock-disabled="disabled"
144144
>
145145
<p
146-
aria-hidden="true"
147-
class="emotion-euiScreenReaderOnly"
148-
id="euiDataGridCellHeader_generated-id_exited"
149-
/>
150-
<p
151-
aria-hidden="true"
152-
class="emotion-euiScreenReaderOnly"
153-
id="euiDataGridCellHeader_generated-id_keyboardHint"
146+
hidden=""
147+
id="generated-id_focusTrapHint"
154148
>
155149
Press the Enter key to interact with this cell's contents.
156150
</p>

packages/eui/src/components/datagrid/body/cell/focus_utils.tsx

Lines changed: 38 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,9 @@ import React, {
1616
import { FocusableElement, tabbable } from 'tabbable';
1717
import classNames from 'classnames';
1818

19-
import { keys } from '../../../../services';
20-
import { useGeneratedHtmlId } from '../../../../services/accessibility';
19+
import { keys, useGeneratedHtmlId } from '../../../../services';
2120
import { isDOMNode } from '../../../../utils';
2221
import { EuiFocusTrap } from '../../../focus_trap';
23-
import { EuiScreenReaderOnly } from '../../../accessibility';
2422
import { EuiI18n } from '../../../i18n';
2523

2624
/**
@@ -92,14 +90,8 @@ export const FocusTrappedChildren: FunctionComponent<
9290
const [isCellEntered, setIsCellEntered] = useState(false);
9391
const [isExited, setExited] = useState(false);
9492

95-
const keyboardHintAriaId = useGeneratedHtmlId({
96-
prefix: 'euiDataGridCellHeader',
97-
suffix: 'keyboardHint',
98-
});
99-
100-
const exitedHintAriaId = useGeneratedHtmlId({
101-
prefix: 'euiDataGridCellHeader',
102-
suffix: 'exited',
93+
const ariaDescribedById = useGeneratedHtmlId({
94+
suffix: 'focusTrapHint',
10395
});
10496

10597
// direct DOM manipulation as workaround to attach required hints
@@ -108,9 +100,17 @@ export const FocusTrappedChildren: FunctionComponent<
108100

109101
cellEl.setAttribute(
110102
'aria-describedby',
111-
classNames(currentAriaDescribedbyId, exitedHintAriaId, keyboardHintAriaId)
103+
classNames(currentAriaDescribedbyId, ariaDescribedById)
112104
);
113-
}, [cellEl, keyboardHintAriaId, exitedHintAriaId]);
105+
106+
return () => {
107+
if (currentAriaDescribedbyId) {
108+
cellEl.setAttribute('aria-descibedby', currentAriaDescribedbyId);
109+
} else {
110+
cellEl.removeAttribute('aria-describedby');
111+
}
112+
};
113+
}, [cellEl, ariaDescribedById]);
114114

115115
useEffect(() => {
116116
if (isCellEntered) {
@@ -173,37 +173,31 @@ export const FocusTrappedChildren: FunctionComponent<
173173
>
174174
{children}
175175

176-
<EuiScreenReaderOnly>
177-
{/**
178-
* Hints use aria-hidden to prevent them from being read as regular content.
179-
* They are still read in JAWS and NVDA via the linking with aria-describedby.
180-
* VoiceOver does generally not read the column on re-focus after exiting a cell,
181-
* which mean the exited hint is not read.
182-
* VoiceOver does react to aria-live (without aria-hidden) but that would causes
183-
* duplicate output in JAWS/NVDA (reading content & live announcement).
184-
* Optimizing for Windows screen readers as they have a larger usages.
185-
*/}
186-
<p id={exitedHintAriaId} aria-hidden="true">
187-
{isExited && (
188-
<EuiI18n
189-
// eslint-disable-next-line local/i18n
190-
token="euiDataGridCell.focusTrapExitPrompt"
191-
default="Exited cell content."
192-
/>
193-
)}
194-
</p>
195-
</EuiScreenReaderOnly>
196-
<EuiScreenReaderOnly>
197-
<p id={keyboardHintAriaId} aria-hidden="true">
198-
{!isCellEntered && (
199-
<EuiI18n
200-
// eslint-disable-next-line local/i18n
201-
token="euiDataGridCell.focusTrapEnterPrompt"
202-
default="Press the Enter key to interact with this cell's contents."
203-
/>
204-
)}
205-
</p>
206-
</EuiScreenReaderOnly>
176+
{/**
177+
* Hints use `hidden` to prevent them from being read by screen readers as regular content.
178+
* They are still read in JAWS and NVDA via the linking with aria-describedby.
179+
* VoiceOver does generally not read the column on re-focus after exiting a cell,
180+
* which mean the exited hint is not read.
181+
* VoiceOver does react to aria-live (without aria-hidden) but that would causes
182+
* duplicate output in JAWS/NVDA (reading content & live announcement).
183+
* Optimizing for Windows screen readers as they have a larger usages.
184+
*/}
185+
<p id={ariaDescribedById} hidden>
186+
{isExited && (
187+
<EuiI18n
188+
// eslint-disable-next-line local/i18n
189+
token="euiDataGridCell.focusTrapExitPrompt"
190+
default="Exited cell content."
191+
/>
192+
)}
193+
{!isCellEntered && (
194+
<EuiI18n
195+
// eslint-disable-next-line local/i18n
196+
token="euiDataGridCell.focusTrapEnterPrompt"
197+
default="Press the Enter key to interact with this cell's contents."
198+
/>
199+
)}
200+
</p>
207201
</EuiFocusTrap>
208202
);
209203
};

packages/eui/src/components/datagrid/body/header/data_grid_control_header_cell.test.tsx

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ describe('EuiDataGridControlHeaderCell', () => {
2626
const { container } = render(<EuiDataGridControlHeaderCell {...props} />);
2727
expect(container.firstChild).toMatchInlineSnapshot(`
2828
<div
29-
aria-describedby="euiDataGridCellHeader_generated-id_exited euiDataGridCellHeader_generated-id_keyboardHint"
29+
aria-describedby="generated-id_focusTrapHint"
3030
class="euiDataGridHeaderCell euiDataGridHeaderCell--controlColumn emotion-euiDataGridHeaderCell"
3131
data-gridcell-column-id="someControlColumn"
3232
data-gridcell-column-index="0"
@@ -50,14 +50,8 @@ describe('EuiDataGridControlHeaderCell', () => {
5050
tabindex="-1"
5151
/>
5252
<p
53-
aria-hidden="true"
54-
class="emotion-euiScreenReaderOnly"
55-
id="euiDataGridCellHeader_generated-id_exited"
56-
/>
57-
<p
58-
aria-hidden="true"
59-
class="emotion-euiScreenReaderOnly"
60-
id="euiDataGridCellHeader_generated-id_keyboardHint"
53+
hidden=""
54+
id="generated-id_focusTrapHint"
6155
>
6256
Press the Enter key to interact with this cell's contents.
6357
</p>

packages/eui/src/components/datagrid/body/header/data_grid_header_cell_wrapper.test.tsx

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,8 @@ describe('EuiDataGridHeaderCellWrapper', () => {
121121
Mock column actions
122122
</button>
123123
<p
124-
aria-hidden="true"
125-
class="emotion-euiScreenReaderOnly"
126-
id="euiDataGridCellHeader_generated-id_exited"
127-
/>
128-
<p
129-
aria-hidden="true"
130-
class="emotion-euiScreenReaderOnly"
131-
id="euiDataGridCellHeader_generated-id_keyboardHint"
124+
hidden=""
125+
id="generated-id_focusTrapHint"
132126
>
133127
Press the Enter key to interact with this cell's contents.
134128
</p>

0 commit comments

Comments
 (0)