diff --git a/source b/source index 2c5ffa547d9..6bb8a2bcb9d 100644 --- a/source +++ b/source @@ -4373,7 +4373,18 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute

In addition, the following aria-* content @@ -12625,6 +12636,8 @@ interface HTMLUnknownElement : HTMLElement { [CEReactions, Reflect] attribute boolean autofocus; [CEReactions, ReflectSetter] attribute long tabIndex; + [CEReactions, Reflect] attribute DOMString focusgroup; + [CEReactions, Reflect] attribute boolean focusgroupEntryPriority; undefined focus(optional FocusOptions options = {}); undefined blur(); }; @@ -13896,6 +13909,8 @@ https://software.hixie.ch/utilities/js/live-dom-viewer/?%3C%21DOCTYPE%20HTML%3E%

  • dir
  • draggable
  • enterkeyhint
  • +
  • focusgroup
  • +
  • focusgroup-entry-priority
  • headingoffset
  • headingreset
  • hidden
  • @@ -84270,7 +84285,7 @@ dictionary CommandEventInit : EventInit {
  • the element is not inert;
  • the element is either being rendered, delegating its rendering to its - children, or being used as relevant canvas fallback content.
  • + children, or being used as relevant canvas fallback content; The element itself. @@ -84588,12 +84603,16 @@ dictionary CommandEventInit : EventInit { @@ -85192,6 +85211,15 @@ dictionary CommandEventInit : EventInit { (For example, some platforms select the contents of a text control when that control is focused.)

    +
  • +

    If new focus target is a focusgroup item, + and the focusgroup owner does not have the no-memory token, then store new focus + target as the last focused item of the focusgroup segment that contains new focus + target.

    +
  • +
  • For each entry entry in new chain, in reverse order, run these substeps:

    @@ -85975,6 +86003,388 @@ dictionary CommandEventInit : EventInit {
    <div contenteditable autofocus>Edit <strong>me!</strong><div>
    +

    The focusgroup-entry-priority + attribute

    + +

    The focusgroup-entry-priority content attribute + is a boolean attribute that marks an element as the preferred entry point when entering a focusgroup segment via sequential focus + navigation. When this attribute is present on a focusgroup + item and the user has not previously focused an item within that focusgroup segment (or if the no-memory token is specified), that item will be given + priority over other items in the segment when determining the + entry element.

    + +

    The focusgroup attribute

    + +

    The 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.

    + +
    Concepts
    + +

    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:

    + + + + + + + + + + + + + + + + + + +
    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 segment is a contiguous subset of focusgroup items within a focusgroup scope + that are not separated by sequentially focusable elements that have been opted out + with focusgroup="none" or a nested focusgroup + scope with at least one focusgroup item. Sequentially focusable elements within + opted out subtrees (focusgroup="none") and nested focusgroups + create boundaries that divide a focusgroup scope into + one or more focusgroup segments. Each segment acts + independently for entry element determination.

    + +

    A focusgroup item is an element that is considered as focusable area + within a focusgroup scope except the elements whose + tabindex value is a negative integer.

    + +

    The order-modified document order is the ordering of elements used for sequential focus navigation after applying any layout reordering semantics that affect keyboard navigation order, such as the CSS order property for flex items and grid items. If no such reordering applies to a set of elements, then their order-modified document order is identical to tree order. User agents must use order-modified document order wherever the algorithms in this section reference it.

    + +
    ARIA Role Inference
    + +

    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.

    + +
    Focus Handling
    + + +
    Directional Navigation
    + +
    +

    When the user requests Directional Navigation and the currently focused area of a top-level traversable's DOM anchor is a focusgroup item, the user agent must run these steps:

    + +
      +
    1. If the navigation request is not in an allowed axis given the focusgroup owner's modifiers, do nothing.
    2. +
    3. Let direction be the spatial direction requested (e.g., up, down, left, right) as determined by the user agent and input device.
    4. +
    5. Let owner be the focusgroup owner.
    6. +
    7. Let currentItem be the currently focused focusgroup item.

    8. +
    9. Let items be all focusgroup items in order-modified document order.

    10. +
    11. Determine the nextItem by finding the next focusgroup item in order-modified document order in the direction.

    12. +
    13. If no nextItem is found and the wrap token is present, wrap to the first focusgroup item in the specified direction. Otherwise, do nothing.

    14. +
    15. If a nextItem is identified, run the focusing steps for it.

    16. +
    +
    + +
    Determining the entry element for sequential focus navigation
    + +
    +

    The entry element of a focusgroup segment given a focusgroup segment segment is determined by the following + algorithm:

    + +
      +
    1. If segment has a last focused item and the focusgroup owner does not have the no-memory token, and the last focused item is within segment, then return last focused item.

    2. + +
    3. Otherwise, return the first focusgroup item in segment according to the following + priority order: first, the first element with the focusgroup-entry-priority attribute in tree order; then, the first + element in order-modified document + order.

    4. +
    +
    + +
    +

    This example shows how opted-out elements create multiple focusgroup entry points:

    + +
    <div focusgroup="toolbar wrap" aria-label="Text formatting">
    +  <button type="button">Bold</button>
    +  <button type="button">Italic</button>
    +  <span focusgroup="none" aria-label="Help group">
    +    <button type="button">Help</button>
    +    <button type="button">Shortcuts</button>
    +  </span>
    +  <button type="button">Underline</button>
    +</div>
    + +

    Sequential focus navigation behavior:

    +
      +
    1. Entering from before the focusgroup: Pressing Tab focuses "Bold" (first + focusgroup item).
    2. +
    3. Tab from "Bold": Focuses "Help" (opted-out elements remain in sequential navigation order + order).
    4. +
    5. Tab from "Help": Focuses "Shortcuts" (normal sequential navigation within + opted-out subtree).
    6. +
    7. Tab from "Shortcuts": Enters the second focusgroup segment, focusing "Underline" +
    8. +
    9. Shift+Tab from "Help": Moves focus back to the focusgroup segment before + "Help", focus will be set on "Bold".
    10. +
    + +

    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 directional 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">macOS</button>
    +  <button id="tab-2">Windows</button>
    +  <button id="tab-3">Linux</button>
    +  </div>
    + +

    Sequential focus navigation behavior:

    +
      +
    1. Entering from before the focusgroup: Pressing Tab focuses "macOS" (first + focusgroup item in the order-modified document order).
    2. +
    3. Entering from after the focusgroup: Pressing Shift+Tab also focuses "macOS").
    4. +
    +
    + +
    +

    This example shows a toolbar where the focusgroup-entry-priority attribute designates a + preferred entry point:

    + +
    <div focusgroup="toolbar" aria-label="Text formatting">
    +  <button type="button">Undo</button>
    +  <button type="button">Redo</button>
    +  <button type="button" focusgroup-entry-priority>Bold</button>
    +  <button type="button">Italic</button>
    +  <button type="button">Underline</button>
    +</div>
    + +

    Sequential focus navigation behavior:

    +
      +
    1. Entering from before: Pressing Tab focuses "Bold" (has focusgroup-entry-priority, taking precedence + over order-modified document order).
    2. +
    3. After arrow navigation to "Italic": Pressing Tab to leave and + then Shift+Tab to return focuses "Italic" (memory of last focused item takes + precedence over entry priority).
    4. +
    +
    + +
    Key Conflict Elements
    + +

    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:

    + + + +

    When 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 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:

    + +
      +
    1. Let direction be "forward" if the user pressed Tab, or "backward" + if the user pressed Shift+Tab.

    2. + +
    3. Let keyConflictElement be the currently focused key conflict element.

    4. + +
    5. Let candidates be all focusgroup items + in the same focusgroup-segment as + keyConflictElement, excluding keyConflictElement itself.

    6. + +
    7. If direction is "forward", let eligibleItems be all items in + candidates that follow keyConflictElement in order-modified document order.

    8. + +
    9. If direction is "backward", let eligibleItems be all items in + candidates that precede keyConflictElement in order-modified document order.

    10. + +
    11. Among eligibleItems, let target be the first item that would be + focused according to the following priority order: first, the nearest element with the focusgroup-entry-priority attribute in order-modified document order; then, the nearest + element in order-modified document + order.

    12. + +
    13. If target is not null, run the focusing steps for + target. + +

    14. Otherwise, follow the normal sequential focus navigation rules.

    15. +
    +
    + +
    +

    In this toolbar example, the search input is a key conflict element:

    + +
    <div focusgroup="toolbar" aria-label="Text formatting">
    +  <button type="button">Bold</button>
    +  <button type="button">Italic</button>
    +  <input type="text" placeholder="Search" /> <!-- Key conflict element -->
    +  <button>Go</button>
    +  <button type="button">Save</button>
    +  <button type="button">Print</button>
    +</div>
    + +

    When focus is within the search input:

    + +
    + +
    Scrolling Interactions
    + +

    Focusgroups 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:

    + + +

    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="0" aria-selected="false">Item 2</div>
    +    <div tabindex="0" aria-selected="false">Item 3</div>
    +    <!-- Items 4-97 would be here, creating a long scrollable list -->
    +    <div tabindex="0" aria-selected="false">Item 98</div>
    +    <div tabindex="0" aria-selected="false">Item 99</div>
    +    <div tabindex="0" aria-selected="false">Item 100</div>
    +  </div>
    +</div>
    + +

    In this example:

    + +
    +

    Assigning keyboard shortcuts