Add switch theme animation

This commit is contained in:
Wendelin 2025-02-13 16:00:35 +01:00
parent c824e58e0a
commit d4125d433f
No known key found for this signature in database
2 changed files with 50 additions and 3 deletions

View File

@ -20,6 +20,12 @@
<meta name="color-scheme" content="dark light" />
<%= renderTemplate("_style_base.html.template") %>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
html {
background-color: var(--primary-background-color, #fafafa);
color: var(--primary-text-color, #212121);

View File

@ -51,7 +51,7 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
selectedTheme: ev.detail.settings,
browserThemeEnabled: ev.detail.storageLocation === "browser",
});
this._applyTheme(mql.matches);
this._animateApplyTheme(mql.matches);
}
if (ev.detail.storageLocation === "browser") {
@ -71,10 +71,12 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
selectedTheme,
browserThemeEnabled: false,
});
this._applyTheme(mql.matches);
this._animateApplyTheme(mql.matches);
});
mql.addEventListener("change", (ev) => this._applyTheme(ev.matches));
mql.addEventListener("change", (ev) =>
this._animateApplyTheme(ev.matches)
);
if (!this._themeApplied && mql.matches) {
applyThemesOnElement(
@ -121,6 +123,45 @@ export default <T extends Constructor<HassBaseEl>>(superClass: T) =>
);
}
private async _animateApplyTheme(darkPreferred: boolean) {
if (!this.hass) {
return;
}
if (!document.startViewTransition || !document.documentElement.animate) {
this._applyTheme(darkPreferred);
} else {
await document.startViewTransition(() => {
this._applyTheme(darkPreferred);
}).ready;
const { top, left, width, height } =
document.documentElement.getBoundingClientRect();
const x = left + width / 2;
const y = top + height / 2;
const right = window.innerWidth - left;
const bottom = window.innerHeight - top;
const maxRadius = Math.hypot(
Math.max(left, right),
Math.max(top, bottom)
);
document.documentElement.animate(
{
clipPath: [
`circle(0px at ${x}px ${y}px)`,
`circle(${maxRadius}px at ${x}px ${y}px)`,
],
},
{
duration: 500,
easing: "ease-in-out",
pseudoElement: "::view-transition-new(root)",
}
);
}
}
private _applyTheme(darkPreferred: boolean) {
if (!this.hass) {
return;