feat(a11y): add label for screen readers#1121
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1121 +/- ##
==========================================
+ Coverage 72.26% 72.90% +0.64%
==========================================
Files 387 405 +18
Lines 12021 12388 +367
Branches 2629 2680 +51
==========================================
+ Hits 8687 9032 +345
- Misses 3309 3322 +13
- Partials 25 34 +9
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
myasonik
left a comment
There was a problem hiding this comment.
Left a couple small code comments but otherwise looks good!
(Holding off approving until I have a chance to run through it in VoiceOver though.)
|
|
||
| const ariaProps = { | ||
| 'aria-labelledby': labelledBy || label ? labelledBy ?? chartIdLabel : '', | ||
| 'aria-describedby': `${labelledBy || ''} ${useDefaultSummary ? chartIdLabel : ''}`, |
There was a problem hiding this comment.
Did you mean to use chartIdDescription here?
| 'aria-describedby': `${labelledBy || ''} ${useDefaultSummary ? chartIdLabel : ''}`, | |
| 'aria-describedby': `${labelledBy || ''} ${useDefaultSummary ? chartIdDescription : ''}`, |
There was a problem hiding this comment.
And I'm also confused by the fact that we are reusing labelledByin the describedBy. Should we introduce a new props called describedBy?
Codecov Report
@@ Coverage Diff @@
## master #1121 +/- ##
==========================================
+ Coverage 72.26% 72.90% +0.64%
==========================================
Files 387 405 +18
Lines 12021 12388 +367
Branches 2629 2680 +51
==========================================
+ Hits 8687 9032 +345
- Misses 3309 3322 +13
- Partials 25 34 +9
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
| chartId: string; | ||
| label?: string; | ||
| labelledBy?: string; | ||
| HeadingLevel: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p'; |
There was a problem hiding this comment.
each prop name should follow the camelCase with the first char lowercase, independently if you use them later as component
There was a problem hiding this comment.
We should also sanitize this: it's true that in a TS this will throw error if the value is one of the union type, but in the JS compiled world not. This can lead to errors if this heading comes from an user input, or stored string value.
we can have a function that checks and returns/construct the appropriate header based on the input, like:
{label && <HeadingLevel id={chartIdLabel}>{label}</HeadingLevel>}
const ChartLabel = ({headingLevel: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p', id: string, label?: string}) => {
if(!label) return null;
switch(headingLevel){
case 'h1':
return <h1 id={id}>{label}</h1>
......
}
}
.....
<ChartLabel id={chartIdLabel} label={label} headingLevel={headingLevel} />
@nickofthyme other suggestions?
|
|
||
| const ariaProps = { | ||
| 'aria-labelledby': labelledBy || label ? labelledBy ?? chartIdLabel : '', | ||
| 'aria-describedby': `${labelledBy || ''} ${useDefaultSummary ? chartIdLabel : ''}`, |
There was a problem hiding this comment.
And I'm also confused by the fact that we are reusing labelledByin the describedBy. Should we introduce a new props called describedBy?
|
@markov00 @nickofthyme do you think it would be better in terms of Kibana dashboards etc. for the |
| if (ariaLabelledBy || useDefaultSummary) { | ||
| ariaProps['aria-describedby'] = `${ariaLabelledBy || ''} ${useDefaultSummary ? chartIdLabel : undefined}`; | ||
| } |
There was a problem hiding this comment.
@markov00 Good catch in #1121 (comment)
Adding a suggestion here so I could target more lines, I think the ariaLabelledBy stuff snuck in by mistake. It should probably be something like:
| if (ariaLabelledBy || useDefaultSummary) { | |
| ariaProps['aria-describedby'] = `${ariaLabelledBy || ''} ${useDefaultSummary ? chartIdLabel : undefined}`; | |
| } | |
| if (accessibilityDescription || useDefaultSummary) { | |
| ariaProps['aria-describedby'] = `${accessibilityDescription ? chartIdDescription : undefined} ${useDefaultSummary ? aNewIdForTheChartSeriesTypesDD : undefined}`; | |
| } |
(I'm suggesting making a new id just for the chartSeriesTypes <dd> because description text can't be structured data so we can't just set an id for the whole <dl> and use that. It's not perfect but it works well enough for a quick description imo.
@rshen91 Feel free to reach out if this suggestion doesn't make any sense! It's a little convoluted.
myasonik
left a comment
There was a problem hiding this comment.
One small tweak but otherwise looks good to me! Ship it!
This will be an awesome one to get integrated into Dashboards!
|
jenkins test this |
This commit extracts all the Settings props related to accessibility into an internal configuration, and reuse that configuration within the code without thinking about defaults" BREAKING CHANGE: `description` prop in `<Settings/>` is renamed to `ariaDescription`
markov00
left a comment
There was a problem hiding this comment.
LGTM!
Remember to add the BREAKING CHANGE: footer when merging
| <dl id={a11ySettings.defaultSummaryId}> | ||
| <dt>Chart type</dt> | ||
| <dd>{chartSeriesTypes}</dd> | ||
| </dl> |
There was a problem hiding this comment.
@markov00 Setting the summary id here would be ideal but aria-labelledby can't reliably report structured content so we're better off putting it on a simple string. Reporting just the chart type seems appropriate for a supplemental description (better than nothing, type of situation).
| <dl id={a11ySettings.defaultSummaryId}> | |
| <dt>Chart type</dt> | |
| <dd>{chartSeriesTypes}</dd> | |
| </dl> | |
| <dl> | |
| <dt>Chart type</dt> | |
| <dd id={a11ySettings.defaultSummaryId}>{chartSeriesTypes}</dd> | |
| </dl> |
| headingLevel: 'p', | ||
|
|
||
| ariaUseDefaultSummary: true, | ||
| ariaLabelHeadingLevel: 'h2', |
There was a problem hiding this comment.
thanks sorry about that, I was reading the API docs and was marked as h2
# [29.0.0](v28.2.0...v29.0.0) (2021-04-22) ### Features * **a11y:** add label for screen readers ([#1121](#1121)) ([920e585](920e585)), closes [#1096](#1096) * **annotations:** marker body with dynamic positioning ([#1116](#1116)) ([601abac](601abac)) ### BREAKING CHANGES * **a11y:** `description` prop in `<Settings/>` is renamed to `ariaDescription` Co-authored-by: Marco Vettorello <vettorello.marco@gmail.com>
|
🎉 This PR is included in version 29.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
# [29.0.0](elastic/elastic-charts@v28.2.0...v29.0.0) (2021-04-22) ### Features * **a11y:** add label for screen readers ([opensearch-project#1121](elastic/elastic-charts#1121)) ([ddb8782](elastic/elastic-charts@ddb8782)), closes [opensearch-project#1096](elastic/elastic-charts#1096) * **annotations:** marker body with dynamic positioning ([#1116](elastic/elastic-charts#1116)) ([997d487](elastic/elastic-charts@997d487)) ### BREAKING CHANGES * **a11y:** `description` prop in `<Settings/>` is renamed to `ariaDescription` Co-authored-by: Marco Vettorello <vettorello.marco@gmail.com>
Summary
Fixes #1096
This PR allows the consumer to set the heading level (or as a p tag), a label, and labelledBy aria-prop for a cartesian chart that can be read by a screen reader.
PR1121.mp4
Renamed the story within test_cases to
accessibility customizationswith a knob for this change.Checklist
Delete any items that are not applicable to this PR.
src/index.ts(and stories only import from../srcexcept for test data & storybook)