-
Notifications
You must be signed in to change notification settings - Fork 39
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
ColorPicker a11y fixes #1470
ColorPicker a11y fixes #1470
Conversation
Will add changelog shortly. |
@@ -140,6 +140,8 @@ export const ColorPalette = React.forwardRef((props, ref) => { | |||
> | |||
{label && <Box className='iui-color-picker-section-label'>{label}</Box>} | |||
<Box | |||
role='listbox' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how did you decide on using role=listbox
and role=option
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It was the set of roles that was worked the best for the swatch array. Implementing a grid / gridcell system would have required too much refactoring. Meanwhile, giving the swatches the role of 'button' changes their appearance. 'Checkbox' didn't work for them either, because only one swatch is meant to be selected at a time.
'Listbox' / 'option' was the best structure I could find for a set of swatches. If there's another setup that you find works better, I can implement that instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense, but previously there was no role, so I'm asking why/how you decided to add one. Which specific a11y violation is this addressing? Would have been nice if you made the PR description more... descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's totally my bad. Lot of threads to keep track of!
The listbox
and option
roles were added to the ColorPalette
and the ColorSwatches
, respectively, because without those roles, it violated the 'aria-allowed-attribute' rule. This is because the Color Swatch component originally had the aria-selected
attribute, despite the component not being given a role.
Other roles that can take aria-selected
- Tab, Row, and Grid - either weren't appropriate for ColorPalette
& ColorSwatch
, or (in the case of Grid) would have required a more extensive refactoring of the code than I figured would be necessary. (More info here.)
@@ -287,6 +287,8 @@ export const ColorBuilder = React.forwardRef((props, ref) => { | |||
</Box> | |||
|
|||
<Slider | |||
aria-label='Hue slider' | |||
id='Slider' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ids should not be hardcoded like this. why do you need it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There wasn't a way to set the IDs for these nodes from example
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need to give an aria-label
to the Slider div? Instead, I believe you can pass an aria-label
to the thumbs directly (https://github.com/iTwin/iTwinUI/pull/1470/files#r1287238103). Then there is no need for an id.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
id
s are meant to be globally unique. Hardcoding a static id will result in every instance of this component getting the same clashing id.- this
id
is getting applied on the top-level container div, so i want to reiterate my question: why do you need it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll follow Rohan's suggestion.
return ( | ||
<ColorSwatch | ||
role='option' | ||
aria-label={swatchLabel} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a default aria-label
that the ColorSwatch
adds? Like swatchLabel
could be calculated inside ColorSwatch
. If the user provided an aria-label
to ColorSwatch
, we use it. But if not, we use swatchLabel
as the aria-label
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to implement this, although it might be a bit too involved of a refactor for the scope of this PR. I'll see what I can do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohh, actually colorString
(L42-48 of the screenshot) already calculates the string representation of the color. You could try reusing that instead of swatchLabel
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
colorString
return's the color's hex value, which wouldn't be very understandable. That's one of the main reasons I made swatchLabel
its own thing - it returns the color's value in HSL form, which (in my experience) is easier to learn to interpret than the hex form.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Switched from hsl to hex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please read the comment again, the suggestion is not to switch from hsl to hex, but to use colorString
which preserves the source value (can be hex or hsl or whatever string the color was instantiated with)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had tried using colorString
for the swatch label already, but I couldn't figure out how to use it in ColorPalette.tsx
. When I try using colorString
in ColorSwatches.tsx
, its original scope, ColorPickerBasicExample
throws an aria-allowed-attribute
error for the selected color swatch on top.
This is because that swatch doesn't have a role, since the roles are distributed in ColorPalette.tsx
. I could try giving that swatch its own role in the examples
file, but it's hard for me to tell what role is appropriate. I could also continue to assign the swatch labels the way I have been, even if it is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be fixable if you use visually-hidden text instead of aria-label
<Box
className={cx('iui-color-swatch', { 'iui-active': isActive }, className)}
// ...
{...rest}
>
<VisuallyHidden>{colorString.toUpperCase()}</VisuallyHidden>
</Box>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. It works!
Co-authored-by: Rohan Kadkol <[email protected]>
Co-authored-by: Rohan Kadkol <[email protected]>
…b.com/iTwin/iTwinUI into xander/color-picker-a11y-improvements
Changes
#1148 - Editing
ColorPicker
examples so that they meet a11y requirements.Testing
a11y testing will be conducted.
Docs
N/A