Skip to content

feat(a11y): add label for screen readers#1121

Merged
rshen91 merged 16 commits intoelastic:masterfrom
rshen91:add-labels
Apr 22, 2021
Merged

feat(a11y): add label for screen readers#1121
rshen91 merged 16 commits intoelastic:masterfrom
rshen91:add-labels

Conversation

@rshen91
Copy link
Copy Markdown
Contributor

@rshen91 rshen91 commented Apr 14, 2021

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 customizations with a knob for this change.

Checklist

Delete any items that are not applicable to this PR.

  • Any consumer-facing exports were added to src/index.ts (and stories only import from ../src except for test data & storybook)
  • Unit tests were updated or added to match the most common scenarios

@rshen91 rshen91 added :accessibility Accessibility related issue :xy Bar/Line/Area chart related labels Apr 14, 2021
@codecov-io
Copy link
Copy Markdown

codecov-io commented Apr 14, 2021

Codecov Report

Merging #1121 (e1c4fcd) into master (c1b59f2) will increase coverage by 0.64%.
The diff coverage is 97.36%.

Impacted file tree graph

@@            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     
Flag Coverage Δ
unittests 72.48% <97.36%> (+0.21%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/specs/constants.ts 100.00% <ø> (ø)
src/specs/settings.tsx 90.32% <ø> (ø)
.../chart_types/partition_chart/state/chart_state.tsx 70.68% <66.66%> (+0.51%) ⬆️
...partition_chart/state/selectors/get_debug_state.ts 100.00% <100.00%> (ø)
.../chart_types/xy_chart/renderer/canvas/xy_chart.tsx 95.69% <100.00%> (+0.19%) ⬆️
src/components/chart_status.tsx 91.66% <100.00%> (ø)
src/mocks/series/series.ts 91.22% <0.00%> (ø)
src/mocks/xy/domains.ts 89.47% <0.00%> (ø)
src/mocks/scale/index.ts 100.00% <0.00%> (ø)
src/mocks/store/store.ts 92.59% <0.00%> (ø)
... and 18 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 8017edd...e1c4fcd. Read the comment docs.

Copy link
Copy Markdown

@myasonik myasonik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking p good overall!

@rshen91 rshen91 requested a review from myasonik April 15, 2021 20:26
@rshen91 rshen91 marked this pull request as ready for review April 19, 2021 15:39
Copy link
Copy Markdown

@myasonik myasonik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 : ''}`,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to use chartIdDescription here?

Suggested change
'aria-describedby': `${labelledBy || ''} ${useDefaultSummary ? chartIdLabel : ''}`,
'aria-describedby': `${labelledBy || ''} ${useDefaultSummary ? chartIdDescription : ''}`,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'm also confused by the fact that we are reusing labelledByin the describedBy. Should we introduce a new props called describedBy?

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Apr 20, 2021

Codecov Report

Merging #1121 (e1c4fcd) into master (c1b59f2) will increase coverage by 0.64%.
The diff coverage is 97.36%.

❗ Current head e1c4fcd differs from pull request most recent head deff638. Consider uploading reports for the commit deff638 to get more accurate results
Impacted file tree graph

@@            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     
Flag Coverage Δ
unittests 72.48% <97.36%> (+0.21%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/specs/constants.ts 100.00% <ø> (ø)
src/specs/settings.tsx 90.32% <ø> (ø)
.../chart_types/partition_chart/state/chart_state.tsx 70.68% <66.66%> (+0.51%) ⬆️
...partition_chart/state/selectors/get_debug_state.ts 100.00% <100.00%> (ø)
.../chart_types/xy_chart/renderer/canvas/xy_chart.tsx 95.69% <100.00%> (+0.19%) ⬆️
src/components/chart_status.tsx 91.66% <100.00%> (ø)
src/mocks/index.ts 100.00% <0.00%> (ø)
src/mocks/utils.ts 100.00% <0.00%> (ø)
src/mocks/xy/domains.ts 89.47% <0.00%> (ø)
src/mocks/store/store.ts 92.59% <0.00%> (ø)
... and 18 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ab82bde...deff638. Read the comment docs.

chartId: string;
label?: string;
labelledBy?: string;
HeadingLevel: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

each prop name should follow the camelCase with the first char lowercase, independently if you use them later as component

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 : ''}`,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I'm also confused by the fact that we are reusing labelledByin the describedBy. Should we introduce a new props called describedBy?

@rshen91
Copy link
Copy Markdown
Contributor Author

rshen91 commented Apr 20, 2021

@markov00 @nickofthyme do you think it would be better in terms of Kibana dashboards etc. for the headingLevel to have the default being a <p> vs a <h2>? With an <h2> it's very easily navigable, but do you think it will be overwhelming for users? TY

Comment on lines +192 to +194
if (ariaLabelledBy || useDefaultSummary) {
ariaProps['aria-describedby'] = `${ariaLabelledBy || ''} ${useDefaultSummary ? chartIdLabel : undefined}`;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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:

Suggested change
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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Woops added this in 6150d2d thank you!

@rshen91 rshen91 requested review from markov00 and myasonik April 21, 2021 15:05
Copy link
Copy Markdown

@myasonik myasonik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small tweak but otherwise looks good to me! Ship it!

This will be an awesome one to get integrated into Dashboards!

@rshen91
Copy link
Copy Markdown
Contributor Author

rshen91 commented Apr 21, 2021

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`
Copy link
Copy Markdown
Collaborator

@markov00 markov00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
Remember to add the BREAKING CHANGE: footer when merging

@rshen91 rshen91 merged commit 920e585 into elastic:master Apr 22, 2021
Comment on lines +195 to +198
<dl id={a11ySettings.defaultSummaryId}>
<dt>Chart type</dt>
<dd>{chartSeriesTypes}</dd>
</dl>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@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).

Suggested change
<dl id={a11ySettings.defaultSummaryId}>
<dt>Chart type</dt>
<dd>{chartSeriesTypes}</dd>
</dl>
<dl>
<dt>Chart type</dt>
<dd id={a11ySettings.defaultSummaryId}>{chartSeriesTypes}</dd>
</dl>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

committing in #1118

headingLevel: 'p',

ariaUseDefaultSummary: true,
ariaLabelHeadingLevel: 'h2',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rshen91 @markov00

I thought we were going to use p to be less noisy on pages like Dashboards which can have tons of charts.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

committing in #1118 thank you!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks sorry about that, I was reading the API docs and was marked as h2

nickofthyme pushed a commit that referenced this pull request Apr 22, 2021
# [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>
@nickofthyme
Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 29.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@nickofthyme nickofthyme added the released Issue released publicly label Apr 22, 2021
@rshen91 rshen91 deleted the add-labels branch April 30, 2021 18:06
AMoo-Miki pushed a commit to AMoo-Miki/OpenSearch-Dashboards that referenced this pull request Feb 10, 2022
# [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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:accessibility Accessibility related issue released Issue released publicly :xy Bar/Line/Area chart related

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow pasing labelling props to <canvas> element

6 participants