Scope view transitions to event list and prevent page shift
This commit is contained in:
@@ -38,12 +38,65 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.event-filter-target-list {
|
||||||
|
view-transition-name: event-filter-list;
|
||||||
|
contain: layout paint;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
scrollbar-gutter: stable both-edges;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes event-filter-vt-fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes event-filter-vt-fade-out {
|
||||||
|
from {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: no-preference) {
|
@media (prefers-reduced-motion: no-preference) {
|
||||||
|
::view-transition-group(root),
|
||||||
::view-transition-old(root),
|
::view-transition-old(root),
|
||||||
::view-transition-new(root) {
|
::view-transition-new(root) {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-group(event-filter-list) {
|
||||||
animation-duration: 240ms;
|
animation-duration: 240ms;
|
||||||
animation-timing-function: ease;
|
animation-timing-function: ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
::view-transition-old(event-filter-list),
|
||||||
|
::view-transition-new(event-filter-list) {
|
||||||
|
animation-duration: 240ms;
|
||||||
|
animation-timing-function: ease;
|
||||||
|
mix-blend-mode: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-old(event-filter-list) {
|
||||||
|
animation-name: event-filter-vt-fade-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-new(event-filter-list) {
|
||||||
|
animation-name: event-filter-vt-fade-in;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -130,6 +183,7 @@
|
|||||||
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||||
let activeViewTransition = null;
|
let activeViewTransition = null;
|
||||||
let isViewTransitionMutation = false;
|
let isViewTransitionMutation = false;
|
||||||
|
let hasAppliedInitialFilter = false;
|
||||||
let currentFilter = { type: 'all', value: '' };
|
let currentFilter = { type: 'all', value: '' };
|
||||||
let suppressedChangeEvents = 0;
|
let suppressedChangeEvents = 0;
|
||||||
|
|
||||||
@@ -437,8 +491,9 @@
|
|||||||
setActiveControl(filterState);
|
setActiveControl(filterState);
|
||||||
|
|
||||||
const immediateVisibility = shouldMutateVisibilityImmediately();
|
const immediateVisibility = shouldMutateVisibilityImmediately();
|
||||||
|
const shouldAnimateLayout = immediateVisibility && hasAppliedInitialFilter;
|
||||||
|
|
||||||
runWithLayoutTransition(() => {
|
const mutateVisibility = () => {
|
||||||
events.forEach((eventItem) => {
|
events.forEach((eventItem) => {
|
||||||
if (matches(eventItem, filterState)) {
|
if (matches(eventItem, filterState)) {
|
||||||
showEvent(eventItem, { immediateVisibility });
|
showEvent(eventItem, { immediateVisibility });
|
||||||
@@ -446,7 +501,15 @@
|
|||||||
hideEvent(eventItem, { immediateVisibility });
|
hideEvent(eventItem, { immediateVisibility });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (shouldAnimateLayout) {
|
||||||
|
runWithLayoutTransition(mutateVisibility);
|
||||||
|
} else {
|
||||||
|
mutateVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
hasAppliedInitialFilter = true;
|
||||||
|
|
||||||
updateStatus(filterState);
|
updateStatus(filterState);
|
||||||
syncState(filterState);
|
syncState(filterState);
|
||||||
|
|||||||
Reference in New Issue
Block a user