vuestorefront / storefront-ui

A frontend library for Vue and React that helps developers quickly build fast, accessible, and beautiful storefronts. Made with 💚 by Vue Storefront team and contributors.
https://storefrontui.io
MIT License
2.33k stars 455 forks source link

[BUG] A11y | Checkbox is not accessible #586

Closed pixelass closed 4 years ago

pixelass commented 4 years ago

Describe the bug The custom checkboxes are not accessible.
They can't be focused and don't allow interaction via keyboard input.
There is no focus style.

How to reproduce Steps to reproduce the behavior:

  1. Go to https://storybook.storefrontui.io/?path=/story/atoms-checkbox--multiple-checkboxes
  2. Click on any checkbox
  3. Try to use the keyboard to check/uncheck the checkbox
  4. The checkbox can not be changed or focused via keyboard

Expected behavior I should be able to interact with the checkbox via keyboard commands

Actual behavior The checkbox can not be changed or focused via keyboard

Caused by

The following style causes the accessibility issue.

.sf-checkbox__input {
    display: none;
}

display: none or visibility: hidden prevents access to these elements. They can also not be read by screen readers.

Potential solution (without focus styles)

Without wrapper:

use position: fixed to prevent jumping during focus/interaction.

.sf-checkbox__input {
    position: fixed;
    left: -100vw;
    top: 50%;
}

With wrapper:

use position: absolute to hook to current page-context (flow).

sf-checkbox {
    position: relative;
}

.sf-checkbox__input {
    position: absolute;
    left: -100vw;
    top: 0;
}

Both of the solutions above fix the issue without visually changes. There are several other solutions but these are very lightweight and deliver the expected behavior with minimal changes.

The missing focus styles are not added in these examples but are mandatory for full a11y support.

Keyboard interaction with changes applied (using wrapper + position: absolute

vue-storefront-ui

pspaczek commented 4 years ago

@pixelass I found something like that to fix this issue

&__input {
    position: absolute;
    border: 0;
    margin: -1px;
    padding: 0;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0px, 0px, 0px, 0px);
  }

https://github.com/DivanteLtd/storefront-ui/pull/419/commits/3b83c0cc2f8e071b5b69266f081464df9f5e5f43

pixelass commented 4 years ago

@pspaczek sure that should work too (while most of the styles are unnecessary and clip is deprecated).

Here's an example of several ways to implement it: (5 is yours)

https://codepen.io/000999/pen/0f17e799a3d475666cf6875f1c6dac88

._1 > .input {
  position: absolute;
  appearance: none;
}

._2 > .input {
  position: absolute;
  opacity: 0;
}

._3 > .input {
  position: absolute;
  left: -100vw;
}

._4 > .input {
  position: fixed;
  left: -100vw;
}

._5 > .input {
    position: absolute;
    border: 0;
    margin: -1px;
    padding: 0;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0px, 0px, 0px, 0px);
  }
pspaczek commented 4 years ago

thanks, @pixelass

aniamusial commented 4 years ago

Done in https://github.com/DivanteLtd/storefront-ui/pull/419