finish animations and add elevation

This commit is contained in:
Vincent van der Wal
2026-08-06 22:19:17 +02:00
parent d0f94094ca
commit 83b0e46e64
21 changed files with 328 additions and 112 deletions
+39 -36
View File
@@ -135,9 +135,18 @@
/* ── Day switching ────────────────────────────────────────────────────────
Only the three regions whose content depends on the selected day take part
in the cross-fade. Everything else keeps its pixels: the `day-switch`
class cancels the root animation, so the strip, header and page chrome do
not so much as flicker while the table, summary and charts swap over. */
in the cross-fade - and nothing else is captured at all. A captured
element is neither painted nor hit-testable in the live page for the
length of the animation (per spec: as if it had visibility:hidden and
pointer-events:none), and the root is captured by default, which captures
the whole page. That is what made the strip unclickable and the page
unscrollable while a switch played - no amount of pointer-events on the
overlay could fix it, because the page underneath was gone too. With the
root left un-named the strip, the chrome and the scroller keep their live
pixels and stay fully interactive. */
:root.day-switch {
view-transition-name: none;
}
:root.day-switch .day-region-table {
view-transition-name: day-table;
}
@@ -148,23 +157,20 @@
view-transition-name: day-charts;
}
/* The sticky day strip never changes during a day switch, but it has to be
captured too: view-transition snapshots all paint in one layer above the
page, so without its own group (and a higher z-index in that layer) the
fading table and charts would slide over the top of it. */
:root.day-switch .daystrip {
view-transition-name: daystrip;
}
::view-transition-group(daystrip) {
z-index: 20;
/* Region snapshots paint in a viewport-fixed layer above the live page, at
their full layout size - including the part of the table normally
scrolled up behind the sticky strip and the topbar. The strip used to be
captured purely to stay on top of that, but a captured strip is dead to
input; instead the whole overlay is clipped at the strip bar's bottom
edge (measured per switch by runDayTransition), so the snapshots stay
out of the chrome and the chrome stays live. */
:root.day-switch::view-transition {
clip-path: inset(var(--day-switch-clip, 0px) 0 0 0);
}
/* Same for the topbar and the sidebar: a captured region's snapshot is
painted at its layout position, including the part normally scrolled up
behind the chrome. Both are also identical either side of a *page* swap,
so they are captured there too and pinned below - a region that does not
change should not be animated at all. */
:root.day-switch .topbar,
/* Page swaps capture the topbar and sidebar: a region that is identical on
both sides should not be animated at all, so they are pinned here and
swapped outright below. */
:root.page-switch .topbar {
view-transition-name: topbar;
}
@@ -178,24 +184,27 @@
z-index: 25;
}
/* The root fade is the page swap's own; during a day switch the chrome must
not so much as flicker, so it is cancelled outright. */
:root.day-switch::view-transition-old(root),
:root.day-switch::view-transition-new(root) {
animation: none;
}
@media (prefers-reduced-motion: reduce) {
.day-region-table,
.day-region-summary,
.day-region-charts,
.daystrip,
.topbar,
.sidebar-region {
view-transition-name: none;
}
}
/* The snapshot layer is a fixed overlay across the whole viewport and it
hit-tests, so for the length of an animation every click would land on it
and die - a day tapped while the previous switch is still fading simply
went dead. Let input fall through to the live page instead: by the time
the pseudo elements exist the DOM is already in its final state, and a
click that starts a new transition supersedes the running one cleanly
(see view-transition.ts). */
::view-transition {
pointer-events: none;
}
/* ── Cross-fades that do not dip ──────────────────────────────────────────
The default cross-fade is NOT opacity-neutral: coverage of two stacked
layers is `new + old * (1 - new)`, so at the midpoint the pair covers only
@@ -240,21 +249,15 @@
mix-blend-mode: plus-lighter;
}
/* Chrome captured only so the fading regions cannot paint over it. The strip
does change - the selected day moves - but that change belongs to the
regions' cross-fade, not to the strip, so it swaps outright: the outgoing
snapshot is dropped rather than held, because the selected cell is a
translucent `bg-primary/10` tint and anything left underneath shows
through it as a second, doubled label. */
/* Pinned chrome swaps outright: identical on both sides, so any animation
would only risk a flicker. */
::view-transition-old(topbar),
::view-transition-old(sidebar),
::view-transition-old(daystrip) {
::view-transition-old(sidebar) {
animation: none;
opacity: 0;
}
::view-transition-new(topbar),
::view-transition-new(sidebar),
::view-transition-new(daystrip) {
::view-transition-new(sidebar) {
animation: none;
opacity: 1;
}