Skip to content
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

[Accessibility] Improve visualization legends accessibility #14505

Merged
merged 12 commits into from
Oct 26, 2017

Conversation

timroes
Copy link
Contributor

@timroes timroes commented Oct 23, 2017

Release Note: Improve the keyboard accessibility of visualization legends.


Improve the accessibility of the regular visualization legends:

This should make the legend accessible for now. We could definitely improve the accessibility especially in the color picker a lot, but I hope that we can replace the color picker at some point with the ui framework color picker, so I wouldn't spend now too much time into improving the existing color picker as it is basically working now.

@timroes timroes added Feature:Visualizations Generic visualization features (in case no more specific feature label is available) Project:Accessibility bug Fixes for quality problems that affect the customer experience review v6.1.0 v7.0.0 labels Oct 23, 2017
@timroes
Copy link
Contributor Author

timroes commented Oct 23, 2017

Jenkins, test this

Copy link
Contributor

@cjcenizal cjcenizal left a comment

Choose a reason for hiding this comment

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

It's so great to see our visualizations becoming more accessible! I had some suggestions and questions for your consideration.

@@ -3,10 +3,13 @@
type="button"
ng-click="toggleLegend()"
class="kuiCollapseButton legend-collapse-button"
aria-label="Toggle legend"
Copy link
Contributor

Choose a reason for hiding this comment

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

VoiceOver doesn't announce this label because of this aria-hidden logic introduced in #13573. I think that the warning is still useful, but perhaps we should just remove aria-hidden="true" from the legend?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, I will remove it, but therefor I would like to add an aria-label introducing the legend as such. That would also partly solve the issue you mentioned below, regarding missing context for the user with just legend values.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@@ -18,6 +21,10 @@

<div class="legend-value-container">
<div
kbn-accessible-click
data-label="{{legendData.label}}"
Copy link
Contributor

Choose a reason for hiding this comment

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

What does this attribute do?

Copy link
Contributor

Choose a reason for hiding this comment

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

Currently, the label doesn't indicate to the screen reader what will happen if the user clicks the button. Is there an elegant way to add an invisible label that says something like "Click for filtering options"? Maybe we can associate it with aria-describedby? Do you think this will be helpful?

Also, if the label is a value like "181", then the screen reader will just read this number aloud, which doesn't provide enough context for me to make sense of it. What if we added a noun to the end of this value? For example, if the aggregation was on "bytes", we could read aloud:

{{ `${legendData.label} + ${legendData.values.aggConfig.params.field.name}` }}

Which would cause the screen reader to announce "181 bytes". What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The attribute itself is required by the handlers in the visualization, that are doing the highlight and unhighlight to find the actual value. Not ideal imho, but that's the way it works atm.

I will add a description for what the label triggering does, that's a very good idea.

I think extending the label with the fieldname, won't always work as smooth as it did in your example :-) So I would rather add this to the description like: "Filtering bytes fields for this value"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added it to the label instead, so you really can't miss it. I didn't add aria-expanded since that would require we can reference the legend options via aria-controls. But they use ng-if and not ng-show at the moment, so they are really removed from DOM and we cannot reference them when hidden. I also don't want to use ng-show in that place, since imho the options contain a significant amount of DOM nodes and having a dashboard with multiple visualizations on it, which several legend items, would render a significantly higher amount of DOM nodes with ng-show.

So I decided to not use aria-expanded in that case.

kbn-accessible-click
data-label="{{legendData.label}}"
ng-focus="highlight($event)"
ng-blur="unhighlight($event)"
ng-click="showDetails = !showDetails"
Copy link
Contributor

Choose a reason for hiding this comment

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

Once the user opens these options, it's easy to get lost in the colorpicker. I know we don't want to spend time fixing this in this PR, but I think it would be helpful to let the user close the options by hitting ESC. This way if s/he gets lost in the color picker we've provided an easy way out. We just need to extract lines 22 through 75 into their own directive, and add a keypress handler there which sets showDetails to false. The challenge might be setting focus back on the button once the filtering options have been closed. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the color picker is not really accessible the way it is even after that PR. But I don't think just adding Escape would be enough. We still would need to think about color names, proper arrow navigation, etc... So I would rather replace this in the more or less near future, by using a standardized color picker from the UI framework instead and put the a11y effort into this. It would also come with the benefit, of being able to freely assign a color.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I hear you... I was just thinking of it as a temporary solution, since it's so easy to get stuck inside the color picker options and not know that the only way to get out of them is to backtrack all the way back to the button and then click it again.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

>
<span class="kuiIcon fa-search-minus"></span>
</button>
</div>

<div class="legend-value-color-picker">
<div class="legend-value-color-picker" role="listbox">
<span id="{{legendId}}ColorPickerDesc" class="kuiScreenReaderOnly">Set color for value {{legendData.label}}</span>
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we indent this?

<span
  id="{{legendId}}ColorPickerDesc"
  class="kuiScreenReaderOnly"
>
  Set color for value {{legendData.label}}
</span>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What if I would say "no"? Yes of course we can :-)

Copy link
Contributor

Choose a reason for hiding this comment

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

Then you better have a good reason! :D

const colors = $scope.uiState.get('vis.colors') || {};
if (colors[label] === color) delete colors[label];
else colors[label] = color;
$scope.uiState.setSilent('vis.colors', null);
$scope.uiState.set('vis.colors', colors);
$scope.uiState.emit('colorChanged');
if (event) {
event.currentTarget.blur();
Copy link
Contributor

Choose a reason for hiding this comment

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

Out of curiosity, why are we doing this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question. I was tinged with the slight idea, of not having the color button keeping the focus ring and it's then selected state. But honestly, we don't do this anywhere else, and again I want to replace this by the unified color picker in the future, so yeah I will throw it out for this PR.

Copy link
Member

@ppisljar ppisljar left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@thomasneirynck thomasneirynck left a comment

Choose a reason for hiding this comment

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

I like it.

This works a lot more intuitively than I thought it would. Nice too that you can jump to filter bar and continue editing filters there.

Copy link
Contributor

@cjcenizal cjcenizal left a comment

Choose a reason for hiding this comment

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

Fantastic! Thanks for adding the ESCAPE handler -- I really think it's a great escape hatch (sorry).

I had one small nitpicky comment but it's probably unnecessary so feel free to disregard it.

You mentioned this:

So I would rather add this to the description like: "Filtering bytes fields for this value"

But I didn't see this change -- not sure if this was intentional? If so, that's fine, it's a minor thing anyway, but just wanted to check.

* This will close the details panel of this legend entry when pressing Escape.
*/
$scope.onLegendEntryKeydown = function (event, scope) {
if (event.keyCode === keyCodes.ESCAPE) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I might be overthinking this but maybe we should check if showDetails is true first? Maybe someday in some bizarre future, something further up the DOM tree will care about the ESCAPE key being pressed and will be sad that it's being swallowed up here.

      $scope.onLegendEntryKeydown = function (event, scope) {
        if (event.keyCode === keyCodes.ESCAPE) {
          if (scope.showDetails) {
            event.preventDefault();
            event.stopPropagation();
            scope.showDetails = false;
          }
        }
      };

@timroes
Copy link
Contributor Author

timroes commented Oct 26, 2017

@cjcenizal actually it was intentional. Sorry for not commenting on that :/

That problem is, that the field is nested deep within the aggregation information and also there doesn't need to be a field (e.g. if you are doing a filters aggregation). Since we currently have no service (or I didn't found any) to extract the field information from the visualization legend data, but would have to implement that logic all over again, I decided it's not worth it at the moment.

timroes added a commit to timroes/kibana that referenced this pull request Oct 26, 2017
…14505)

* Make legend toggle button accessible, fix elastic#11843

* Make legend filter buttons accessible

* Highlight chart segments when focusing legend, fix elastic#11845

* Make legend color picker accessible

* Remove aria-hidden from legend

* Use proper indentation

* Remove bluring color button again

* Close legend details on pressing escape

* Add hint about the action

* Only capture escape press when details are opened
timroes added a commit that referenced this pull request Oct 26, 2017
…14606)

* Make legend toggle button accessible, fix #11843

* Make legend filter buttons accessible

* Highlight chart segments when focusing legend, fix #11845

* Make legend color picker accessible

* Remove aria-hidden from legend

* Use proper indentation

* Remove bluring color button again

* Close legend details on pressing escape

* Add hint about the action

* Only capture escape press when details are opened
@timroes timroes removed the review label Nov 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Fixes for quality problems that affect the customer experience Feature:Visualizations Generic visualization features (in case no more specific feature label is available) Project:Accessibility release_note:enhancement v6.1.0 v7.0.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants