script: Add basic support for tab navigation#42952
Conversation
|
🔨 Triggering try run (#22574078780) for Linux (WPT) |
|
Test results for linux-wpt from try job (#22574078780): Flaky unexpected result (26)
Stable unexpected results that are known to be intermittent (19)
Stable unexpected results (8)
|
|
|
| winning_node_and_tab_index = Some((element, element_tab_index)); | ||
| continue; | ||
| }; | ||
| // If the candidate is a less than the current winner, then it replaces it as the winner. |
There was a problem hiding this comment.
did you mean to write "is a lesser tab index"?
There was a problem hiding this comment.
Sure. It was a bit implied from the text, but I agree that your wording is clearer. I'll clean up all the comments.
There was a problem hiding this comment.
I've updated most of the comments to be a bit clearer and also have renamed some variables to make it clear what the candidate is.
| for node in root_node | ||
| .upcast::<Node>() | ||
| .traverse_preorder(ShadowIncluding::Yes) |
There was a problem hiding this comment.
I wonder if its worth placing a (ordered) list of elements with a non-negative tabindex attribute on the document, to avoid this traversal. But we can worry about that later.
There was a problem hiding this comment.
We did consider this actually! It's a bit tricky because you still need to track the relative order of elements with equal tab indices in the DOM is. In the end we looked at what Gecko, WebKit, and Blink do. They seem to walk the DOM in this case. Even though it's expensive, I guess it's cheap enough as pressing tab is not a high frequency part of the code. Our plan was to do it this way and then optimize if we found an issue later.
| let Some((_, winning_tab_index)) = winning_node_and_tab_index else { | ||
| winning_node_and_tab_index = Some((element, element_tab_index)); | ||
| continue; | ||
| }; |
There was a problem hiding this comment.
If i understand tab navigation correctly then we will never find a better element if winning_tab_index is 1 and the focus direction is "forward", so can we return early here if that happens?
The same applies to find_first_tab_focusable_element.
There was a problem hiding this comment.
Hrm. In fact, I think we can generalize this. If we find any element with a tab index equal to current + 1 we can exit early. I'll make that change.
0b080bf to
c0bd3bc
Compare
|
@simonwuelker Thanks for the review. I've updated a new version of the change. PTAL when you have a moment. |
| for node in root_node | ||
| .upcast::<Node>() | ||
| .traverse_preorder(ShadowIncluding::Yes) |
| FocusDirection::Forward => match winning_node_and_tab_index { | ||
| Some((_, winning_tab_index)) | ||
| if compare_tab_indices(element_tab_index, winning_tab_index) != | ||
| Ordering::Less => {}, | ||
| _ => { |
There was a problem hiding this comment.
This match statement is pretty convoluted, consider using something like
if winning_node_and_tab_index.is_none_or(|(_, winning_tab_index)| {
compare_tab_indices(element_tab_index, winning_tab_index) == Ordering::Less
}) {
// ...
}(same for the other match arm below)
There was a problem hiding this comment.
I've done this. It's indeed a bit clearer.
| // Only promote a candidate to the current winner if it has a lesser tab | ||
| // index than the current winner or there is currently no winer. | ||
| winning_node_and_tab_index = Some((candidate_element, element_tab_index)); |
There was a problem hiding this comment.
if element_tab_index is 1 at this point then we can immediately return the candidate element, because we're not going to find another element with higher precedence (= lesser tab index)
There was a problem hiding this comment.
Okay. This is done now.
| // Step 8. If result is true and target is a focusable area | ||
| // that is click focusable, then Run the focusing steps at target. |
There was a problem hiding this comment.
Its unclear what spec algorithm this implements, please put a link either here or at the top of the function.
There was a problem hiding this comment.
Sorry. I'll remove these comments. They are from the event handling code that handles focus changes. I believe this part of tab navigation is not really specified.
c0bd3bc to
aeb8ac0
Compare
This change adds very basic support for tab navigation, but without support for focus scopes. Followup changes will refine the behavior of this implementation to follow the specification around focus scopes, shadow DOM, and slots. In particular `delegatesFocus` is not supported here yet. Signed-off-by: Martin Robinson <[email protected]> Co-authored-by: Oriol Brufau <[email protected]>
aeb8ac0 to
9dd199b
Compare
This change adds very basic support for tab navigation, but without support for focus scopes. Followup changes will refine the behavior of this implementation to follow the specification around focus scopes, shadow DOM, and slots. In particular `delegatesFocus` is not supported here yet. Testing: This causes quite a few WPT tests to start passing. Signed-off-by: Martin Robinson <[email protected]> Co-authored-by: Oriol Brufau <[email protected]>
This change adds very basic support for tab navigation, but without support for focus scopes. Followup changes will refine the behavior of this implementation to follow the specification around focus scopes, shadow DOM, and slots. In particular `delegatesFocus` is not supported here yet. Testing: This causes quite a few WPT tests to start passing. Signed-off-by: Martin Robinson <[email protected]> Co-authored-by: Oriol Brufau <[email protected]>
This change adds very basic support for tab navigation, but without
support for focus scopes. Followup changes will refine the behavior of
this implementation to follow the specification around focus scopes,
shadow DOM, and slots. In particular
delegatesFocusis not supportedhere yet.
Testing: This causes quite a few WPT tests to start passing.