diff --git a/source b/source index 2c5ffa547d9..af0338245fc 100644 --- a/source +++ b/source @@ -4373,7 +4373,18 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
button
listbox
menu
menubar
menuitem
menuitemcheckbox
option
presentation
radio
radiogroup
tab
tablist
toolbar
In addition, the following aria-*
content
@@ -12625,6 +12636,7 @@ interface HTMLUnknownElement : HTMLElement {
[CEReactions, Reflect] attribute boolean autofocus;
[CEReactions, ReflectSetter] attribute long tabIndex;
+ [CEReactions, Reflect] attribute DOMString focusgroup;
undefined focus(optional FocusOptions options = {});
undefined blur();
};
@@ -13896,6 +13908,7 @@ https://software.hixie.ch/utilities/js/live-dom-viewer/?%3C%21DOCTYPE%20HTML%3E%
dir
draggable
enterkeyhint
focusgroup
headingoffset
headingreset
hidden
<div contenteditable autofocus>Edit <strong>me!</strong><div>
+ focusgroup
attributeThe focusgroup
+ content attribute provides declarative focus navigation for a group of related focusable
+ elements. When applied to an element, it enables Directional Navigation among its
+ focusable descendants, forming a focus group. Directional Navigation is navigation by spatial direction (such as up, down, left, or right), as determined by the user agent and input device (for example, arrow keys, gamepad, remote control, etc.). In contrast, Sequential focus navigation refers to navigation in the order defined by the sequential focus navigation order (see definition), often via Tab and Shift+Tab.
The attribute's value is a string of space-separated tokens. The first token must either be a
+ behavior token, which defines the primary interaction pattern, or the special token
+ none
which is used alone to opt out of focusgroup behavior. If a behavior token is
+ specified, modifier tokens can be provided subsequently.
Behavior tokens define the interaction pattern, which refers to how the directional navigation inputs are used to move focus between focusgroup items.
+ +The following interaction patterns are defined:
+ +Linear: Enables sequential navigation forwards and backwards through a set of focusable items. In a linear interaction pattern, even when both directional input axes are allowed (such as when neither inline
nor block
modifiers are specified), navigation follows the document order of the items rather than spatial positioning.
Token + | Type + | Interaction + | Description + |
---|---|---|---|
toolbar
+ | Behavior + | Linear + | Indicates a toolbar pattern. Infers a toolbar role.
+ |
tablist
+ | Behavior + | Linear + | Indicates a tablist pattern. Infers a tablist role for the owner and a tab role for items.
+ |
radiogroup
+ | Behavior + | Linear + | Indicates a radiogroup pattern. Infers a radiogroup role for the owner and a radio role for items.
+ |
listbox
+ | Behavior + | Linear + | Indicates a listbox pattern. Infers a listbox role for the owner and an option role for items.
+ |
menu
+ | Behavior + | Linear + | Indicates a menu pattern. Infers a menu role for the owner and a menuitem role for items.
+ |
menubar
+ | Behavior + | Linear + | Indicates a menubar pattern. Infers a menubar role for the owner and a menuitem role for items.
+ |
wrap
+ | Modifier + | + | Enables navigation to wrap from the last item to the first, and vice-versa. + |
inline
+ | Modifier + | + | Restricts arrow key navigation to the inline axis (e.g., left/right arrows). + |
block
+ | Modifier + | + | Restricts arrow key navigation to the block axis (e.g., up/down arrows). + |
no-memory
+ | Modifier + | + | Disables the "last focused item" memory when re-entering the focus group. + |
none
+ | Special + | + | Opts the element and its descendants out of any ancestor focus group. Must be used alone. + |
A focusgroup owner is an element with a valid focusgroup
attribute specified, where the attribute value contains a behavior token (not none
).
The focusgroup scope of a focusgroup owner is all of its shadow-including descendants, excluding any descendants that are a focusgroup owner themselves or are are in a different focusgroup scope or have opted out with focusgroup="none"
.
A focusgroup item is any focusable element within the focusgroup scope.
+When a behavior token is used, the user agent may infer a corresponding ARIA role for the focusgroup owner and its items. This inference must only occur if the element would otherwise have a generic role (such as a div
or span
) and does not have an explicit role
attribute.
For example, <div focusgroup="toolbar">
would be exposed with a toolbar
role. However, if the element has existing semantics (e.g., <nav focusgroup="toolbar">
) or an explicit role (e.g., <div focusgroup="toolbar" role="navigation">
), the existing role is preserved and only the focus navigation behavior is applied.
Role inference never overrides explicit author-defined roles or meaningful native-element semantics. It also does not infer variant roles like menuitemcheckbox
; such roles can be specified explicitly by the author.
When a user requests Directional Navigation and focus is within a focusgroup scope, the user agent must run these steps:
+ +Let currentItem be the currently focused focusgroup item.
Let items be all focusgroup items in tree order.
Determine the nextItem by finding the nearest item in tree order in the direction.
If no nextItem is found and the wrap
token is present, wrap to the first item in the specified direction. Otherwise, do nothing.
If a nextItem is identified, run the focusing steps for it.
A focus group must have at least one guaranteed tab stop. When elements opt-out of a focusgroup using focusgroup="none"
, they divide the focusgroup for sequential focus navigation purposes, creating one tab stop per focusgroup segment.
When a user requests sequential focus navigation into a focus group, the user agent must run these steps:
+ +Let direction be "forward" or "backward" as determined by the user agent and input device (for example, Tab or Shift+Tab).
Let entryElement be the element from which focus is entering the focusgroup.
Let focusgroupSegment be the set of focusgroup items in the nearest focusgroup scope that are reachable without crossing any opted-out elements in tree order from entryElement in the direction of navigation.
If focusgroupSegment has a last focused item and the no-memory
token is not present, and the last focused item is within focusgroupSegment, then let target be the last focused item.
Otherwise, let target be the first item that would be focused according to the following priority order: first, the lowest positive tabindex
value; then elements with tabindex="0"
or implicit focusability; and finally, as the lowest priority, elements with tabindex="-1"
. Within each priority level, prioritize the nearest to the entryElement in tree order.
Run the focusing steps for target. If the no-memory
token is not present, store target as the last focused item of the focusgroup.
This example shows how opted-out elements create multiple focusgroup entry points:
+ +<div focusgroup="toolbar wrap" aria-label="Text formatting">
+ <button type="button" tabindex="-1">Bold</button>
+ <button type="button" tabindex="-1">Italic</button>
+ <span focusgroup="none" aria-label="Help group">
+ <button type="button">Help</button>
+ <button type="button">Shortcuts</button>
+ </span>
+ <button type="button" tabindex="-1">Underline</button>
+</div>
+
+ Sequential focus navigation behavior:
+Arrow key navigation is unaffected by opted-out elements: pressing the right arrow on "Italic" moves focus directly to "Underline", treating the opted-out span as if it doesn't exist for arrow navigation purposes.
+This example shows a tablist with manual activation, wrap-around navigation, and disabled memory:
+ +<div focusgroup="toolbar wrap no-memory">
+ <button id="tab-1" tabindex="-1">macOS</button>
+ <button id="tab-2" tabindex="0">Windows</button>
+ <button id="tab-3" tabindex="-1">Linux</button>
+ </div>
+
+ Sequential focus navigation behavior:
+A key conflict element is a focusgroup item that consumes arrow key events for its own functionality, creating a conflict with focusgroup navigation. Key conflict elements include:
+ +input
elements (most, but not all types use arrow keys)textarea
elementsselect
elements when the arrow-key axis used by the focusgroup is the same axis used by the select elementcontenteditable
attributeaudio
and video
elements with visible controlsiframe
and object
elements with focusable content insideWhen focus is within a key conflict element, the element's native behavior takes precedence over focusgroup navigation. To ensure users can still navigate to other focusgroup items, user agents must provide escape behavior for native key conflict elements.
+ +When the user activates the escape behavior by pressing Tab or Shift+Tab from within a key conflict element, the user agent must run these steps:
+ +Let direction be "forward" if the user pressed Tab, or "backward" if the user pressed Shift+Tab.
Let keyConflictElement be the currently focused key conflict element.
Let candidates be all focusgroup items in the same focusgroup scope as keyConflictElement, excluding keyConflictElement itself.
If direction is "forward", let eligibleItems be all items in candidates that follow keyConflictElement in tree order.
If direction is "backward", let eligibleItems be all items in candidates that precede keyConflictElement in tree order.
Among eligibleItems, let target be the first item that would be focused according to the following priority order: first, the lowest positive tabindex
value; then elements with tabindex="0"
or implicit focusability; and finally, as the lowest priority, elements with tabindex="-1"
. Within each priority level, order by tree order.
If target is not null, run the focusing steps for target. + +
Otherwise, follow the normal sequential focus navigation rules.
In this toolbar example, the search input is a key conflict element:
+ +<div focusgroup="toolbar" aria-label="Text formatting">
+ <button type="button" tabindex="-1">Bold</button>
+ <button type="button" tabindex="-1">Italic</button>
+ <div>
+ <input type="text" placeholder="Search" /> <!-- Key conflict element -->
+ <button tabindex="-1">Go</button>
+ </div>
+ <button type="button" tabindex="-1">Save</button>
+ <button type="button" tabindex="-1">Print</button>
+</div>
+
+ When focus is within the search input:
+This example shows how authors can control escape behavior using tabindex
values:
<div focusgroup="toolbar" aria-label="Text formatting">
+ <button type="button" tabindex="-1">Bold</button>
+ <button type="button" tabindex="-1">Italic</button>
+ <div>
+ <input type="text" placeholder="Search" /> <!-- Key conflict element -->
+ <button tabindex="-1">Go</button> <!-- Higher priority -->
+ </div>
+ <button type="button" tabindex="0">Save</button> <!-- Lowest priority -->
+ <button type="button" >Print</button> <!-- Lower priority -->
+</div>
+
+ In this modified example, the priority order for escape behavior is:
+tabindex="0"
and tree order.)tabindex
elements were present, Tab would move to the "Go" button (lowest priority due to tabindex="-1"
)tabindex="-1"
are considered as the fallback option when no higher-priority elements are availableFocusgroups must coexist with scrolling behavior, as arrow keys are commonly used for both focus navigation and scrolling. The priority and interaction between these behaviors depends on the context.
+ +When a focusgroup is contained within a scrollable region:
+wrap
behavior: Focus navigation takes priority over scrolling. Arrow keys will move focus between focusgroup items, wrapping from end to start as configured. Scrolling will only occur as needed to bring the focused element into view.wrap
behavior: Focus navigation takes priority until the focus reaches a boundary (first or last item). Once at a boundary, continuing to press arrow keys in the same direction will allow normal scrolling behavior to resume.inline
or block
tokens), then arrow keys in the cross-axis will be available for scrolling.Since focusgroup navigation takes priority over scrolling, take care when constructing large focusgroups to avoid situations where content could be missed when jumping from one item to another.
+ +When a scrollable element is contained within a focusgroup, the behavior depends on whether there's a conflict between the focusgroup's arrow key handling and the scrollable element's needs:
+This example shows a focusgroup with restricted axis containing a scrollable region:
+ +<div style="height: 200px; overflow: auto;">
+ <div focusgroup="listbox block">
+ <div tabindex="0" aria-selected="true">Item 1</div>
+ <div tabindex="-1" aria-selected="false">Item 2</div>
+ <div tabindex="-1" aria-selected="false">Item 3</div>
+ <!-- Items 4-97 would be here, creating a long scrollable list -->
+ <div tabindex="-1" aria-selected="false">Item 98</div>
+ <div tabindex="-1" aria-selected="false">Item 99</div>
+ <div tabindex="-1" aria-selected="false">Item 100</div>
+ </div>
+</div>
+
+ In this example:
+block