Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 3 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /html/interaction/focus/focusgroup/tentative/sequential-navigation/directional-input-handler-scrollable-container.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<meta charset="utf-8">
<title>HTML Test: focusgroup - Scrollable containers as native directional input handlers</title>
<meta name="assert" content="Focusable scrollable containers block directional navigation only on their scrollable axes.">
<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/testdriver-actions.js"></script>
<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
<script src="../resources/focusgroup-utils.js"></script>
<style>
.scroll-container {
width: 100px;
height: 100px;
border: 1px solid black;
}
.scroll-content {
width: 200px;
height: 200px;
background: linear-gradient(to bottom right, red, blue);
}
.horizontal-scroll {
overflow-x: scroll;
overflow-y: hidden;
}
.vertical-scroll {
overflow-x: hidden;
overflow-y: scroll;
}
.both-scroll {
overflow: scroll;
}
</style>
<!-- Toolbar with horizontal-only scroll container -->
<div id="toolbar1" focusgroup="toolbar inline block">
<button tabindex=0 id="t1_btn1">Button 1</button>
<div id="t1_hscroll" class="scroll-container horizontal-scroll" tabindex="0">
<div class="scroll-content"></div>
</div>
<button tabindex=0 id="t1_btn2">Button 2</button>
</div>
<!-- Toolbar with vertical-only scroll container -->
<div id="toolbar2" focusgroup="toolbar inline block">
<button tabindex=0 id="t2_btn1">Button 1</button>
<div id="t2_vscroll" class="scroll-container vertical-scroll" tabindex="0">
<div class="scroll-content"></div>
</div>
<button tabindex=0 id="t2_btn2">Button 2</button>
</div>
<!-- Toolbar with both-axis scroll container -->
<div id="toolbar3" focusgroup="toolbar inline block">
<button tabindex=0 id="t3_btn1">Button 1</button>
<div id="t3_bothscroll" class="scroll-container both-scroll" tabindex="0">
<div class="scroll-content"></div>
</div>
<button tabindex=0 id="t3_btn2">Button 2</button>
</div>
<script>
promise_test(async t => {
const btn1 = document.getElementById("t1_btn1");
const hscroll = document.getElementById("t1_hscroll");
const btn2 = document.getElementById("t1_btn2");
// Directional navigation TO horizontal scroll container works.
await focusAndSendDirectionalInput(btn1, kRight);
assert_equals(document.activeElement, hscroll,
"Right should navigate to horizontal scroll container");
// Horizontal directional input (inline axis) are blocked - scroll container uses them.
await focusAndSendDirectionalInput(hscroll, kRight);
assert_equals(document.activeElement, hscroll,
"Right should NOT move focus (scroll container uses inline axis)");
await focusAndSendDirectionalInput(hscroll, kLeft);
assert_equals(document.activeElement, hscroll,
"Left should NOT move focus (scroll container uses inline axis)");
// Vertical directional input (block axis) should still work - scroll container doesn't use them.
await focusAndSendDirectionalInput(hscroll, kDown);
assert_equals(document.activeElement, btn2,
"Down SHOULD move focus (scroll container doesn't use block axis)");
await focusAndSendDirectionalInput(hscroll, kUp);
assert_equals(document.activeElement, btn1,
"Up SHOULD move focus (scroll container doesn't use block axis)");
}, "Horizontal-only scroll container blocks inline axis but allows block axis navigation");
promise_test(async t => {
const btn1 = document.getElementById("t2_btn1");
const vscroll = document.getElementById("t2_vscroll");
const btn2 = document.getElementById("t2_btn2");
// Directional navigation TO vertical scroll container works.
await focusAndSendDirectionalInput(btn1, kRight);
assert_equals(document.activeElement, vscroll,
"Right should navigate to vertical scroll container");
// Vertical directional input (block axis) are blocked - scroll container uses them.
await focusAndSendDirectionalInput(vscroll, kDown);
assert_equals(document.activeElement, vscroll,
"Down should NOT move focus (scroll container uses block axis)");
await focusAndSendDirectionalInput(vscroll, kUp);
assert_equals(document.activeElement, vscroll,
"Up should NOT move focus (scroll container uses block axis)");
// Horizontal directional input (inline axis) should still work - scroll container doesn't use them.
await focusAndSendDirectionalInput(vscroll, kRight);
assert_equals(document.activeElement, btn2,
"Right SHOULD move focus (scroll container doesn't use inline axis)");
await focusAndSendDirectionalInput(vscroll, kLeft);
assert_equals(document.activeElement, btn1,
"Left SHOULD move focus (scroll container doesn't use inline axis)");
}, "Vertical-only scroll container blocks block axis but allows inline axis navigation");
promise_test(async t => {
const btn1 = document.getElementById("t3_btn1");
const bothscroll = document.getElementById("t3_bothscroll");
const btn2 = document.getElementById("t3_btn2");
// Directional navigation TO both-axis scroll container works.
await focusAndSendDirectionalInput(btn1, kRight);
assert_equals(document.activeElement, bothscroll,
"Right should navigate to both-axis scroll container");
// All directional input is blocked - scroll container uses both axes.
await assert_directional_input_does_not_move_focus(bothscroll);
}, "Both-axis scroll container blocks all directional navigation");
</script>