From 21c00012b74dd44357cc98929f7d0ef9d5e28166 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 14 Mar 2022 20:30:55 +0000 Subject: [PATCH 1/4] test(toast): add test --- .../src/components/toast/test/a11y/index.html | 33 +++++++++++++ .../components/toast/test/a11y/toast.e2e.ts | 48 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 core/src/components/toast/test/a11y/index.html create mode 100644 core/src/components/toast/test/a11y/toast.e2e.ts diff --git a/core/src/components/toast/test/a11y/index.html b/core/src/components/toast/test/a11y/index.html new file mode 100644 index 00000000000..90903f742c8 --- /dev/null +++ b/core/src/components/toast/test/a11y/index.html @@ -0,0 +1,33 @@ + + + + + Toast - a11y + + + + + + + + + +
+

Toast - a11y

+ + + +
+
+ + + diff --git a/core/src/components/toast/test/a11y/toast.e2e.ts b/core/src/components/toast/test/a11y/toast.e2e.ts new file mode 100644 index 00000000000..ff1cf44d1d3 --- /dev/null +++ b/core/src/components/toast/test/a11y/toast.e2e.ts @@ -0,0 +1,48 @@ +import { newE2EPage } from '@stencil/core/testing'; +import { AxePuppeteer } from '@axe-core/puppeteer'; + +describe('toast accessibility tests', () => { + test('it should not have any axe violations with polite toasts', async () => { + const page = await newE2EPage({ + url: '/src/components/toast/test/a11y?ionic:_testing=true' + }); + + const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent'); + + await page.click('#polite'); + + await ionToastDidPresent.next(); + + /** + * IonToast overlays the entire screen, so + * Axe will be unable to verify color contrast + * on elements under the toast. + */ + const results = await new AxePuppeteer(page) + .disableRules('color-contrast') + .analyze(); + expect(results.violations.length).toEqual(0); + }); + + test('it should not have any axe violations with assertive toasts', async () => { + const page = await newE2EPage({ + url: '/src/components/toast/test/a11y?ionic:_testing=true' + }); + + const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent'); + + await page.click('#assertive'); + + await ionToastDidPresent.next(); + + /** + * IonToast overlays the entire screen, so + * Axe will be unable to verify color contrast + * on elements under the toast. + */ + const results = await new AxePuppeteer(page) + .disableRules('color-contrast') + .analyze(); + expect(results.violations.length).toEqual(0); + }); +}); From d79301b4b337ff837ad3c3f2e168f0f499a01312 Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 14 Mar 2022 20:31:05 +0000 Subject: [PATCH 2/4] fix(toast): screen readers now announce toasts when presented --- core/src/components/toast/toast.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/components/toast/toast.tsx b/core/src/components/toast/toast.tsx index 6d519a35f4f..1131d3770a1 100644 --- a/core/src/components/toast/toast.tsx +++ b/core/src/components/toast/toast.tsx @@ -280,6 +280,8 @@ export class Toast implements ComponentInterface, OverlayInterface { return ( Date: Mon, 14 Mar 2022 20:51:23 +0000 Subject: [PATCH 3/4] docs(toast): add docs --- core/src/components/toast/readme.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/core/src/components/toast/readme.md b/core/src/components/toast/readme.md index 45f36de3c75..e23b4471870 100644 --- a/core/src/components/toast/readme.md +++ b/core/src/components/toast/readme.md @@ -59,6 +59,30 @@ interface ToastOptions { interface ToastAttributes extends JSXBase.HTMLAttributes {} ``` +## Accessibility + +### Focus Management + +Toasts are intended to be subtle notifications and are not intended to interrupt the user. User interaction should not be required to dismiss the toast. As a result, focus is not automatically moved to a toast when one is presented. + +### Screen Readers + +`ion-toast` has `aria-live="polite"` and `aria-atomic="true"` set by default. + +`aria-live` causes screen readers to announce the content of the toast when it is presented. However, since the attribute is set to `'polite'`, screen readers generally do not interrupt the current task. Developers can customize this behavior by using the `htmlAttributes` property to set `aria-live` to `'assertive'`. This causes screen readers to immediately notify the user, potentially interrupting any previous updates. + +`aria-atomic="true"` is set to ensure that the entire toast is announced as a single unit. This is useful when dynamically updating the content of the toast as it causes screen readers to announce the entire toast, not just the content that has changed. + +### Tips + +While this is not a complete list, here are some guidelines to follow when using toasts. + +* Do not require user interaction to dismiss toasts. For example, having a "Dismiss" button in the toast is fine, but the toast should also automatically dismiss on its own after a timeout period. If you need user interaction for a notification, consider using [ion-alert](./alert) instead. + +* Avoid opening multiple toasts in quick succession. If `aria-live` is set to `'assertive'`, screen readers may interrupt the reading of the current task to announce the new toast, causing the context of the previous toast to be lost. + +* For toasts with long messages, consider adjusting the `duration` property to allow users enough time to read the content of the toast. + From 4de9f7c0618d4b00fb9f65fac72feb6a41ee1bed Mon Sep 17 00:00:00 2001 From: Liam DeBeasi Date: Mon, 14 Mar 2022 20:53:44 +0000 Subject: [PATCH 4/4] chore(): improve docs clarity --- core/src/components/toast/readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/components/toast/readme.md b/core/src/components/toast/readme.md index e23b4471870..ead2432bd73 100644 --- a/core/src/components/toast/readme.md +++ b/core/src/components/toast/readme.md @@ -69,9 +69,9 @@ Toasts are intended to be subtle notifications and are not intended to interrupt `ion-toast` has `aria-live="polite"` and `aria-atomic="true"` set by default. -`aria-live` causes screen readers to announce the content of the toast when it is presented. However, since the attribute is set to `'polite'`, screen readers generally do not interrupt the current task. Developers can customize this behavior by using the `htmlAttributes` property to set `aria-live` to `'assertive'`. This causes screen readers to immediately notify the user, potentially interrupting any previous updates. +`aria-live` causes screen readers to announce the content of the toast when it is presented. However, since the attribute is set to `'polite'`, screen readers generally do not interrupt the current task. Developers can customize this behavior by using the `htmlAttributes` property to set `aria-live` to `'assertive'`. This will cause screen readers to immediately notify the user when a toast is presented, potentially interrupting any previous updates. -`aria-atomic="true"` is set to ensure that the entire toast is announced as a single unit. This is useful when dynamically updating the content of the toast as it causes screen readers to announce the entire toast, not just the content that has changed. +`aria-atomic="true"` is set to ensure that the entire toast is announced as a single unit. This is useful when dynamically updating the content of the toast as it prevents screen readers from announcing only the content that has changed. ### Tips