diff --git a/source b/source index df283bc9191..17ca2c4cb06 100644 --- a/source +++ b/source @@ -87006,8 +87006,12 @@ dictionary CommandEventInit : EventInit {

The focusgroup scope of a focusgroup owner is all of its shadow-including descendants, excluding any descendants that are themselves a focusgroup owner, are in a different focusgroup scope, or have opted out with focusgroup="none".

+ data-x="focusgroup scope">focusgroup scope, have opted out with focusgroup="none", are in the document's top + layer, or are shadow-including + descendants of an element that is both in the document's top layer + and is itself a shadow-including + descendant of the focusgroup owner.

The focusgroup owner of an element is the nearest shadow-including @@ -87018,8 +87022,11 @@ dictionary CommandEventInit : EventInit { item">focusgroup items within a focusgroup scope that can be navigated without crossing any segment boundary. The following create segment boundaries: sequentially focusable elements that have been opted out with focusgroup="none" and nested focusgroup scopes that contain at least one focusgroup item.

+ data-x="attr-focusgroup-none">focusgroup="none", nested focusgroup scopes that contain at least one focusgroup item, and + subtrees rooted at sequentially focusable elements in the document's top + layer that are shadow-including + descendants of the focusgroup owner.

@@ -87085,6 +87092,93 @@ dictionary CommandEventInit : EventInit { presses move focus in the expected visual direction established by the reading flow, and the direction of an arrow key is determined by the visual position of items in that order.

+
Top layer interaction
+ +

Elements in the document's top layer — such as popovers shown via showPopover(), modal dialog elements, + and fullscreen elements — are excluded from any ancestor focusgroup scope while + they remain in the top layer. This exclusion has the same effect as focusgroup="none" for the purpose of ancestor focusgroup + participation: the element and its shadow-including + descendants do not appear as focusgroup items in + the ancestor's scope, Directional Navigation in the ancestor focusgroup skips the + excluded subtree, and the subtree creates a segment + boundary for sequential focus navigation.

+ +

When an element leaves the top layer (for example, when a popover is hidden), + the element and its descendants participate in the ancestor focusgroup scope again + under the normal rules.

+ +

If the ancestor focusgroup's last focused item is within a subtree rooted at + an element that enters the top layer, then the last focused item is + preserved but temporarily ineligible. The entry element algorithm proceeds to the next priority: an element with + the focusgroupstart attribute, or the first + sequentially focusable focusgroup item in the segment. If the + subtree later leaves the top layer, then the last focused item becomes + eligible again.

+ +

A focusgroup attribute on the top-layer element itself + continues to operate normally. Only participation in ancestor focusgroups changes.

+ +

Authors should provide a keyboard path into a shown + popover, since its subtree + no longer participates in the ancestor focusgroup's arrow-key traversal. The appropriate + mechanism depends on the widget pattern — for example, a menu button opens its menu on + Enter, Space, or Down Arrow and focuses the first item.

+ +
+ +

In this example, a toolbar contains a popover. When the popover is hidden, arrow keys in + the toolbar move among the four buttons. When the popover is shown and enters the top + layer, its subtree is excluded from the toolbar's focusgroup scope:

+ +
<div focusgroup="toolbar wrap" aria-label="Text formatting">
+  <button type="button" aria-haspopup="true" aria-expanded="false"
+          aria-controls="color-picker" commandfor="color-picker"
+          command="show-popover">Text color</button>
+  <button type="button">Bold</button>
+  <button type="button">Italic</button>
+  <div id="color-picker" popover>
+    <button type="button">Red</button>
+    <button type="button">Green</button>
+    <button type="button">Blue</button>
+  </div>
+  <button type="button">Underline</button>
+</div>
+ +

Arrow keys in the toolbar skip the popover's buttons. Tab from a toolbar button + can reach the popover's buttons via sequential focus navigation, since the + excluded subtree creates a segment boundary.

+ +
+ +
+ +

If the popover defines its own focusgroup, that inner + focusgroup operates independently:

+ +
<div focusgroup="toolbar wrap" aria-label="Text formatting">
+  <button type="button" aria-haspopup="true" aria-expanded="false"
+          aria-controls="color-picker" commandfor="color-picker"
+          command="show-popover">Text color</button>
+  <button type="button">Bold</button>
+  <div id="color-picker" popover focusgroup="radiogroup"
+       aria-label="Color palette">
+    <button type="button" role="radio" aria-checked="true">Red</button>
+    <button type="button" role="radio" aria-checked="false">Green</button>
+    <button type="button" role="radio" aria-checked="false">Blue</button>
+  </div>
+  <button type="button">Underline</button>
+</div>
+ +

The popover's subtree is excluded from the parent toolbar's focusgroup when shown. Once + focus moves into the popover, its own radiogroup focusgroup provides independent arrow + key navigation among the color choices.

+ +
+
ARIA Role Inference

When a behavior token is used, the user agent may @@ -87232,9 +87326,13 @@ dictionary CommandEventInit : EventInit {

  • Let owner be the focusgroup owner of segment.

  • If owner has a last focused item, owner does not have - the nomemory token, and the last focused item is within segment, then return - the last focused item.

  • + the nomemory token, the last focused item is within segment, and the + last focused item is not in the document's + top layer and does not have a shadow-including ancestor that is in the + document's top layer, then return the last + focused item.

  • If any focusgroup item in segment has the focusgroupstart attribute, then return the first @@ -87272,9 +87370,15 @@ dictionary CommandEventInit : EventInit {

  • The last focused item is no longer within the focusgroup scope of its focusgroup owner (for example, because focusgroup="none" is added to it or a - shadow-including ancestor, or a new focusgroup attribute is added to it or a - shadow-including ancestor).

  • + shadow-including ancestor, or a new + focusgroup attribute is added to it or a + shadow-including ancestor), unless + the last focused item is no longer within the scope solely because it, or a + shadow-including ancestor, is in + the document's top layer (in which case the last focused item + is preserved but temporarily ineligible, as described in the top layer interaction + section).