Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion e2e/src/web/specs/photo-viewer.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ test.describe('Photo Viewer', () => {
await page.waitForLoadState('load');
// this is the spinner
await page.waitForSelector('svg[role=status]');
await expect(page.getByRole('status')).toBeVisible();
await expect(page.getByTestId('loading-spinner')).toBeVisible();
});

test('loads high resolution photo when zoomed', async ({ page }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
bind:this={menuElement}
class:max-h-[100vh]={isVisible}
class:max-h-0={!isVisible}
class="flex flex-col transition-all duration-[250ms] ease-in-out"
class="flex flex-col transition-all duration-[250ms] ease-in-out outline-none"
role="menu"
tabindex="-1"
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
viewBox="0 0 100 101"
fill="none"
xmlns="http://www.w3.org/2000/svg"
data-testid="loading-spinner"
>
<path
d="M100 50.5908C100 78.2051 77.6142 100.591 50 100.591C22.3858 100.591 0 78.2051 0 50.5908C0 22.9766 22.3858 0.59082 50 0.59082C77.6142 0.59082 100 22.9766 100 50.5908ZM9.08144 50.5908C9.08144 73.1895 27.4013 91.5094 50 91.5094C72.5987 91.5094 90.9186 73.1895 90.9186 50.5908C90.9186 27.9921 72.5987 9.67226 50 9.67226C27.4013 9.67226 9.08144 27.9921 9.08144 50.5908Z"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand All @@ -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({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
size="20"
padding="2"
on:click={discard}
aria-hidden="true"
tabindex={-1}
/>
</div>

Expand All @@ -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>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<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';

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>
Loading