diff --git a/content/patterns/listbox/examples/css/listbox-actions.css b/content/patterns/listbox/examples/css/listbox-actions.css
index b2e95bdfb..447fe59ec 100644
--- a/content/patterns/listbox/examples/css/listbox-actions.css
+++ b/content/patterns/listbox/examples/css/listbox-actions.css
@@ -1,81 +1,155 @@
+.hide-actions-button {
+ display: none !important;
+}
+
[role="option"] span.actions {
- display: none;
+ display: none;
}
[role="option"]:hover span.actions,
[role="listbox"]:focus [role="option"].focused span.actions {
- position: absolute;
- right: 0.5em;
- display: flex;
- justify-content: center;
- align-items: center;
- gap: 3px;
- top: -3px;
+ position: absolute;
+ right: 0.5em;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ gap: 3px;
+}
+
+.contentRow {
+ display: flex;
+ width: 100%;
+}
+
+.contentColumn {
+ flex: 1;
+ padding: 1rem;
+ background-color: #f0f0f0;
+}
+
+.listbox-area h3 {
+ font-weight: normal;
+ color: var(--text);
+ font-family: sans-serif;
+ font-size: 1em;
+ padding-bottom: 3px;
+}
+
+.listbox-area ul {
+ padding-top: 5px;
+}
+
+.detailPanel {
+ margin: 1em 0 0;
+ padding-top: 7px;
+ padding-left: 10px;
+ min-height: 18em;
+ border: 1px solid #aaa;
+ background: white;
+}
+
+.detailPanel.is-hidden {
+ display: none;
}
button.actionButton {
- display: inline-block;
- border-radius: 5px;
- text-align: center;
- color: #222428;
- font-size: 14px;
- line-height: 1.5em;
- margin-right: 0.25em;
- background-color: buttonface;
- padding-right: 5px;
- margin-top: -3px;
+ display: inline-block;
+ border-radius: 5px;
+ text-align: center;
+ color: #222428;
+ font-size: 14px;
+ line-height: 1.5em;
+ margin-right: 0.25em;
+ background-color: buttonface;
+ padding-right: 5px;
+ margin-top: -3px;
}
button.actionButton::before {
- display: flex;
- justify-content: center;
- align-items: center;
- height: 32px;
- width: 15px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ height: 32px;
+ width: 15px;
}
button.uparrow::before {
- content: "↑" / "";
+ content: "↑" / "";
}
button.downarrow::before {
- content: "↓" / "";
+ content: "↓" / "";
}
button.favorite[aria-pressed="true"]::before {
- content: "★" / "";
+ content: "★" / "";
}
button.favorite:not([aria-pressed])::before,
button.favorite[aria-pressed="false"]::before {
- content: "☆" / "";
+ content: "☆" / "";
}
button.delete::before {
- content: "🗑" / "";
+ content: "🗑️" / "";
+}
+
+[role="option"] {
+ position: relative;
+ display: block;
+ line-height: 1.8em;
+ cursor: pointer;
+ margin: 2px 2px 2px 8px;
+ padding: 2px 1em 2px 2.5em;
}
[role="option"] button:hover,
.focusedActionButton {
- background-color: rgb(226 239 225);
- color: black !important;
- white-space: pre;
- outline: #036 solid 3px !important;
- border-color: rgb(0 90 156);
+ background-color: rgb(226 239 225);
+ color: black !important;
+ white-space: pre;
+ outline: #036 solid 3px !important;
+ border-color: rgb(0 90 156);
}
-.listbox-area {
- display: block;
- padding: 20px;
- border-width: 1px;
- border-style: solid;
- border-color: rgb(170 170 170);
- border-image: initial;
- border-radius: 4px;
- background: rgb(238 238 238);
- max-width: 20em;
+[role="option"][aria-selected="true"] span.favoriteOptionIndication::before {
+ position: absolute;
+ left: 1.2em;
+ content: "";
}
-.hide-actions-button {
- display: none;
+[role="option"][aria-actions] span.favoriteOptionIndication::before {
+ position: absolute;
+ left: 1.4em;
+ content: "☆" / "Favorite";
+}
+
+[role="option"][aria-actions].js-favoriteIndication span.favoriteOptionIndication::before {
+ position: absolute;
+ left: 1.4em;
+ content: "★" / "Favorite";
}
+
+[role="option"][aria-actions] span.js-selection::before {
+ position: absolute;
+ left: 0.2em;
+ content: "☐" / "Favorite";
+}
+
+[role="option"][aria-selected="true"] span.js-selection::before {
+ position: absolute;
+ left: 0.2em;
+ content: "☑" / "Favorite";
+}
+
+.listbox-area {
+ display: block;
+ padding: 20px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: rgb(170 170 170);
+ border-image: initial;
+ border-radius: 4px;
+ background: rgb(238 238 238);
+ max-width: 20em;
+}
\ No newline at end of file
diff --git a/content/patterns/listbox/examples/js/listbox-actions.js b/content/patterns/listbox/examples/js/listbox-actions.js
index b028ab088..0b0617be0 100644
--- a/content/patterns/listbox/examples/js/listbox-actions.js
+++ b/content/patterns/listbox/examples/js/listbox-actions.js
@@ -55,16 +55,16 @@ aria.ListboxActions = class ListboxActions {
this.activeDescendant = this.listboxActionsNode.getAttribute(
'aria-activedescendant'
);
- this.registerActionsEvents();
this.listboxOptionArray = Array.from(
this.listboxActionsNode.querySelectorAll('[role="option"]')
);
- this.handleItemChange = function () {};
+ this.handleItemChange = function () { };
this.listboxItemCurrent = null;
this.listboxActiveOption = null;
this.listboxCurrentItemActionsButtons = [];
this.listboxCurrentOptionIndex = -1;
this.listboxItemsWithAriaActionsArray = [];
+ this.registerActionsEvents();
}
registerActionsEvents() {
@@ -77,7 +77,7 @@ aria.ListboxActions = class ListboxActions {
this.onSetCurrentActiveOptionForListbox.bind(this)
);
let actionButtons = this.listboxActionsNode.querySelectorAll(
- 'button:not(.hide-actions-button)'
+ 'button:not(.hide-actions-button),.js-favorite'
);
for (let i = 0; i < actionButtons.length; i++) {
actionButtons[i].addEventListener(
@@ -85,6 +85,15 @@ aria.ListboxActions = class ListboxActions {
this.onCheckClickItemActions.bind(this)
);
}
+ let selectionCheckbox = this.listboxActionsNode.querySelectorAll(
+ '.js-selection'
+ );
+ for (let i = 0; i < selectionCheckbox.length; i++) {
+ selectionCheckbox[i].addEventListener('click', (event) => {
+ event.currentTarget.closest('[role="option"]').click();
+ });
+ }
+
}
/**
* @description
@@ -134,92 +143,55 @@ aria.ListboxActions = class ListboxActions {
}
/**
* @description
- * Updates necessary attributes to ensure the up arrow does not appear if the option is the first.
- * Updates necessary attributes to ensure that the down arrow does not appear if the option is the last.
+ * Updates necessary attributes to ensure the up does not appear if an option is the first in the list.
+ * Updates necessary attributes to ensure the down does not appear if an option is the last in the list.
*/
- prepareToMoveUpItems() {
- if (!this.activeDescendant) {
- return;
- }
- const currentItem = this.listboxItemCurrent;
- const previousItem = currentItem.previousElementSibling;
+ updateArrowUpDownItems() {
this.listboxOptionArray = Array.from(
this.listboxActionsNode.querySelectorAll('[role="option"]')
);
- if (previousItem) {
- /** Hides the down arrow for item moved to the end of list and shows arrow on item moved up from bottom */
- if (
- this.listboxOptionArray.indexOf(previousItem) ==
- this.listboxOptionArray.length - 2
- ) {
- currentItem
- .querySelector('.downarrow')
- .classList.remove('hide-actions-button');
- currentItem
+ for (let i = 0; i < this.listboxOptionArray.length; i++) {
+ let option = this.listboxOptionArray[i];
+ if (this.listboxOptionArray.indexOf(option) == this.listboxOptionArray.length - 1) {
+ option
.querySelector('.downarrow')
.classList.remove('focusedActionButton');
- previousItem
+ option
.querySelector('.downarrow')
.classList.add('hide-actions-button');
- this.activeDescendant = currentItem.id;
- }
- /** Hides the up arrow for item moved to the top of list and shows arrow on item moved down from top */
- if (this.listboxOptionArray.indexOf(previousItem) == 1) {
- currentItem
- .querySelector('.uparrow')
- .classList.add('hide-actions-button');
- currentItem
+ } else if (this.listboxOptionArray.indexOf(option) == 0) {
+ option
.querySelector('.uparrow')
.classList.remove('focusedActionButton');
- previousItem
+ option
+ .querySelector('.uparrow')
+ .classList.add('hide-actions-button');
+ } else {
+ option
+ .querySelector('.downarrow')
+ .classList.remove('hide-actions-button');
+ option
.querySelector('.uparrow')
.classList.remove('hide-actions-button');
- this.setActiveDescendant(currentItem);
}
}
}
/**
* @description
- * Updates necessary attributes to ensure the down arrow does not appear if the option is the last option.
- * Updates necessary attributes to ensure that the up arrow does not appear if the options is first option.
+ * Key press listener
+ * Updates the details panel when listbox selection is made
+ * @param currentOption
*/
- prepareToMoveDownItems() {
- if (!this.activeDescendant) {
- return;
- }
- var currentItem = this.listboxItemCurrent;
- var nextItem = currentItem.nextElementSibling;
- this.listboxOptionArray = Array.from(
- this.listboxActionsNode.querySelectorAll('[role="option"]')
- );
- if (nextItem) {
- /** Hides the down arrow for item moved to the end of list and shows arrow on item moved up from bottom */
- if (
- this.listboxOptionArray.indexOf(nextItem) ==
- this.listboxOptionArray.length - 1
- ) {
- currentItem
- .querySelector('.downarrow')
- .classList.add('hide-actions-button');
- currentItem
- .querySelector('.downarrow')
- .classList.remove('focusedActionButton');
- nextItem
- .querySelector('.downarrow')
- .classList.remove('hide-actions-button');
- this.setActiveDescendant(currentItem);
- }
- /** Hides the up arrow for item moved to the top of list and shows arrow on item moved down from top */
- if (this.listboxOptionArray.indexOf(nextItem) == 2) {
- currentItem
- .querySelector('.uparrow')
- .classList.remove('hide-actions-button');
- currentItem
- .querySelector('.uparrow')
- .classList.remove('focusedActionButton');
- nextItem.querySelector('.uparrow').classList.add('hide-actions-button');
- this.activeDescendant = currentItem.id;
+ populateDetails(currentOption) {
+ if (currentOption.role == "option") {
+ let detailPanels = document.querySelectorAll('.js-detailPanel');
+ for (let i = 0; i < detailPanels.length; i++) {
+ if (!detailPanels[i].classList.contains('is-hidden')) {
+ detailPanels[i].classList.add('is-hidden');
+ }
}
+ let detailPanel = document.querySelector('#' + currentOption.id + '_detail_panel');
+ detailPanel.classList.toggle('is-hidden');
}
}
@@ -260,8 +232,15 @@ aria.ListboxActions = class ListboxActions {
}
this.setActiveDescendant(this.listboxItemsWithAriaActionsArray[0]);
this.Listbox.focusItem(this.listboxOptionArray[0]);
+ this.updateArrowUpDownItems();
break;
+ case 'js-favorite':
case 'favorite':
+ //If the favorite icon was clicked and is the activeButton instead of the action button,
+ //convert the activeButton to the action button and continue processing
+ if (activeButton.classList.contains('js-favorite')) {
+ activeButton = activeButton.closest('[role="option"]').querySelector('.favorite');
+ }
activeButton.setAttribute(
'aria-pressed',
activeButton.ariaPressed && activeButton.ariaPressed == 'true'
@@ -272,28 +251,34 @@ aria.ListboxActions = class ListboxActions {
activeButton.ariaPressed == 'true' ? 'favorite' : 'unfavorited',
[activeOption]
);
- if (activeOption.querySelector('.js-favoriteIndication')) {
- activeOption.querySelector('.js-favoriteIndication').innerText =
+ activeOption.classList.toggle('js-favoriteIndication');
+ if (activeOption.classList.contains('js-favoriteIndication')) {
+ activeOption.querySelector('.offscreen').innerText =
activeButton.ariaPressed == 'true' ? 'Favorite' : '';
}
break;
case 'uparrow':
- this.prepareToMoveUpItems();
this.Listbox.moveUpItems();
+ this.updateArrowUpDownItems();
break;
case 'downarrow':
- this.prepareToMoveDownItems();
this.Listbox.moveDownItems();
+ this.updateArrowUpDownItems();
break;
}
this.Listbox.updateScroll();
}
+ /**
+ * @description
+ * Handles the action buttons key press events
+ * @param event
+ * The key press event
+ */
onCheckKeyPressActions(event) {
let listitemCurrentItemActionsButtonPosition,
listboxCurrentItemActionsButton;
this.listboxItemCurrent = this.listboxActionsNode.querySelector('.focused');
this.listboxCurrentOptionIndex = this.listboxOptionArray.indexOf(this.listboxItemCurrent);
- console.log(this.listboxCurrentOptionIndex);
this.activeDescendant = this.listboxActionsNode.getAttribute(
'aria-activedescendant'
);
@@ -321,6 +306,7 @@ aria.ListboxActions = class ListboxActions {
this.listboxItemCurrent,
this.listboxCurrentItemActionsButtons.map((node) => node.id).join(' ')
);
+ this.populateDetails(this.listboxItemCurrent);
break;
case 'ArrowLeft':
case 'ArrowRight':
@@ -347,13 +333,13 @@ aria.ListboxActions = class ListboxActions {
if (listitemCurrentItemActionsButtonPosition > 0) {
this.focusActionsItem(
this.listboxCurrentItemActionsButtons[
- listitemCurrentItemActionsButtonPosition - 1
+ listitemCurrentItemActionsButtonPosition - 1
]
);
} else {
this.defocusActionsItem(
this.listboxCurrentItemActionsButtons[
- listitemCurrentItemActionsButtonPosition
+ listitemCurrentItemActionsButtonPosition
]
);
this.setActiveDescendant(this.listboxItemCurrent);
@@ -367,13 +353,13 @@ aria.ListboxActions = class ListboxActions {
) {
this.focusActionsItem(
this.listboxCurrentItemActionsButtons[
- listitemCurrentItemActionsButtonPosition + 1
+ listitemCurrentItemActionsButtonPosition + 1
]
);
} else {
this.focusActionsItem(
this.listboxCurrentItemActionsButtons[
- listitemCurrentItemActionsButtonPosition
+ listitemCurrentItemActionsButtonPosition
]
);
}
@@ -387,8 +373,6 @@ aria.ListboxActions = class ListboxActions {
: event.currentTarget
);
break;
- default:
- break;
}
}
/**
@@ -398,7 +382,7 @@ aria.ListboxActions = class ListboxActions {
* The click event
*/
onCheckClickItemActions(event) {
- event.preventDefault();
+ event.stopImmediatePropagation();
event.key = 'Enter';
let previousFocus = this.listboxActionsNode.querySelectorAll('.focused');
let prev;
@@ -426,6 +410,7 @@ aria.ListboxActions = class ListboxActions {
}
}
}
+ this.populateDetails(event.target);
}
};
window.addEventListener('load', function () {
diff --git a/content/patterns/listbox/examples/listbox-actions.html b/content/patterns/listbox/examples/listbox-actions.html
new file mode 100644
index 000000000..8635bf099
--- /dev/null
+++ b/content/patterns/listbox/examples/listbox-actions.html
@@ -0,0 +1,449 @@
+
+
+
+
+
+
+ Experimental Example of Scrollable Listbox with Actions on Options
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Experimental Example of Scrollable Listbox with Actions on Options
+
+
+
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:
+
+
Scrollable Listbox Example: Single-select listbox that scrolls to
+ reveal more options, similar to HTML select with size attribute greater than one.
+
+
Example Listboxes with Rearrangeable Options: Examples of both
+ single-select and multi-select listboxes with accompanying toolbars where options can be added, moved, and
+ removed.
+ 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.
+
+
+
+
+
+
+
+ Bucket List:
+
+
+
+
+ Complete an Iron Man
+
+
+
+
+
+
+
+
+
+
+ Climb Everest
+
+
+
+
+
+
+
+
+
+
+ Learn archery
+
+
+
+
+
+
+
+
+
+
+ Train a guide dog
+
+
+
+
+
+
+
+
+
+
+ Build an airplane
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Details:
+
+ Iron Man content goes here.
+
+
+ Climbing Mount Everest content goes here.
+
+
+ Archery content goes here.
+
+
+ Gide dog training content goes here.
+
+
+ Airplane Building content goes here.
+
+
+
+
+
+
+
+
+
+
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.
+
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.
+
To copy the following HTML code, please open it in CodePen.
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/content/patterns/listbox/examples/listbox-scrollable-actions.html b/content/patterns/listbox/examples/listbox-scrollable-actions.html
deleted file mode 100644
index cbb8b8bd8..000000000
--- a/content/patterns/listbox/examples/listbox-scrollable-actions.html
+++ /dev/null
@@ -1,561 +0,0 @@
-
-
-
-
-
- Experimental Example of Scrollable Listbox with Actions on Options
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Experimental Example of Scrollable Listbox with Actions on Options
-
-
-
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:
-
-
Scrollable Listbox Example: Single-select listbox that scrolls to reveal more options, similar to HTML select with size attribute greater than one.
-
Example Listboxes with Rearrangeable Options: Examples of both single-select and multi-select listboxes with accompanying toolbars where options can be added, moved, and removed.
Choose your favorite transuranic element (actinide or transactinide).
-
-
- Transuranium elements:
-
-
-
- None
-
-
-
- Neptunium
-
-
-
-
-
-
-
-
-
- Plutonium
-
-
-
-
-
-
-
-
-
- Americium
-
-
-
-
-
-
-
-
-
- Curium
-
-
-
-
-
-
-
-
-
- Berkelium
-
-
-
-
-
-
-
-
-
- Californium
-
-
-
-
-
-
-
-
-
- Einsteinium
-
-
-
-
-
-
-
-
-
- Fermium
-
-
-
-
-
-
-
-
-
- Mendelevium
-
-
-
-
-
-
-
-
-
- Nobelium
-
-
-
-
-
-
-
-
-
- Lawrencium
-
-
-
-
-
-
-
-
-
- Rutherfordium
-
-
-
-
-
-
-
-
-
- Dubnium
-
-
-
-
-
-
-
-
-
- Seaborgium
-
-
-
-
-
-
-
-
-
- Bohrium
-
-
-
-
-
-
-
-
-
- Hassium
-
-
-
-
-
-
-
-
-
- Meitnerium
-
-
-
-
-
-
-
-
-
- Darmstadtium
-
-
-
-
-
-
-
-
-
- Roentgenium
-
-
-
-
-
-
-
-
-
- Copernicium
-
-
-
-
-
-
-
-
-
- Nihonium
-
-
-
-
-
-
-
-
-
- Flerovium
-
-
-
-
-
-
-
-
-
- Moscovium
-
-
-
-
-
-
-
-
-
- Livermorium
-
-
-
-
-
-
-
-
-
- Tennessine
-
-
-
-
-
-
-
-
-
- Oganesson
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
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.
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.
-