From ef960d735d5bd87e242866418aee6dcdbb41b4d6 Mon Sep 17 00:00:00 2001 From: intergrav Date: Mon, 20 Jul 2026 22:37:51 -0400 Subject: [PATCH] chore: remove animations setting animations should just rely on prefersReducedMotion for consistency. it's the same case with app theming - there's no light/dark setting as we rely on the system color scheme. --- src/App.svelte | 1 - src/app.css | 27 ++++++++++++--------------- src/lib/Library.svelte | 13 +++++++++++-- src/lib/Queue.svelte | 10 ++++------ src/lib/animations.ts | 6 ++---- src/lib/app.svelte.ts | 3 --- src/lib/components/ContextMenu.svelte | 4 ++-- src/lib/components/ProgressBar.svelte | 8 ++++---- src/lib/dialogs/Modal.svelte | 2 +- src/lib/dialogs/SettingsModal.svelte | 4 ---- src/lib/settings.svelte.ts | 1 - 11 files changed, 36 insertions(+), 43 deletions(-) diff --git a/src/App.svelte b/src/App.svelte index 78f8f03..57bed0c 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -119,7 +119,6 @@ $effect(() => { "dynamic-colors": settings.dynamicColors, "rounded-corners": settings.roundedCorners, "transparent-borders": settings.transparentOutlines, - animations: settings.animations, miniplayer: ui.miniplayer, "show-library-mobile": ui.showLibraryMobile, }; diff --git a/src/app.css b/src/app.css index 1295b73..88c8e01 100644 --- a/src/app.css +++ b/src/app.css @@ -48,32 +48,29 @@ button.pressable--gentle { } @media (prefers-reduced-motion: no-preference) { - html.animations.dynamic-colors { + html.dynamic-colors { transition: background-color 300ms cubic-bezier(0.33, 1, 0.68, 1); } - html.animations img.image-loading { + img.image-loading { visibility: hidden; } - html.animations button:where(.pressable, :has(> .icon)) { + button:where(.pressable, :has(> .icon)) { transform-origin: var(--button-transform-origin, center); transition: transform var(--button-hover-duration) var(--button-release-easing), opacity var(--button-hover-duration) var(--button-release-easing); } - html.animations - button:where(.pressable, :has(> .icon)):not(:disabled):not( - :where(.pressable--gentle) - ):hover, - html.animations - button.pressable.focused:not(:disabled, :active, .pressable--gentle) { + button:where(.pressable, :has(> .icon)):not(:disabled):not( + :where(.pressable--gentle) + ):hover, + button.pressable.focused:not(:disabled, :active, .pressable--gentle) { transform: scale(var(--button-hover-scale)); } - html.animations - button:where(.pressable, :has(> .icon)):not(:disabled):active { + button:where(.pressable, :has(> .icon)):not(:disabled):active { transform: scaleX(var(--button-press-scale-x)) scaleY(var(--button-press-scale-y)); opacity: 0.5; @@ -81,16 +78,16 @@ button.pressable--gentle { transition-timing-function: ease-out; } - html.animations button.is-activated { + button.is-activated { animation: button-activation calc(var(--button-hover-duration) + var(--button-press-duration)) ease-out; } - html.animations button.pressable--gentle.is-activated { + button.pressable--gentle.is-activated { animation-name: button-activation-gentle; } - html.animations .progress-bar.is-activated:not(.disabled) { + .progress-bar.is-activated:not(.disabled) { animation: progress-bar-activation calc(var(--button-hover-duration) + var(--button-press-duration) - 35ms) ease-out; @@ -195,7 +192,7 @@ body { } @media (prefers-reduced-motion: no-preference) { - html.animations.dynamic-colors body { + html.dynamic-colors body { transition: background-color 300ms cubic-bezier(0.33, 1, 0.68, 1); } } diff --git a/src/lib/Library.svelte b/src/lib/Library.svelte index 864bc54..6ab15d4 100644 --- a/src/lib/Library.svelte +++ b/src/lib/Library.svelte @@ -665,9 +665,17 @@ $effect(() => { }); }); -function scrollToRow(key: string, align: "nearest" | "center" = "nearest") { +function scrollToRow( + key: string, + align: "nearest" | "center" = "nearest", + smooth = false, +) { const index = visibleRows.findIndex((row) => row.key === key); - if (index >= 0) virtualizer?.scrollToIndex(index, { align }); + if (index >= 0) + virtualizer?.scrollToIndex(index, { + align, + smooth: smooth && animationsEnabled(), + }); } function showKeyboardMenu(row: ItemRow) { @@ -726,6 +734,7 @@ function onKey(event: KeyboardEvent) { focusedIndex >= 0 && (key === "ArrowDown" || key === "ArrowUp") ? "center" : "nearest", + true, ); } } else if (code === "Enter") { diff --git a/src/lib/Queue.svelte b/src/lib/Queue.svelte index 5bc710e..6d3450a 100644 --- a/src/lib/Queue.svelte +++ b/src/lib/Queue.svelte @@ -248,7 +248,7 @@ function scrollToIndex(index: number, smooth = false) { } $effect(() => { - if (nav.head >= 0) scrollToIndex(nav.head); + if (nav.head >= 0) scrollToIndex(nav.head, true); }); $effect(() => { @@ -933,7 +933,7 @@ function showMenu(index: number, x?: number, y?: number) { gap: 1rem; @media (prefers-reduced-motion: no-preference) { - :global(html.animations) & button { + & button { transition-property: transform; } } @@ -950,7 +950,7 @@ function showMenu(index: number, x?: number, y?: number) { border-block-end: var(--border-subtle); @media (prefers-reduced-motion: no-preference) { - :global(html.animations.dynamic-colors) & { + :global(html.dynamic-colors) & { transition: background-color 300ms cubic-bezier(0.33, 1, 0.68, 1); } } @@ -1073,9 +1073,7 @@ function showMenu(index: number, x?: number, y?: number) { display: inline-block; @media (prefers-reduced-motion: no-preference) { - :global(html.animations) & { - animation: spin 1.5s linear infinite; - } + animation: spin 1.5s linear infinite; } } } diff --git a/src/lib/animations.ts b/src/lib/animations.ts index 39683ab..ad4700a 100644 --- a/src/lib/animations.ts +++ b/src/lib/animations.ts @@ -1,4 +1,4 @@ -import { settings } from "./settings.svelte.js"; +import { prefersReducedMotion } from "svelte/motion"; const activationTimers = new WeakMap(); const imageFadeAnimations = new WeakMap(); @@ -47,9 +47,7 @@ export function animateEntryRows( } } -export const animationsEnabled = () => - settings.animations && - !window.matchMedia("(prefers-reduced-motion: reduce)").matches; +export const animationsEnabled = () => !prefersReducedMotion.current; export function fadeImage(image: HTMLImageElement) { if (!animationsEnabled()) return; diff --git a/src/lib/app.svelte.ts b/src/lib/app.svelte.ts index 7106239..b557b27 100644 --- a/src/lib/app.svelte.ts +++ b/src/lib/app.svelte.ts @@ -93,9 +93,6 @@ export const init = async () => { ) { parsed.visualizerPlacement = "start"; } - if ("eyeCandy" in parsed && !("animations" in parsed)) - parsed.animations = parsed.eyeCandy; - delete parsed.eyeCandy; if (typeof parsed.fontSize === "number") { if (parsed.fontSize <= 1) parsed.fontSize *= 16; else if (parsed.fontSize > 16) parsed.fontSize *= 0.16; diff --git a/src/lib/components/ContextMenu.svelte b/src/lib/components/ContextMenu.svelte index 090ad79..b52649b 100644 --- a/src/lib/components/ContextMenu.svelte +++ b/src/lib/components/ContextMenu.svelte @@ -290,10 +290,10 @@ function onKey(event: KeyboardEvent) { } } @media (prefers-reduced-motion: no-preference) { - :global(html.animations) .menu.ready { + .menu.ready { animation: pop-in 75ms ease-out; } - :global(html.animations) .submenu.ready { + .submenu.ready { animation-name: pop-from-side; } } diff --git a/src/lib/components/ProgressBar.svelte b/src/lib/components/ProgressBar.svelte index f441f07..9d60a5c 100644 --- a/src/lib/components/ProgressBar.svelte +++ b/src/lib/components/ProgressBar.svelte @@ -83,21 +83,21 @@ const percentage = $derived( transform-origin: bottom center; } .simple:not(.disabled):hover, - :global(html.animations) .simple:not(.disabled):global(.is-activated) { + .simple:not(.disabled):global(.is-activated) { --thumb-opacity: 1; } @media (prefers-reduced-motion: no-preference) { - :global(html.animations) :is(.simple, .triangle) { + :is(.simple, .triangle) { transition: transform var(--button-hover-duration) ease-out; } - :global(html.animations) :is(.simple, .triangle):not(.disabled):active { + :is(.simple, .triangle):not(.disabled):active { transform: scaleY( var(--progress-press-scale, var(--button-press-scale-y)) ); transition-duration: var(--button-press-duration); } - :global(html.animations) .loading .track::after { + .loading .track::after { position: absolute; inset: 0; background: linear-gradient( diff --git a/src/lib/dialogs/Modal.svelte b/src/lib/dialogs/Modal.svelte index 1977d41..eb42bec 100644 --- a/src/lib/dialogs/Modal.svelte +++ b/src/lib/dialogs/Modal.svelte @@ -68,7 +68,7 @@ $effect(() => { } } @media (prefers-reduced-motion: no-preference) { - :global(html.animations) dialog[open] { + dialog[open] { animation: pop-in 100ms ease-out; } } diff --git a/src/lib/dialogs/SettingsModal.svelte b/src/lib/dialogs/SettingsModal.svelte index e9b92ad..f189606 100644 --- a/src/lib/dialogs/SettingsModal.svelte +++ b/src/lib/dialogs/SettingsModal.svelte @@ -228,10 +228,6 @@ const columnSettings = [ {t("settings.dynamic_favicon")} -
- {t("settings.animations")} - -
{t("settings.transparent_borders")} diff --git a/src/lib/settings.svelte.ts b/src/lib/settings.svelte.ts index 846ac8e..f3fa15e 100644 --- a/src/lib/settings.svelte.ts +++ b/src/lib/settings.svelte.ts @@ -41,7 +41,6 @@ const settingDefs = { downloadsAutoSongs: { default: 3 }, downloadsAutoTrigger: { default: 10 }, dynamicFavicon: { default: false }, - animations: { default: true }, enableAlbum: { default: true }, enableArtist: { default: true }, enableDisc: { default: false }, -- 2.51.2