Use ARIA disclosure pattern for Toolbar buttons with trays

Created on 25 October 2019, over 5 years ago
Updated 14 July 2025, about 13 hours ago

Problem/Motivation

  1. The relationship of toolbar buttons to their trays is not conveyed to assistive technology.

    The Toolbar previously attempted to convey this using aria-owns, but it was discovered that his usage was incorrect in this issue: #3066954: Admin toolbar not usable with latest versions of JAWS due to mis-use of aria-owns β†’ , and aria-owns was removed in order to address a bug impacting screenreader users. The correct ARIA relationship attributes need to be implemented.

  2. The toolbar buttons incorrectly use aria-pressed. The value of this attribute never changes (i.e. knows when it is pressed), and it is not the proper attribute to use. The correct dynamic ARIA state for a disclosure control is aria-expanded.
  3. A major benefit of using aria-pressed is that the open/close behaviour is conveyed by assistive tech before the user operates the button, using standardized terms from the operating system and/or assistive tech. Currently the open/close behaviour is only conveyed after pressing the button, using a custom Drupal.announce() message, in terms localized by Drupal. Using aria-expanded correctly means we no longer need Drupal.announce here.

Proposed resolution

  1. Remove the aria-pressed attribute from the toolbar buttons which control trays.
  2. Use an aria-controls ID reference for the button/tray relationship. This attribute should be on the element which has the button role, and should point to the tray wrapper which gets display:none.
  3. Use aria-expanded to convey current state of a given tray. This attribute should be on the same element which has the button role.
  4. Remove the Drupal.announce() message about the tray being opened. It's no longer necessary after adding the aria-expanded property to the button.

Scope: this issue is just about the behaviour of the buttons in the top-level toolbar, which control the visibility of the second-level trays. The behaviour of sub-menus under "mange" when the toolbar tray is in vertical alignment has a separate issue: πŸ“Œ Use ARIA disclosure pattern for submenu buttons in vertical toolbar orientation Needs work .

Remaining tasks

User interface changes

Improved semantics for assistive technology.
No changes to visual design or behaviour.

API changes

Data model changes

None.

Release notes snippet

πŸ“Œ Task
Status

Active

Version

11.0 πŸ”₯

Component

toolbar.module

Created by

πŸ‡ΊπŸ‡ΈUnited States bnjmnm Ann Arbor, MI

Live updates comments and jobs are added and updated live.
  • Accessibility

    It affects the ability of people with disabilities or special needs (such as blindness or color-blindness) to use Drupal.

  • JavaScript

    Affects the content, performance, or handling of Javascript.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States benjifisher Boston area

    Oddly, this issue does not show up when I search for "aria-expanded". Maybe that is because it appears inside a code tag.

    If so, then it should show up now in the search.

  • πŸ‡ΊπŸ‡ΈUnited States kentr Durango, CO

    When Javascript is disabled and those items behave as links, they still have role="button" and (currently) aria-pressed="false".

    In this case, they may be wrongly announced to AT as buttons instead of as links. Attached a screencast of this in VoiceOver.

    Based on a Slack discussion with @cwilcox808, I suggest:

    1. Rendering these items as plain links without any HTML button properties (aria-role, aria-expanded, aria-controls, etc).
    2. Adding those button properties in Javascript as part of the progressive-enhancement.
    3. Adding CSS based on aria-role="button" that will style these as buttons instead of links when the progressive-enhancement has happened (both for full-color and forced-colors cases).

    @cwilcox808 said this about the full-color styling and aria-controls:

    I think that's a good idea independent of the forced-colors state, something like:

    .toolbar a[role="button"] {
      text-decoration: none;
    }
    

    Instead of .toolbar .toolbar-item including text-decoration: none.

    That does open up the use of adding the underline on :hover and :focus. I really like strongly associating underlines with links (behaving as links) so I'd like to see something else used when they have [role="button"]. Without JS, the line thickness could be changed, e.g.

    .toolbar a[href]:not([role="button"]):is(:focus, :hover) {
      text-decoration-thickness: 0.1875em;
    }
    

    Note that only a single assistive technology, JAWS, makes use of aria-controls so it's not very useful. The better practice is to instead have the associated element immediately follow the control so users don't have to navigate through other content from the control.

    @cwilcox808 said this RE forced-colors styling for the "pressed" state of the buttons:

    For aria-pressed="true", you could maybe set border-color: Highlight;, buttons in that state wouldn't have a visual change on hover but focused buttons would still have the addition of the outline.

Production build 0.71.5 2024