-
Notifications
You must be signed in to change notification settings - Fork 3.6k
Description
Title:
Toolbar items are tabbable individually instead of being navigable by arrow keys.
Description:
Currently, users can tab through each toolbar button (e.g., bold, italic, underline, etc.) using the Tab key. This behavior does not align with accessibility best practices for composite widgets such as toolbars. According to the WAI-ARIA Authoring Practices for Toolbars, users should press Tab once to enter the toolbar, and then use the arrow keys (← and →) to move between individual controls.
Expected Behavior:
Pressing Tab should move focus into the first element of the toolbar.
Once inside, Left Arrow and Right Arrow should move between toolbar items.
Pressing Tab again should move focus out of the toolbar to the next focusable element in the page.
Actual Behavior:
Each toolbar item is focusable with the Tab key.
Pressing Tab cycles through every single toolbar button individually.
Users cannot efficiently move in and out of the toolbar.
Impact:
Creates keyboard traps or excessive tab stops, which hinders efficient navigation.
Violates expected keyboard behavior for composite widgets.
Impacts users who rely solely on the keyboard, including users with mobility impairments or screen reader users.
WCAG References:
Severity:
🟠 Moderate – Significant usability impact for keyboard-only users.
Recommendation / Fix:
Wrap the toolbar buttons in a container with role="toolbar".
Remove individual tabindex attributes from buttons.
Implement arrow-key navigation to move focus between buttons:
toolbar.addEventListener('keydown', (e) => {
const buttons = Array.from(toolbar.querySelectorAll('button'));
const index = buttons.indexOf(document.activeElement);
if (e.key === 'ArrowRight') {
e.preventDefault();
buttons[(index + 1) % buttons.length].focus();
} else if (e.key === 'ArrowLeft') {
e.preventDefault();
buttons[(index - 1 + buttons.length) % buttons.length].focus();
}
});
Ensure pressing Tab once enters the toolbar and pressing it again exits.