Skip to content

Experimental Example of Scrollable Listbox with Actions on Options

Experimental Example of Scrollable Listbox with Actions on Options

Read This First

Experimental content! Do not use except for new standards development purposes. Please read below to understand why.

This is an experimental implementation of potential future techniques that may not yet be supported by web standards.

  • This example may include ARIA, HTML, CSS, or other code that is not yet included in a final web standard specification.
  • Experimental content is published in the APG only to facilitate discussion, gather feedback, and support testing of new features in browsers and assistive technologies.
  • There may be little or no support for this example in any or most browser and assistive technology combinations.
  • The ARIA and Assistive Technologies Project is developing measurements of assistive technology support for APG examples.

About This Experimental Example

This is an experimental implementation of the draft specification of the aria-actions attribute. The aria-actions property enables an element to reference one or more interactive elements that can be activated to perform an action on the referencing element. In this example, each option element in the listbox references several buttons that perform actions on the option. The relationship provided by aria-actions enables an assistive technology to both communicate the availability of the action button and provide a command for activating the button while focus is on the tab.

The following example implementation of the Listbox Pattern demonstrates a scrollable single-select listbox widget. This widget is functionally similar to an HTML select input where the size attribute has a value greater than one.

This example also demonstrates how to provide buttons that provide contextual actions for each item in the list. Each option has an associated set of four actions that enable users to move an option up or down, favorite it, or remove it from the list. The contextual actions are provided by buttons that appear on hover or focus. The buttons are referenced by aria-actions specified on the option element, which enables them to be discovered and activated by an assistive technology user while focus is on the option.

Similar examples include:

Example

Last change:

Plan your bucket list: Select an item to view or edit its details. Flag it for follow up if you need to do more research. You can also rank or delete items.

  • https://github.com/w3c/aria-practices/pull/3400
    • Readonly edit like color picker and file tree view so it can be accessible and screen reader users could tab to it
    • Don't have selection follow focus. Require space bar or enter key. Other listbox examples follow the implicit selection model so having it require an enter.
    • Make the star next to the checkbox the action and remove the button from the actions buttons
Bucket List:
  • Complete an Iron Man
  • Climb Everest
  • Learn archery
  • Train a guide dog
  • Build an airplane

Details:

Accessibility Features

  • Because this listbox implementation is scrollable and manages which option is focused by using aria-activedescendant, the JavaScript must ensure the focused option is visible. So, when a keyboard or pointer event changes the option referenced by aria-activedescendant, if the referenced option is not fully visible, the JavaScript scrolls the listbox to position the option in view.
  • To enhance perceivability when operating the listbox, visual keyboard focus and hover are styled using the CSS :hover and :focus pseudo-classes:
    • To help people with visual impairments identify the listbox as an interactive element, the cursor is changed to a pointer when hovering over the list.
    • To make it easier to distinguish the selected listbox option from other options, selection creates a 2 pixel border above and below the option.

Keyboard Support

The example listbox on this page implements the following keyboard interface. Other variations and options for the keyboard interface are described in the Keyboard Interaction section of the Listbox Pattern.

NOTE: When visual focus is on an option in this listbox implementation, DOM focus remains on the listbox element and the value of aria-activedescendant on the listbox refers to the descendant option that is visually indicated as focused. Where the following descriptions of keyboard commands mention focus, they are referring to the visual focus indicator, not DOM focus. For more information about this focus management technique, see Managing Focus in Composites Using aria-activedescendant.

Key Function
Tab Moves focus into and out of the listbox.
Down Arrow Moves focus to and selects the next option.
Up Arrow Moves focus to and selects the previous option.
Right Arrow
  • If an option has focus, moves focus to the first action button.
  • If an action button has focus, moves focus to the next action button for the current option.
  • If the last action button has focus, does nothing.
Left Arrow
  • If any action button except for the first action button has focus, moves focus to the previous action button for the current option.
  • If the first action button has focus, moves focus to the current option.
  • If an option has focus, does nothing.
Home Moves focus to and selects the first option.
End Moves focus to and selects the last option.
Printable Characters
  • Type a character: focus moves to the next item with a name that starts with the typed character.
  • Type multiple characters in rapid succession: focus moves to the next item with a name that starts with the string of characters typed.

Role, Property, State, and Tabindex Attributes

The example listbox on this page implements the following ARIA roles, states, and properties. Information about other ways of applying ARIA roles, states, and properties is available in the Roles, States, and Properties section of the Listbox Pattern.

Role Attribute Element Usage
listbox ul Identifies the focusable element that has listbox behaviors and contains the listbox options.
aria-labelledby="ID_REF" ul Refers to the element containing the listbox label.
tabindex="0" ul Includes the listbox in the page tab sequence.
aria-activedescendant="ID_REF" ul
  • When an option in the listbox is visually indicated as having keyboard focus, refers to that option.
  • Enables assistive technologies to know which element the application regards as focused while DOM focus remains on the listbox element.
  • When navigation keys, such as Down Arrow, are pressed, the JavaScript changes the value.
  • For more information about this focus management technique, see Managing Focus in Composites Using aria-activedescendant.
option li Identifies each selectable element containing the name of an option.
aria-selected="true" li
  • Indicates that the option is selected.
  • Applied to the element with role option that is visually styled as selected.
  • The option with this attribute is always the same as the option that is referenced by aria-activedescendant because it is a single-select listbox where selection follows focus.
aria-actions="" li
  • Indicates to assistive technologies that the option will have actions available on focus or hover, enabling the assistive technology to focus the element to gain access to the actions.
  • Applied to all elements with role option when they are not visually styled as selected and are not referenced by aria-activedescendant.
aria-actions="ID_REFS" li
  • Specifies the ID attributes of the action buttons that are associated with the option.
  • Applied to the element with role option that is visually styled as selected and is referenced by aria-activedescendant.
aria-hidden="true" span Removes the character entity used for the check mark icon from the accessibility tree to prevent it from being included in the accessible name of the option.

JavaScript and CSS Source Code

HTML Source Code

To copy the following HTML code, please open it in CodePen.


<p>
  Plan your bucket list: Select an item to view or edit its details. Flag it for follow up if you need to do
  more research. You can also rank or delete items.
</p>
<ul>
  <li>
    https://github.com/w3c/aria-practices/pull/3400
    <ul>
      <li>
        Readonly edit like color picker and file tree view so it can be accessible and screen reader users could tab to it
      </li>
      <li>
        Don't have selection follow focus.  Require space bar or enter key. Other listbox examples follow the implicit selection model so having it require an enter.
      </li>
      <li>
        Make the star next to the checkbox the action and remove the button from the actions buttons
      </li>
    </ul>
  </li>
</ul>
<div class="contentRow">
  <div class="contentColumn">
    <div class="listbox-area">
      <div>
        <span id="ss_elem" class="listbox-label">
          Bucket List:
        </span>
        <ul id="ss_elem_list"
            tabindex="0"
            role="listbox"
            aria-labelledby="ss_elem">
          <li id="ss_elem_IronMan"
              role="option"
              aria-controls="ss_elem_IronMan_detail_panel"
              aria-details="ss_elem_IronMan_detail_panel"
              aria-actions="">
            <span class="js-selection" aria-hidden="true"></span>
            <button aria-label="favorite"
                    tabindex="-1"
                    class="js-favorite favorite favoriteOptionIndication actionButton"
                    id="ss_elem_IronMan_favorite"></button>
            Complete an Iron Man
            <span class="offscreen favoriteIndication"></span>
            <span class="actions">
              <button aria-label="move up"
                      tabindex="-1"
                      class="uparrow actionButton hide-actions-button"
                      id="ss_elem_IronMan_uparrow"></button>
              <button aria-label="move down"
                      tabindex="-1"
                      class="downarrow actionButton"
                      id="ss_elem_IronMan_downarrow"></button>
              <button aria-label="delete"
                      tabindex="-1"
                      class="delete actionButton"
                      id="ss_elem_IronMan_delete"></button>
            </span>
          </li>
          <li id="ss_elem_Everest"
              role="option"
              aria-controls="ss_elem_Everest_detail_panel"
              aria-actions="">
            <span class="js-selection" aria-hidden="true"></span>
            <button aria-label="favorite"
                    tabindex="-1"
                    class="js-favorite favorite favoriteOptionIndication actionButton"
                    id="ss_elem_Everest_favorite"></button>
            Climb Everest
            <span class="offscreen favoriteIndication"></span>
            <span class="actions">
              <button aria-label="move up"
                      tabindex="-1"
                      class="uparrow actionButton"
                      id="ss_elem_Everest_uparrow"></button>
              <button aria-label="move down"
                      tabindex="-1"
                      class="downarrow actionButton"
                      id="ss_elem_Everest_downarrow"></button>
              <button aria-label="delete"
                      tabindex="-1"
                      class="delete actionButton"
                      id="ss_elem_Everest_delete"></button>
            </span>
          </li>
          <li id="ss_elem_Archery"
              role="option"
              aria-controls="ss_elem_Archery_detail_panel"
              aria-actions="">
            <span class="js-selection" aria-hidden="true"></span>
            <button aria-label="favorite"
                    tabindex="-1"
                    class="js-favorite favorite favoriteOptionIndication actionButton"
                    id="ss_elem_Archery_favorite"></button>
            Learn archery
            <span class="offscreen favoriteIndication"></span>
            <span class="actions">
              <button aria-label="move up"
                      tabindex="-1"
                      class="uparrow actionButton"
                      id="ss_elem_Archery_uparrow"></button>
              <button aria-label="move down"
                      tabindex="-1"
                      class="downarrow actionButton"
                      id="ss_elem_Archery_downarrow"></button>
              <button aria-label="delete"
                      tabindex="-1"
                      class="delete actionButton"
                      id="ss_elem_Archery_delete"></button>
            </span>
          </li>
          <li id="ss_elem_GuideDog"
              role="option"
              aria-controls="ss_elem_GuideDog_detail_panel"
              aria-actions="">
            <span class="js-selection" aria-hidden="true"></span>
            <button aria-label="favorite"
                    tabindex="-1"
                    class="js-favorite favorite favoriteOptionIndication actionButton"
                    id="ss_elem_GuideDog_favorite"></button>
            Train a guide dog
            <span class="offscreen favoriteIndication"></span>
            <span class="actions">
              <button aria-label="move up"
                      tabindex="-1"
                      class="uparrow actionButton"
                      id="ss_elem_GuideDog_uparrow"></button>
              <button aria-label="move down"
                      tabindex="-1"
                      class="downarrow actionButton"
                      id="ss_elem_GuideDog_downarrow"></button>
              <button aria-label="delete"
                      tabindex="-1"
                      class="delete actionButton"
                      id="ss_elem_GuideDog_delete"></button>
            </span>
          </li>
          <li id="ss_elem_Airplane"
              role="option"
              aria-controls="ss_elem_Airplane_detail_panel"
              aria-actions="">
            <span class="js-selection" aria-hidden="true"></span>
            <button aria-label="favorite"
                    tabindex="-1"
                    class="js-favorite favorite favoriteOptionIndication actionButton"
                    id="ss_elem_Airplane_favorite"></button>
            Build an airplane
            <span class="offscreen favoriteIndication"></span>
            <span class="actions">
              <button aria-label="move up"
                      tabindex="-1"
                      class="uparrow actionButton"
                      id="ss_elem_Airplane_uparrow"></button>
              <button aria-label="move down"
                      tabindex="-1"
                      class="downarrow actionButton hide-actions-button"
                      id="ss_elem_Airplane_downarrow"></button>
              <button aria-label="delete"
                      tabindex="-1"
                      class="delete actionButton"
                      id="ss_elem_Airplane_delete"></button>
            </span>
          </li>
        </ul>
      </div>
    </div>
  </div>
  <div class="contentColumn">
    <div class="listbox-area">
      <h3>
        Details:
      </h3>
      <div id="ss_elem_IronMan_detail_panel" class="js-detailPanel detailPanel is-hidden">
        Iron Man content goes here.
      </div>
      <div id="ss_elem_Everest_detail_panel" class="js-detailPanel detailPanel is-hidden">
        Climbing Mount Everest content goes here.
      </div>
      <div id="ss_elem_Archery_detail_panel" class="js-detailPanel detailPanel is-hidden">
        Archery content goes here.
      </div>
      <div id="ss_elem_GuideDog_detail_panel" class="js-detailPanel detailPanel is-hidden">
        Gide dog training content goes here.
      </div>
      <div id="ss_elem_Airplane_detail_panel" class="js-detailPanel detailPanel is-hidden">
        Airplane Building content goes here.
      </div>
    </div>
  </div>
</div>
Back to Top

This is an unpublished draft preview that might include content that is not yet approved. The published website is at w3.org/WAI/.