-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Bug 1938639 [wpt PR 49802] - [carousel] Pin the selected scroll-marke…
…r for targeted scrolls, a=testonly Automatic update from web-platform-tests [carousel] Pin the selected scroll-marker for targeted scrolls The CSS working group resolved[1] that when a scroll operation is aimed at an element, i.e. Element.scrollIntoView, the associated scroll-marker-group should select the active scroll-marker based on the element which the operation is intending to scroll to. In such cases, the scroll-marker that should be selected is the scroll-marker associated with the first scroll target (a scroll target is an element which generates a scroll-marker) found through a search starting from the target of the scrollIntoView itself and backwards in tree-order. As soon as some other type of scroll occurs, e.g. Element.scrollTo, or a user gesture scroll, the scroll-marker-group should no longer consider its active marker pinned, i.e. it should be based on the scroll position. This patch implements this for elements in general, but not for ::column pseudo elements which may also act as scroll targets since ::column::scroll-marker is allowed. The ::column case needs to be handled specially as ::column pseudos are not parents of the elements which are flowed into them in the DOM tree. This will be done in a follow-up patch. [1] w3c/csswg-drafts#10738 (comment) Bug: 380062280 Change-Id: I363e0f055f9791ead0b35f4bbe037db91f299624 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6089232 Reviewed-by: Steve Kobes <[email protected]> Commit-Queue: David Awogbemila <[email protected]> Cr-Commit-Position: refs/heads/main@{#1399197} -- wpt-commits: 9bbcdbf23b7b1ba83b82211b46f84c488bfc98e9 wpt-pr: 49802
- Loading branch information
1 parent
2f481a1
commit ff702e2
Showing
1 changed file
with
247 additions
and
0 deletions.
There are no files selected for viewing
247 changes: 247 additions & 0 deletions
247
testing/web-platform/tests/css/css-overflow/targeted-scroll-marker-selection.tentative.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,247 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
|
||
<head> | ||
<meta charset="utf-8"> | ||
<title>CSS Test: scroll tracking for ::scroll-markers whose orignatin elements cannot be scroll-aligned </title> | ||
<link rel="help" href="https://drafts.csswg.org/css-overflow-5/#scroll-container-scroll"> | ||
<script src="/resources/testharness.js"></script> | ||
<script src="/resources/testharnessreport.js"></script> | ||
<script src="/resources/testdriver.js"></script> | ||
<script src="/resources/testdriver-actions.js"></script> | ||
<script src="/resources/testdriver-vendor.js"></script> | ||
<script src="/css/css-transitions/support/helper.js"></script> | ||
<script src="/dom/events/scrolling/scroll_support.js"></script> | ||
</head> | ||
|
||
<body> | ||
<style> | ||
.wrapper { | ||
display: grid; | ||
justify-content: center; | ||
} | ||
|
||
.carousel { | ||
display: grid; | ||
grid-auto-flow: column; | ||
width: 1600px; | ||
height: 512px; | ||
overflow-x: scroll; | ||
scroll-snap-type: x mandatory; | ||
list-style-type: none; | ||
scroll-behavior: smooth; | ||
border: solid 2px grey; | ||
padding-top: 10%; | ||
text-align: center; | ||
counter-set: markeridx -1; | ||
|
||
div>.item { | ||
&>.itemchild { | ||
|
||
} | ||
scroll-snap-align: center; | ||
height: 80%; | ||
width: 318px; | ||
border: 1px solid; | ||
place-content: center; | ||
|
||
&::scroll-marker { | ||
content: counter(markeridx); | ||
counter-increment: markeridx; | ||
align-content: center; | ||
text-align: center; | ||
width: 35px; | ||
height: 35px; | ||
border: 3px solid gray; | ||
border-radius: 50%; | ||
margin: 3px; | ||
background-color: red; | ||
} | ||
|
||
&::scroll-marker:target-current { | ||
background-color: green; | ||
} | ||
&::scroll-marker:checked { | ||
background-color: green; | ||
} | ||
} | ||
|
||
scroll-marker-group: after; | ||
|
||
&::scroll-marker-group { | ||
height: 45px; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
border: solid 1px black; | ||
border-radius: 30px; | ||
} | ||
} | ||
</style> | ||
<div class="wrapper" id="wrapper"> | ||
<div class="carousel" id="carousel"> | ||
<div> | ||
<div class="item" id="item0" tabindex=0> | ||
<div class="itemchild" id="itemchild0">0</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling0"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item1" tabindex=0> | ||
<div class="itemchild" id="itemchild1">1</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling1"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item2" tabindex=0> | ||
<div class="itemchild" id="itemchild2">2</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling2"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item3" tabindex=0> | ||
<div class="itemchild" id="itemchild3">3</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling3"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item4" tabindex=0> | ||
<div class="itemchild" id="itemchild4">4</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling4"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item5" tabindex=0> | ||
<div class="itemchild" id="itemchild5">5</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling5"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item6" tabindex=0> | ||
<div class="itemchild" id="itemchild6">6</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling6"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item7" tabindex=0> | ||
<div class="itemchild" id="itemchild7">7</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling7"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item8" tabindex=0> | ||
<div class="itemchild" id="itemchild8">8</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling8"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item9" tabindex=0> | ||
<div class="itemchild" id="itemchild9">9</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling9"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item10" tabindex=0> | ||
<div class="itemchild" id="itemchild10">10</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling10"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item11" tabindex=0> | ||
<div class="itemchild" id="itemchild11">11</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling11"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item12" tabindex=0> | ||
<div class="itemchild" id="itemchild12">12</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling12"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item13" tabindex=0> | ||
<div class="itemchild" id="itemchild13">13</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling13"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item14" tabindex=0> | ||
<div class="itemchild" id="itemchild14">14</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling14"></div> | ||
</div> | ||
<div> | ||
<div class="item" id="item15" tabindex=0> | ||
<div class="itemchild" id="itemchild15">15</div> | ||
</div> | ||
<div class="itemsibling" id="itemsibling15"></div> | ||
</div> | ||
</div> | ||
</div> | ||
<script> | ||
|
||
const carousel = document.getElementById("carousel"); | ||
const items = document.querySelectorAll(".item"); | ||
const wrapper = document.getElementById("wrapper"); | ||
|
||
RED = "rgb(255, 0, 0)"; | ||
GREEN = "rgb(0, 128, 0)"; | ||
|
||
function verifySelectedMarker(selected_idx) { | ||
for (let idx = 0; idx < items.length; idx++) { | ||
const should_be_selected = idx == selected_idx | ||
let expected_color = should_be_selected ? GREEN : RED; | ||
const color = | ||
getComputedStyle(items[idx], "::scroll-marker").backgroundColor; | ||
assert_equals(color, expected_color, | ||
`marker ${idx} should be ${should_be_selected ? "" : "un"}selected.`); | ||
} | ||
} | ||
|
||
const max_scroll_offset = carousel.scrollWidth - carousel.clientWidth; | ||
async function testTargetedHasActiveMarker(test, element, expected_idx) { | ||
// Start from somewhere in the middle, ensuring that scrolling to the | ||
// extremes generates scrollend events. | ||
await waitForScrollReset(test, carousel, max_scroll_offset / 2); | ||
const color = | ||
getComputedStyle(items[expected_idx], "::scroll-marker").backgroundColor; | ||
assert_not_equals(color, GREEN, | ||
`Target item ${expected_idx} is not selected yet.`); | ||
const scrollend_promise = waitForScrollendEventNoTimeout(carousel); | ||
element.scrollIntoView({behavior: "smooth"}); | ||
await scrollend_promise; | ||
verifySelectedMarker(expected_idx); | ||
} | ||
|
||
promise_test(async(t) => { | ||
// Item 1 cannot be snap-aligned because there is not enough | ||
// room for its scroll container to be aligned to its center. | ||
const target_item = items[1]; | ||
await testTargetedHasActiveMarker(t, target_item, 1); | ||
}, "scroll-marker of target (idx 1) of scrollIntoView is selected"); | ||
|
||
promise_test(async(t) => { | ||
// Item 14 cannot be snap-aligned because there is not enough | ||
// room for its scroll container to be aligned to its center. | ||
const target_item = items[14]; | ||
await testTargetedHasActiveMarker(t, target_item, 14); | ||
}, "scroll-marker of target (idx 14) of scrollIntoView is selected"); | ||
|
||
promise_test(async(t) => { | ||
const item14 = items[14]; | ||
const target_item = item14.querySelector(".itemchild"); | ||
// Item 14 is the parent. We call scrollIntoView on its child. | ||
await testTargetedHasActiveMarker(t, target_item, 14); | ||
}, "scroll-marker of parent of target of scrollIntoView is selected"); | ||
|
||
promise_test(async(t) => { | ||
const item14 = items[14]; | ||
const target_item = item14.nextElementSibling; | ||
// Item 14 is before itemsibling14 in the DOM. We call scrollIntoView on | ||
// itemsibling14. | ||
await testTargetedHasActiveMarker(t, target_item, 14); | ||
}, "scroll-marker of earlier sibling of target of scrollIntoView is selected"); | ||
</script> | ||
</body> | ||
|
||
</html> |