perf(mui): smooth theme cross-fade via View Transitions API (was per-element repaint jank)
The per-element color/box-shadow transition repainted the whole tree every frame (~5fps). Replaced with document.startViewTransition: the browser cross-fades one GPU-composited snapshot of the page — smooth regardless of element count. flushSync + useLayoutEffect ensure the data-theme flip is captured in the transition; instant fallback where unsupported / reduced-motion. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,30 +13,20 @@ html {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Coordinated dark/light cross-fade. ThemeContext adds `.theme-transition` to
|
||||
<html> for ~300ms during a toggle (only on real switches, not initial load),
|
||||
so the whole UI fades its theme-driven colors together. Normal interactions
|
||||
keep their own transitions, because this rule applies only while the class
|
||||
is present. */
|
||||
html.theme-transition,
|
||||
html.theme-transition *,
|
||||
html.theme-transition *::before,
|
||||
html.theme-transition *::after {
|
||||
transition:
|
||||
background-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
border-color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
color 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
fill 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
stroke 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
box-shadow 0.3s cubic-bezier(0.4, 0, 0.2, 1) !important;
|
||||
/* Premium dark/light cross-fade via the View Transitions API (driven by
|
||||
ThemeContext.toggleTheme). The browser cross-fades a GPU-composited snapshot
|
||||
of the whole page — smooth at any element count — instead of repainting every
|
||||
node's colors (which stutters). Tune only the root cross-fade timing here. */
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation-duration: 0.3s;
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html.theme-transition,
|
||||
html.theme-transition *,
|
||||
html.theme-transition *::before,
|
||||
html.theme-transition *::after {
|
||||
transition: none !important;
|
||||
::view-transition-old(root),
|
||||
::view-transition-new(root) {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user