feat(web): announce notifications to screen readers (#12071)

This commit is contained in:
Ben
2024-08-27 18:13:17 -04:00
committed by GitHub
parent 98b3441cb1
commit 72ab664936
7 changed files with 46 additions and 14 deletions

View File

@@ -39,6 +39,29 @@ describe('NotificationCard component', () => {
expect(sut.getByTestId('message')).toHaveTextContent('Notification message');
});
it('makes all buttons non-focusable and hidden from screen readers', () => {
sut = render(NotificationCard, {
notification: {
id: 1234,
message: 'Notification message',
timeout: 1000,
type: NotificationType.Info,
action: { type: 'discard' },
button: {
text: 'button',
onClick: vi.fn(),
},
},
});
const buttons = sut.container.querySelectorAll('button');
expect(buttons).toHaveLength(2);
for (const button of buttons) {
expect(button.getAttribute('tabindex')).toBe('-1');
expect(button.getAttribute('aria-hidden')).toBe('true');
}
});
it('shows title and renders component', () => {
sut = render(NotificationCard, {
notification: {

View File

@@ -9,8 +9,6 @@ function _getNotificationListElement(sut: RenderResult<NotificationList>): HTMLA
}
describe('NotificationList component', () => {
const sut: RenderResult<NotificationList> = render(NotificationList);
beforeAll(() => {
// https://testing-library.com/docs/svelte-testing-library/faq#why-arent-transition-events-running
vi.stubGlobal('requestAnimationFrame', (fn: FrameRequestCallback) => {
@@ -23,6 +21,10 @@ describe('NotificationList component', () => {
});
it('shows a notification when added and closes it automatically after the delay timeout', async () => {
const sut: RenderResult<NotificationList> = render(NotificationList);
const status = await sut.findAllByRole('status');
expect(status).toHaveLength(1);
expect(_getNotificationListElement(sut)).not.toBeInTheDocument();
notificationController.show({

View File

@@ -91,6 +91,8 @@
size="20"
padding="2"
on:click={discard}
aria-hidden="true"
tabindex={-1}
/>
</div>
@@ -108,6 +110,8 @@
type="button"
class="{buttonStyle[notification.type]} rounded px-3 pt-1.5 pb-1 transition-all duration-200"
on:click={handleButtonClick}
aria-hidden="true"
tabindex={-1}
>
{notification.button.text}
</button>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { notificationController } from './notification';
import { fade } from 'svelte/transition';
import { t } from 'svelte-i18n';
import NotificationCard from './notification-card.svelte';
import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing';
@@ -9,12 +9,14 @@
const { notificationList } = notificationController;
</script>
{#if $notificationList.length > 0}
<section transition:fade={{ duration: 250 }} id="notification-list" class="fixed right-5 top-[80px] z-[99999999]">
{#each $notificationList as notification (notification.id)}
<div animate:flip={{ duration: 250, easing: quintOut }}>
<NotificationCard {notification} />
</div>
{/each}
</section>
{/if}
<div role="status" aria-relevant="additions" aria-label={$t('notifications')}>
{#if $notificationList.length > 0}
<section transition:fade={{ duration: 250 }} id="notification-list" class="fixed right-5 top-[80px] z-[99999999]">
{#each $notificationList as notification (notification.id)}
<div animate:flip={{ duration: 250, easing: quintOut }}>
<NotificationCard {notification} />
</div>
{/each}
</section>
{/if}
</div>