Shopify / polaris

Shopify’s design system to help us work together to build a great experience for all of our merchants.
https://polaris.shopify.com
Other
5.79k stars 1.17k forks source link

[a11y] Issues with the Modal component #795

Closed dpersing closed 4 years ago

dpersing commented 6 years ago

Issue summary

The Modal component examples have a few accessibility issues that may impact users who rely on Windows High Contrast and/or screen readers, as well as keyboard users:

Focus

Semantic structure

The focus issue may also relate to a weird deal with NVDA/Firefox, where the virtual buffer is still able to read the modal content even after it's removed from the DOM. (I tested with NVDA/Chrome as well, just to see what it would do, and it reads as expected.) Examples I've tested where focus goes directly to an onscreen element don't have this issue, since that updates the buffer.

High Contrast support

Basic modal example

Modal viewed in High Contrast in Windows 10

Current code

X button (HTML)

<button class="Polaris-Modal-Header__CloseButton">
  <span class="Polaris-Icon Polaris-Icon--colorInkLighter Polaris-Icon--isColored">
    <svg class="Polaris-Icon__Svg" viewBox="0 0 20 20" focusable="false" aria-hidden="true">
    <!-- ... --></svg>
  </span>
</button>

Modal container styles (CSS)

.Polaris-Modal-Dialog__Modal {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: -ms-flexbox;
  display: flex;
  -ms-flex-direction: column;
  flex-direction: column;
  width: 100vw;
  height: 100%;
  max-height: calc(100vh - 60px);
  background: #fff;
  box-shadow: 0 31px 41px 0 rgba(32,42,53,.2), 0 2px 16px 0 rgba(32,42,54,.08);
}

Input example (HTML)

<input id="TextField4" class="Polaris-TextField__Input" aria-labelledby="TextField4Label" aria-invalid="false" value="https://polaris.shopify.com/">

Steps to reproduce

Button and label text

  1. Navigate to the Modal component examples.
  2. Using VoiceOver or NVDA, open each modal and read through the modal content to hear how it is identified.
  3. Use the tab key to move through controls in the modals to hear how they are read.

High Contrast

  1. Navigate to the Modal component examples.
  2. Open the default modal, and do a visual inspection.
  3. Turn on any High Contrast theme in Windows settings and redo the visual inspection.

Keyboard

  1. Navigate to the Modal component examples.
  2. tab to the Open button and press return/enter or space to activate it.
  3. To close the modal, tab to the X button and activate it.
  4. Repeat, closing the modal instead with the esc key.

Behavior (tl;dr)

Expected

Actual

Recommendations

See the ARIA authoring practices modal example.

There are a number of enhancements currently available in the 1.1 spec for modals, but support is either not present or buggy at present. We can keep an eye on that progress and add those in time.

X button recommendation example (HTML)

<button class="Polaris-Modal-Header__CloseButton" aria-label="Close modal">
  <span class="Polaris-Icon Polaris-Icon--colorInkLighter Polaris-Icon--isColored">
    <svg class="Polaris-Icon__Svg" viewBox="0 0 20 20" focusable="false" aria-hidden="true">
    <!-- ... --></svg>
  </span>
</button>

Modal border recommendation example (CSS)

.Polaris-Modal-Dialog__Modal {
  ...
  border: 1px solid transparent;
}

Input label recommendation example (HTML)

<label for="TextField4"><span class="Polaris-VisuallyHidden">Shareable link</span></label>
<input id="TextField4" class="Polaris-TextField__Input" aria-invalid="false" value="https://polaris.shopify.com/">

Specifications

dpersing commented 6 years ago

Retested as part of support for merchandising.

dpersing commented 5 years ago

We can keep an eye on inert support in regard to modals as well.

dpersing commented 5 years ago

The button that closes the modal has no text equivalent for the icon. Screen reader users will not be able to tell what the button does.

This item will be addressed by PR #1582.

chloerice commented 5 years ago

Focus

The modal does not receive focus automatically in Chrome. Chrome users must tab once to access the modal content.

It's possible to tab out of the modal before it is closed.

When the modal is closed with the keyboard, either by activating the X button or via the esc key, where focus moves is not immediately apparent to the user. Pressing tab after the modal closes causes focus to appear on the control that launched the button, but users will generally expect focus to return to the control that launched the interaction when it closes. (This looks like it should be working in code?)

When the first audit was done, our overlay components like Modal and Popover rendered only their activators and required interaction to be visible. Are the problems outlined around focus in the Modal examples still a concern now that our overlays default to being open or active @dpersing ?

dpersing commented 5 years ago

Are the problems outlined around focus in the Modal examples still a concern now that our overlays default to being open or active

@chloerice I believe so. I think folks should be able to close the examples and reopen them to see the expected behavior.

dpersing commented 4 years ago

Some accidental testing within the Vault and admin shows that if the Modal component appears in a page using the Nav component, focus goes to the "Skip to content" link as part of the modal focus order, which is unexpected. My initial thought that @LauraAubin's work to keep focus from going to the browser chrome should help this. 🤔

LauraAubin commented 4 years ago

Closing this since the last task was completed with https://github.com/Shopify/polaris-react/pull/2555