Make WordPress Core

Opened 4 months ago

Last modified 2 weeks ago

#47149 assigned defect (bug)

Tab structure does not use tab semantics

Reported by: anevins Owned by: afercia
Milestone: 5.3 Priority: normal
Severity: normal Version:
Component: Media Keywords: wpcampus-report has-screenshots semantic-buttons has-patch needs-refresh
Focuses: accessibility, javascript Cc:


Moved from the WPCampus accessibility report issues on GitHub, see: https://github.com/WordPress/gutenberg/issues/15287

  • Severity:
    • Medium
  • Affected Populations:
    • Blind
    • Low-Vision
    • Motor Impaired
    • Cognitively Impaired
  • Platform(s):
    • Windows - Screen Reader
    • Windows - ZoomText
    • Windows - Dragon
    • Mac - VoiceOver
    • Android - TalkBack
    • iOS - VoiceOver
  • Components affected:
    • Media Dialog

Issue description
In the "Featured Image" modal dialog, two links are used to switch
views (between the "Media Library" and the "Upload Files" panels).
These are coded as links with redundant href attributes ("#"),
which is not semantically valid, and does not convey the
currently-active link to assistive technologies.

The choice of button vs link has a significant effect on user
expectations for assistive technology users: links convey the
expectation that the browser will navigate to a different location or
page, which standard buttons do not. The difference also affects what
keys can be used within assistive technologies to navigate between the
elements, and which page summaries the element appears in (for example,
it won't show up in a list of all form elements on the page).

Semantic markup is vital for assistive technology users, to convey the
structure and relationships between information. When appropriate
semantic markup is not used, it may be more difficult for such users to
understand what the content means, and to comprehend the structure that
the visual presentation conveys.

Issue Code

    <div class="media-router">

        <a href="#" class="media-menu-item active">Upload Files</a>

        <a href="#" class="media-menu-item">Media Library</a>


Remediation Guidance
The visual presentation of the content within the "Featured Image"
dialog is a tab panel. Using the [tab panel pattern]
(https://www.w3.org/TR/wai-aria-practices-1.1/#tabpanel) will give the
elements proper roles, and using aria-selected will allow users of
assistive technologies to know which tab is currently selected.

Recommended Code

    <div role="tablist" class="media-router">

        <button role="tab" aria-selected="true" class="media-menu-item active">Upload Files</button>

        <button role="tab" class="media-menu-item">Media Library</button>


Relevant standards

Note: This issue may be a duplicate with other existing accessibility-related bugs in this project. This issue comes from the Gutenberg accessibility audit, performed by Tenon and funded by WP Campus. This issue is GUT-58 in Tenon's report

Attachments (7)

2fd289d77bd897652138d753f1420cd8.gif (757.9 KB) - added by audrasjb 4 months ago.
Workaround: add button role and aria-pressed attributes
media-views.min.js (243.0 KB) - added by audrasjb 4 months ago.
Workaround: search "JBA" comments to see the changes from the original file
media menu.png (85.1 KB) - added by afercia 4 months ago.
Media menu items in the desktop and responsive view.
47149.diff (10.6 KB) - added by afercia 3 months ago.
47149.2.diff (11.3 KB) - added by afercia 3 months ago.
47149.3.diff (13.0 KB) - added by afercia 2 months ago.
47149.4.diff (13.1 KB) - added by afercia 2 months ago.

Download all attachments as: .zip

Change History (34)

#1 @afercia
4 months ago

Comment from the GitHub issue: https://github.com/WordPress/gutenberg/issues/15287#issuecomment-488441147

Aside: I'm wary about using a tab interface when there are just 2 "tabs", as it tends to make keyboard interaction more complicated. Instead, it definitely helps when there are many tabs as it significantly reduces the amount of tab stops. With only 2 tabs, the missing information could be provided by other means.

#2 @afercia
4 months ago

  • Milestone changed from Awaiting Review to 5.3

4 months ago

Workaround: add button role and aria-pressed attributes

4 months ago

Workaround: search "JBA" comments to see the changes from the original file

#3 @audrasjb
4 months ago

  • Keywords has-screenshots added; needs-screenshots removed


I'd like to propose a first workaround, based on this ressource: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/button_role

I was not able to make a proper fix on this issue but I uploaded a testable JS fix above.

  • add role="button" attribute
  • add aria-pressed="true/false" attribute
  • toggle aria-pressed attribute when needed

Search for //JBA comments to see the changes I've done.
See also the animated GIF file to see the result.


#4 @audrasjb
4 months ago

  • Owner set to audrasjb
  • Status changed from new to accepted

#5 @afercia
4 months ago

  • Keywords semantic-buttons added

Worth noting this applies also to the menu items in the left sidebar of the media modal (the sidebar appears only in some of the media views). They're all <a href="#"> links, while they should be vertical tabs. However, in the responsive view the menu becomes a dropdown menu (see screenshot on the right), which makes things a bit more difficult to fix.

4 months ago

Media menu items in the desktop and responsive view.

#6 @afercia
4 months ago

Previously #32236, which didn't fix the menu items. See tracking ticket #26504.

This ticket was mentioned in Slack in #core-media by antpb. View the logs.

3 months ago

#8 @anevins
3 months ago

Steps we need to take:
1) Investigate all instances of this tabs antipattern;
2) Implement the tabs design pattern with keyboard interactions as per the W3C's recommendation. Helpful examples: https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-1/tabs.html
3) Test across all instances of the tabs.

Version 0, edited 3 months ago by anevins (next)

#9 @afercia
3 months ago

Note: actually, an ARIA tabbed interface could be built also upon links (<a> tags) if only they were valid URL-fragment links pointing to a valid page fragment, see for example https://inclusive-components.design/tabbed-interfaces/

However, these are just invalid links <a href="#"> thus they need to be changed to buttons, see https://core.trac.wordpress.org/query?keywords=~semantic-buttons

#10 @afercia
3 months ago

  • Owner changed from audrasjb to afercia
  • Status changed from accepted to assigned

I'm looking into this and working on a patch. In the media views, the Menu view generates both the menu on the left sidebar and the horizontal menu (called media-router, not sure why):


The left menu should be a vertical ARIA tabbed interface as well, so it makes sense to change both menus. Worth reminding it's not just a matter of adding some ARIA roles. ARIA tabs need to implement a specific keyboard interaction pattern, see details in the ARIA Authoring Practices.

I'm almost done with the interaction part. The main problem now is to add the required roles and attributes

Both the menus and the content update "on the fly" and this makes difficult to add IDs referencing the correct views. I'd tend to think this part would need a workaround.

These are the parts that are a bit tricky to implement:

  • Each element with role tab has the property aria-controls referring to its associated tabpanel element.
  • Each element that contains the content panel for a tab has role tabpanel.
  • Each element with role tabpanel has the property aria-labelledby referring to its associated tab element.

3 months ago

#11 @afercia
3 months ago

  • Keywords has-patch dev-feedback added; needs-patch removed

47149.diff is a proof of concept. It implements a first part of the ARIA tabbed interface, ie. the keyboard interaction part. As said in the previous comment, there's the need to add roles, attributes, and IDs required for this user interface pattern to work properly. This second part is a bit tricky and needs some exploration.

The basic idea is to extend wp.media.view.FocusManager to make it a tool able to handle special cases of focus management (e.g. arrow keys navigation) and ARIA widgets.

WordCamp Europe 2019 is in a few days, it would be a good opportunity to collaborate at implementing the missing parts :)

Note: in this proof of concept styling is only partially implemented: when testing, please ignore the visual part for now.

Last edited 3 months ago by afercia (previous) (diff)

#12 @afercia
3 months ago

Re: aria-controls, there's an important update. See this quick note by Steve Faulkner:

"If you encounter an element on a web page with a defined aria controls relationship, JAWS will no longer say "use JAWSKEY+ALT+M to move to controlled element" by default."

JAWS 2019 release notes: https://support.freedomscientific.com/Downloads/JAWS/JAWSWhatsNew

JAWS was the only known assistive tech to support aria-controls. Not to mention the actual usefulness of aria-controls was previously argued for good reasons.

#13 @afercia
3 months ago

See some initial design feedback on this related ticket comment: https://core.trac.wordpress.org/ticket/47145#comment:9
/Cc @kjellr @melchoyce

#14 @afercia
3 months ago

  • Keywords needs-design-feedback added

3 months ago

#15 @afercia
3 months ago

47149.2.diff refreshes the patch and improves styling. Still to do:

  • correct association of the tabs with the tab panels
  • make a decision on how the left menu should behave in the responsive view: currently, it switches to a dropdown but this doesn't fit so well with the ARIA tabs pattern

This ticket was mentioned in Slack in #core-media by afercia. View the logs.

2 months ago

2 months ago

#17 @afercia
2 months ago

  • Focuses javascript added
  • Keywords dev-feedback removed

47149.3.diff associates the tabpanel content with the active menu item in the left menu, so that the tabpanel is properly labelled. Also, cleans up things a bit. Still to do:

  • associate the tabpanel with the "router" tabs: "Upload Files" and "Media Library"
  • handle edge cases where the modal view hides the left menu, e.g.: the Image Editor
  • make a decision on how the left menu should behave in the responsive view: currently, it switches to a dropdown but this doesn't fit so well with the ARIA tabs pattern, see screenshot below


2 months ago

#18 @afercia
2 months ago

In 47149.4.diff

It appears NVDA needs an explicit aria-selected="false" instead of the absence of the attribute, otherwise it will announce all the tabs as "selected".

This ticket was mentioned in Slack in #core-media by karmatosed. View the logs.

6 weeks ago

This ticket was mentioned in Slack in #core-media by anevins. View the logs.

5 weeks ago

#21 @anevins
5 weeks ago

Hey @afercia , just checking you're okay owning this for 5.3? If not, no pressure, we can get this reassigned.

#22 @anevins
5 weeks ago

Would you also be waiting on design feedback too @afercia ?

#23 @afercia
3 weeks ago

  • Keywords needs-refresh added; needs-design-feedback removed

I'm progressing slowly on this one, as there are some technical details to solve. Can own it.

Design feedback will be addressed in #47610, if need be. Removing the keyword.

This ticket was mentioned in Slack in #accessibility by afercia. View the logs.

2 weeks ago

#25 @joedolson
2 weeks ago

Thanks for your work on this, Andrea!

I think that your proposed solution should work. Regarding the mobile view, I think that switching the dropdown into a disclosure widget will give the necessary affordance for the interface to make sense.

The fact that the H1 heading is being used to toggle that dropdown will definitely need to change - the control needs to be a clickable element, and the text should be a) constant and b) something that conveys what options are in that tab panel. I'm not honestly certain how to describe that, however - those choices are fairly diverse.

Something like "Media Tools"?

#26 @afercia
2 weeks ago

the control needs to be a clickable element,

Thanks @joedolson! I guess you meant keyboard operable? :)

#27 @joedolson
2 weeks ago

Eh. Yeah, that's what I meant. ;) Well, literally, I meant "an element that is natively clickable", but yeah - not stated clearly.

Last edited 2 weeks ago by joedolson (previous) (diff)
Note: See TracTickets for help on using tickets.