Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5f652530ed | |||
| 11b927b91f | |||
| e1a426bde4 | |||
| 8a422aa4ee |
@@ -37,6 +37,69 @@
|
|||||||
<p id="eventfilter-status" class="visually-hidden" aria-live="polite"></p>
|
<p id="eventfilter-status" class="visually-hidden" aria-live="polite"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<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) {
|
||||||
|
::view-transition-group(root),
|
||||||
|
::view-transition-old(root),
|
||||||
|
::view-transition-new(root) {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
::view-transition-group(event-filter-list) {
|
||||||
|
animation-duration: 240ms;
|
||||||
|
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>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const filters = document.getElementById('eventfilters');
|
const filters = document.getElementById('eventfilters');
|
||||||
|
|
||||||
@@ -116,9 +179,62 @@
|
|||||||
|
|
||||||
const animationMs = 220;
|
const animationMs = 220;
|
||||||
let hideTimers = new WeakMap();
|
let hideTimers = new WeakMap();
|
||||||
|
const supportsViewTransitions = typeof document.startViewTransition === 'function';
|
||||||
|
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||||
|
let activeViewTransition = null;
|
||||||
|
let isViewTransitionMutation = false;
|
||||||
|
let hasAppliedInitialFilter = false;
|
||||||
let currentFilter = { type: 'all', value: '' };
|
let currentFilter = { type: 'all', value: '' };
|
||||||
let suppressedChangeEvents = 0;
|
let suppressedChangeEvents = 0;
|
||||||
|
|
||||||
|
const runWithLayoutTransition = (mutation) => {
|
||||||
|
if (!supportsViewTransitions || prefersReducedMotion) {
|
||||||
|
mutation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeViewTransition) {
|
||||||
|
mutation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const transition = document.startViewTransition(() => {
|
||||||
|
isViewTransitionMutation = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
mutation();
|
||||||
|
} finally {
|
||||||
|
isViewTransitionMutation = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
activeViewTransition = transition;
|
||||||
|
|
||||||
|
transition.ready.catch(() => {
|
||||||
|
// Can reject when the transition is skipped.
|
||||||
|
});
|
||||||
|
|
||||||
|
transition.updateCallbackDone.catch(() => {
|
||||||
|
// Keep skipped/aborted update callbacks from surfacing as uncaught.
|
||||||
|
});
|
||||||
|
|
||||||
|
transition.finished
|
||||||
|
.catch(() => {
|
||||||
|
// Browsers can skip overlapping transitions; ignore these rejections.
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
if (activeViewTransition === transition) {
|
||||||
|
activeViewTransition = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
mutation();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const shouldMutateVisibilityImmediately = () => supportsViewTransitions && !prefersReducedMotion;
|
||||||
|
|
||||||
const hasOptionValue = (selectElement, value) => {
|
const hasOptionValue = (selectElement, value) => {
|
||||||
if (!selectElement) {
|
if (!selectElement) {
|
||||||
return false;
|
return false;
|
||||||
@@ -251,21 +367,38 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const showEvent = (eventItem) => {
|
const showEvent = (eventItem, { immediateVisibility = false } = {}) => {
|
||||||
clearHideTimer(eventItem);
|
clearHideTimer(eventItem);
|
||||||
eventItem.hidden = false;
|
|
||||||
|
if (immediateVisibility) {
|
||||||
|
eventItem.hidden = false;
|
||||||
|
eventItem.classList.remove('is-filtered-out');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventItem.hidden) {
|
||||||
|
eventItem.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => {
|
||||||
eventItem.classList.remove('is-filtered-out');
|
eventItem.classList.remove('is-filtered-out');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const hideEvent = (eventItem) => {
|
const hideEvent = (eventItem, { immediateVisibility = false } = {}) => {
|
||||||
clearHideTimer(eventItem);
|
clearHideTimer(eventItem);
|
||||||
|
|
||||||
|
if (immediateVisibility) {
|
||||||
|
eventItem.classList.add('is-filtered-out');
|
||||||
|
eventItem.hidden = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
eventItem.classList.add('is-filtered-out');
|
eventItem.classList.add('is-filtered-out');
|
||||||
|
|
||||||
const timer = window.setTimeout(() => {
|
const timer = window.setTimeout(() => {
|
||||||
eventItem.hidden = true;
|
eventItem.hidden = true;
|
||||||
|
|
||||||
hideTimers.delete(eventItem);
|
hideTimers.delete(eventItem);
|
||||||
}, animationMs);
|
}, animationMs);
|
||||||
|
|
||||||
@@ -332,7 +465,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const visibleCount = events.filter((eventItem) => !eventItem.hidden).length;
|
const visibleCount = events.filter((eventItem) => matches(eventItem, filterState)).length;
|
||||||
let filterText = 'alle';
|
let filterText = 'alle';
|
||||||
|
|
||||||
if (filterState.type === 'tag' && tagSelect) {
|
if (filterState.type === 'tag' && tagSelect) {
|
||||||
@@ -357,13 +490,26 @@
|
|||||||
currentFilter = filterState;
|
currentFilter = filterState;
|
||||||
setActiveControl(filterState);
|
setActiveControl(filterState);
|
||||||
|
|
||||||
events.forEach((eventItem) => {
|
const immediateVisibility = shouldMutateVisibilityImmediately();
|
||||||
if (matches(eventItem, filterState)) {
|
const shouldAnimateLayout = immediateVisibility && hasAppliedInitialFilter;
|
||||||
showEvent(eventItem);
|
|
||||||
} else {
|
const mutateVisibility = () => {
|
||||||
hideEvent(eventItem);
|
events.forEach((eventItem) => {
|
||||||
}
|
if (matches(eventItem, filterState)) {
|
||||||
});
|
showEvent(eventItem, { immediateVisibility });
|
||||||
|
} else {
|
||||||
|
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