Skip to content

Commit 5730732

Browse files
johannes-weberJohannes Weber
andauthored
fix: Add LiveRegion to non-dismissible Popover (#3692)
Co-authored-by: Johannes Weber <[email protected]>
1 parent c91bb8f commit 5730732

File tree

3 files changed

+58
-13
lines changed

3 files changed

+58
-13
lines changed

src/popover/__tests__/popover.test.tsx

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -279,9 +279,12 @@ describe('ARIA labels', () => {
279279
});
280280

281281
it('uses aria-live if dismissButton is false', () => {
282-
const wrapper = renderPopover({ children: 'Trigger', content: 'Popover', dismissButton: false });
282+
const wrapper = renderPopover({ children: 'Trigger', content: 'Popover content', dismissButton: false });
283283
wrapper.findTrigger().click();
284-
expect(wrapper.find('[aria-live="polite"]')).toBeTruthy();
284+
285+
const liveRegion = createWrapper().findLiveRegion()!;
286+
expect(liveRegion).toBeDefined();
287+
expect(liveRegion.getElement()).toHaveTextContent('Popover content');
285288
});
286289

287290
it('does not pass the dismissAriaLabel to the dismiss button if not defined', () => {
@@ -308,15 +311,39 @@ describe('ARIA labels', () => {
308311
expect(wrapper.findBody()!.getElement()).not.toHaveAttribute('role', 'dialog');
309312
});
310313

311-
it('accessibility validation basic popover', async () => {
312-
const wrapper = renderPopover({
313-
children: 'Trigger',
314-
content: 'Popover',
315-
dismissButton: false,
316-
renderWithPortal: true,
314+
describe('live region', () => {
315+
it('do not render live region when closed', () => {
316+
renderPopover({
317+
children: 'Trigger',
318+
content: 'Popover',
319+
dismissButton: false,
320+
renderWithPortal: true,
321+
});
322+
expect(createWrapper().findLiveRegion()).toBeNull();
323+
});
324+
325+
it('render live region when opened and dismissButton = false', () => {
326+
const wrapper = renderPopover({
327+
children: 'Trigger',
328+
content: 'Popover',
329+
dismissButton: false,
330+
renderWithPortal: true,
331+
});
332+
wrapper.findTrigger().click();
333+
const liveRegion = createWrapper().findLiveRegion()!.getElement()!;
334+
expect(liveRegion).toHaveTextContent('Popover');
335+
});
336+
337+
it('do not render live region when opened and dismissButton = true', () => {
338+
const wrapper = renderPopover({
339+
children: 'Trigger',
340+
content: 'Popover',
341+
dismissButton: true,
342+
renderWithPortal: true,
343+
});
344+
wrapper.findTrigger().click();
345+
expect(createWrapper().findLiveRegion()).toBeNull();
317346
});
318-
wrapper.findTrigger().click();
319-
await expect(document.body).toValidateA11y();
320347
});
321348

322349
it('accessibility validation for popover with dismiss button and header', async () => {
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React, { ReactNode } from 'react';
4+
5+
import InternalLiveRegion from '../live-region/internal';
6+
7+
interface ConditionalLiveRegionProps {
8+
condition: boolean;
9+
children: ReactNode;
10+
}
11+
12+
const ConditionalLiveRegion = ({ condition, children }: ConditionalLiveRegionProps) => {
13+
if (condition) {
14+
return <InternalLiveRegion>{children}</InternalLiveRegion>;
15+
}
16+
return <>{children}</>;
17+
};
18+
19+
export default ConditionalLiveRegion;

src/popover/internal.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { usePortalModeClasses } from '../internal/hooks/use-portal-mode-classes'
1717
import { KeyCode } from '../internal/keycode';
1818
import Arrow from './arrow';
1919
import PopoverBody from './body';
20+
import ConditionalLiveRegion from './conditional-live-region';
2021
import PopoverContainer from './container';
2122
import { PopoverProps } from './interfaces';
2223

@@ -144,8 +145,6 @@ function InternalPopover(
144145

145146
const popoverContent = (
146147
<div
147-
aria-live={dismissButton ? undefined : 'polite'}
148-
aria-atomic={dismissButton ? undefined : true}
149148
className={clsx(popoverClasses, !renderWithPortal && styles['popover-inline-content'])}
150149
data-awsui-referrer-id={referrerId}
151150
>
@@ -167,7 +166,7 @@ function InternalPopover(
167166
overflowVisible="both"
168167
closeAnalyticsAction={__closeAnalyticsAction}
169168
>
170-
{content}
169+
<ConditionalLiveRegion condition={!dismissButton}>{content}</ConditionalLiveRegion>
171170
</PopoverBody>
172171
</LinkDefaultVariantContext.Provider>
173172
</PopoverContainer>

0 commit comments

Comments
 (0)