New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HTML: Sequential focus navigation with shadow dom #17523
Merged
Merged
Changes from 2 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
34 changes: 34 additions & 0 deletions
34
shadow-dom/focus/focus-tabindex-order-shadow-negative.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom and negative tabindex in shadow scope</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=0> | ||
// <div #host tabindex=0> | ||
// #shadowRoot | ||
// <div #aboveSlot tabindex=-1> | ||
// <slot #slotAbove tabindex=-1> | ||
// (slotted) <div #slottedAbove tabindex=-1> | ||
// <slot #slotBelow tabindex=-1> | ||
// (slotted) <div #slottedBelow tabindex=-1> | ||
// <div #belowSlot tabindex=-1> | ||
// <div #belowHost tabindex=0> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = | ||
elementsInFlatTreeOrder = prepareDOM(document.body, false); | ||
setTabIndex(elementsInFlatTreeOrder, -1); | ||
setTabIndex([aboveHost, host, belowHost], 0); | ||
resetFocus(); | ||
return assertFocusOrder([aboveHost, host, belowHost]); | ||
}, "Order when all elements in shadow tree has negative tabindex"); | ||
</script> | ||
</body> |
37 changes: 37 additions & 0 deletions
37
shadow-dom/focus/focus-tabindex-order-shadow-slot-one.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0 except for one of the slot</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=0> | ||
// <div #host tabindex=0> | ||
// #shadowRoot | ||
// <div #aboveSlot tabindex=0> | ||
// <slot #slotAbove tabindex=0> | ||
// (slotted) <div #slottedAbove tabindex=0> | ||
// <slot #slotBelow tabindex=1> | ||
// (slotted) <div #slottedBelow tabindex=0> | ||
// <div #belowSlot tabindex=0> | ||
// <div #belowHost tabindex=0> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = | ||
elementsInFlatTreeOrder = prepareDOM(document.body, false); | ||
setTabIndex(elementsInFlatTreeOrder, 0); | ||
slotBelow.tabIndex = 1; | ||
resetFocus(); | ||
// Focus should move first according to flat tree order to #aboveHost and #host, then into #host's focus scope. | ||
// It will then move to #slottedBelow because #slotBelow has tabindex=1 (though we actually won't focus on the slot), | ||
// and then back to #host's focus scope again, finally getting out to the document focus scope. | ||
return assertFocusOrder([aboveHost, host, slottedBelow, aboveSlot, slottedAbove, belowSlot, belowHost]); | ||
}, "Order when all tabindex=0, except for one slot that has tabindex=1"); | ||
</script> | ||
</body> |
36 changes: 36 additions & 0 deletions
36
shadow-dom/focus/focus-tabindex-order-shadow-varying-tabindex.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom with varying tabindex values</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=3> | ||
// <div #host tabindex=3> | ||
// #shadowRoot | ||
// <div #aboveSlot tabindex=2> | ||
// <slot #slotAbove tabindex=1> | ||
// (slotted) <div #slottedAbove tabindex=4> | ||
// <slot #slotBelow tabindex=1> | ||
// (slotted) <div #slottedBelow tabindex=4> | ||
// <div #belowSlot tabindex=2> | ||
// <div #belowHost tabindex=3> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = | ||
elementsInFlatTreeOrder = prepareDOM(document.body, false); | ||
setTabIndex([slotAbove, slotBelow], 1); | ||
setTabIndex([aboveSlot, belowSlot], 2); | ||
setTabIndex([aboveHost, host, belowHost], 3); | ||
setTabIndex([slottedAbove, slottedBelow], 4); | ||
resetFocus(); | ||
return assertFocusOrder([aboveHost, host, slottedAbove, slottedBelow, aboveSlot, belowSlot, belowHost]); | ||
}, "Order with various tabindex values"); | ||
</script> | ||
</body> |
34 changes: 34 additions & 0 deletions
34
shadow-dom/focus/focus-tabindex-order-shadow-zero-delegatesFocus.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom that delegates focus and all tabindex=0</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=0> | ||
// <div #host tabindex=0> | ||
// #shadowRoot (delegatesFocus) | ||
// <div #aboveSlot tabindex=0> | ||
// <slot #slotAbove tabindex=0> | ||
// (slotted) <div #slottedAbove tabindex=0> | ||
// <slot #slotBelow tabindex=0> | ||
// (slotted) <div #slottedBelow tabindex=0> | ||
// <div #belowSlot tabindex=0> | ||
// <div #belowHost tabindex=0> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = elementsInFlatTreeOrder = prepareDOM(document.body, true); | ||
setTabIndex(elementsInFlatTreeOrder, 0); | ||
resetFocus(); | ||
// Focus should move in flat tree order since every one of them has tabindex ==0, | ||
// but doesn't include slots and #host. | ||
return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow && el !== host))); | ||
}, "Order when all tabindex=0 is and delegatesFocus = true"); | ||
</script> | ||
</body> |
35 changes: 35 additions & 0 deletions
35
shadow-dom/focus/focus-tabindex-order-shadow-zero-host-negative.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom and negative host tabindex</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=0> | ||
// <div #host tabindex=-1> | ||
// #shadowRoot | ||
// <div #aboveSlot tabindex=0> | ||
// <slot #slotAbove tabindex=0> | ||
// (slotted) <div #slottedAbove tabindex=0> | ||
// <slot #slotBelow tabindex=0> | ||
// (slotted) <div #slottedBelow tabindex=0> | ||
// <div #belowSlot tabindex=0> | ||
// <div #belowHost tabindex=0> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = | ||
elementsInFlatTreeOrder = prepareDOM(document.body, false); | ||
setTabIndex(elementsInFlatTreeOrder, 0); | ||
host.tabIndex = -1; | ||
resetFocus(); | ||
// Focus willl only move within the focus navigation scope of the document (not going to get into #host). | ||
return assertFocusOrder([aboveHost, belowHost]); | ||
}, "Order when all tabindex=0 except for host, which has tabindex=-1"); | ||
</script> | ||
</body> |
37 changes: 37 additions & 0 deletions
37
shadow-dom/focus/focus-tabindex-order-shadow-zero-host-not-set.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom and non-focusable host</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=0> | ||
// <div #host> | ||
// #shadowRoot | ||
// <div #aboveSlot tabindex=0> | ||
// <slot #slotAbove tabindex=0> | ||
// (slotted) <div #slottedAbove tabindex=0> | ||
// <slot #slotBelow tabindex=0> | ||
// (slotted) <div #slottedBelow tabindex=0> | ||
// <div #belowSlot tabindex=0> | ||
// <div #belowHost tabindex=0> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = | ||
elementsInFlatTreeOrder = prepareDOM(document.body, false); | ||
setTabIndex(elementsInFlatTreeOrder, 0); | ||
removeTabIndex([host]); | ||
resetFocus(); | ||
// Focus should move in flat tree order since every one of them has tabindex ==0, | ||
// but doesn't include #slot since it's not rendered and #host since its tabindex is not set | ||
// (but #host is considered as 0 in focus scope navigation, keeping the flat tree order for the shadow root's descendants). | ||
return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow && el !== host))); | ||
}, "Order when all tabindex=0 except host (tabindex not set)"); | ||
</script> | ||
</body> |
37 changes: 37 additions & 0 deletions
37
shadow-dom/focus/focus-tabindex-order-shadow-zero-host-one.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0 except host (tabindex=1)</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=0> | ||
// <div #host tabindex=1> | ||
// #shadowRoot | ||
// <div #aboveSlot tabindex=0> | ||
// <slot #slotAbove tabindex=0> | ||
// (slotted) <div #slottedAbove tabindex=0> | ||
// <slot #slotBelow tabindex=0> | ||
// (slotted) <div #slottedBelow tabindex=0> | ||
// <div #belowSlot tabindex=0> | ||
// <div #belowHost tabindex=0> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = | ||
elementsInFlatTreeOrder = prepareDOM(document.body, false); | ||
setTabIndex(elementsInFlatTreeOrder, 0); | ||
host.tabIndex = 1; | ||
resetFocus(); | ||
// Focus should move first to #host because it has tabindex=1, and then to the contents of its scope | ||
// (e.g. the contents of its shadow tree) in flat tree order, and then outside to the document scope | ||
// again (aboveHost & belowHost). | ||
return assertFocusOrder([host, aboveSlot, slottedAbove, slottedBelow, belowSlot, aboveHost, belowHost]); | ||
}, "Order when all tabindex=0 except for host, which has tabindex=1"); | ||
</script> | ||
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<!DOCTYPE html> | ||
<meta charset="utf-8"> | ||
<title>HTML Test: focus - the sequential focus navigation order with shadow dom and all tabindex=0</title> | ||
<link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="resources/shadow-utils.js"></script> | ||
<body> | ||
<script> | ||
// Structure: | ||
// <div #aboveHost tabindex=0> | ||
// <div #host tabindex=0> | ||
// #shadowRoot | ||
// <div #aboveSlot tabindex=0> | ||
// <slot #slotAbove tabindex=0> | ||
// (slotted) <div #slottedAbove tabindex=0> | ||
// <slot #slotBelow tabindex=0> | ||
// (slotted) <div #slottedBelow tabindex=0> | ||
// <div #belowSlot tabindex=0> | ||
// <div #belowHost tabindex=0> | ||
|
||
promise_test(() => { | ||
let elementsInFlatTreeOrder; | ||
let [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost] = | ||
elementsInFlatTreeOrder = prepareDOM(document.body, false); | ||
setTabIndex(elementsInFlatTreeOrder, 0); | ||
resetFocus(); | ||
// Focus should move in flat tree order since every one of them has tabindex==0, | ||
// but doesn't include slots. | ||
return assertFocusOrder(elementsInFlatTreeOrder.filter(el => (el !== slotAbove && el !== slotBelow))); | ||
}, "Order when all tabindex=0 is and delegatesFocus = false"); | ||
</script> | ||
</body> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
|
||
// Structure: | ||
// <div #aboveHost> | ||
// <div #host> | ||
// #shadowRoot | ||
// <div #aboveSlot> | ||
// <slot #slotAbove> | ||
// (slotted) <div #slottedAbove> | ||
// <slot #slotBelow> | ||
// (slotted) <div #slottedBelow> | ||
// <div #belowSlot> | ||
// <div #belowHost> | ||
function prepareDOM(container, delegatesFocus) { | ||
|
||
const aboveHost = document.createElement("div"); | ||
aboveHost.innerText = "aboveHost"; | ||
const host = document.createElement("div"); | ||
host.id = "host"; | ||
const slottedBelow = document.createElement("div"); | ||
slottedBelow.innerText = "slotted below"; | ||
slottedBelow.slot = "below"; | ||
const slottedAbove = document.createElement("div"); | ||
slottedAbove.innerText = "slotted above"; | ||
slottedAbove.slot = "above"; | ||
|
||
const belowHost = document.createElement("div"); | ||
belowHost.innerText = "belowHost"; | ||
container.appendChild(aboveHost); | ||
container.appendChild(host); | ||
container.appendChild(belowHost); | ||
host.appendChild(slottedBelow); | ||
host.appendChild(slottedAbove); | ||
const shadowRoot = host.attachShadow({ mode: "open", delegatesFocus: delegatesFocus}); | ||
const aboveSlot = document.createElement("div"); | ||
aboveSlot.innerText = "aboveSlot"; | ||
|
||
const slotAbove = document.createElement("slot"); | ||
slotAbove.name = "above"; | ||
const slotBelow = document.createElement("slot"); | ||
slotBelow.name = "below"; | ||
|
||
const belowSlot = document.createElement("div"); | ||
belowSlot.innerText = "belowSlot"; | ||
shadowRoot.appendChild(aboveSlot); | ||
shadowRoot.appendChild(slotAbove); | ||
shadowRoot.appendChild(slotBelow); | ||
shadowRoot.appendChild(belowSlot); | ||
|
||
return [aboveHost, host, aboveSlot, slotAbove, slottedAbove, slotBelow, slottedBelow, belowSlot, belowHost]; | ||
} | ||
|
||
function setTabIndex(elements, value) { | ||
for (let el of elements) { | ||
el.tabIndex = value; | ||
} | ||
} | ||
|
||
function removeTabIndex(elements) { | ||
for (let el of elements) { | ||
el.removeAttribute("tabindex"); | ||
} | ||
} | ||
|
||
function resetFocus() { | ||
document.body.focus(); | ||
} | ||
|
||
function navigateFocusForward() { | ||
// TAB = '\ue004' | ||
return test_driver.send_keys(document.body, "\ue004"); | ||
} | ||
|
||
function assertFocusOrder(expectedOrder) { | ||
let shadowRoot = document.getElementById("host").shadowRoot; | ||
return new Promise(async (resolve, reject) => { | ||
for (let el of expectedOrder) { | ||
await navigateFocusForward(); | ||
let focused = shadowRoot.activeElement ? shadowRoot.activeElement : document.activeElement; | ||
assert_equals(focused, el); | ||
} | ||
resolve(); | ||
}); | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
return new Promise
isn't needed here. Just make the whole function async, and then put the loop body inside the function:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh awesome, thanks :D