aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-05-19 02:48:04 +0000
committerFuwn <[email protected]>2026-05-19 02:48:04 +0000
commit41ccb3af55d189b5aedd4ee497e49ceda4f1fc8e (patch)
treecb7716d72bb370a1106c250debe8b1ad0272ce80
parentfix(nav): respect displayDisableAnimations in view transitions (diff)
downloaddue.moe-41ccb3af55d189b5aedd4ee497e49ceda4f1fc8e.tar.xz
due.moe-41ccb3af55d189b5aedd4ee497e49ceda4f1fc8e.zip
feat(a11y): rename Disable Page Transitions to Reduce MotionHEADmain
The setting previously only gated the fly slide in Root.svelte. Renaming the label to "Reduce motion" sets the expectation that it acts as a force-on for the browser's prefers-reduced-motion: reduce across the board, so the setting's scope is broadened to match. Storage key (displayDisableAnimations) stays the same so existing user preferences carry over. Only the i18n label and behavior scope change. Adds a reducesMotion() helper that combines the media query with the setting. View Transitions, Lenis init, and the details JS animation now all bypass via this helper. A reactive $: toggles html.reduce-motion on the root element based on the setting; the normalise.css bandaid that already collapsed animations under prefers-reduced-motion is duplicated under that class so every CSS animation and transition (Svelte fly, dropdown panels, hamburger morph, header scroll-hide, the global :where transitions) snaps to 0.01ms when the setting is on.
-rw-r--r--src/lib/Locale/english.ts3
-rw-r--r--src/lib/Locale/japanese.ts3
-rw-r--r--src/lib/Locale/layout.ts2
-rw-r--r--src/lib/Settings/Categories/Display.svelte3
-rw-r--r--src/routes/+layout.svelte17
-rw-r--r--src/styles/normalise.css9
6 files changed, 26 insertions, 11 deletions
diff --git a/src/lib/Locale/english.ts b/src/lib/Locale/english.ts
index 9918d98f..0cfc4035 100644
--- a/src/lib/Locale/english.ts
+++ b/src/lib/Locale/english.ts
@@ -77,8 +77,7 @@ const English: Locale = {
motionAndAccessibility: {
title: "Motion & Accessibility",
fields: {
- disablePageTransitionAnimations:
- "Disable page transition animations",
+ reduceMotion: "Reduce motion",
disableNotifications: "Disable verbose site notifications",
enableAniListNotifications: "Enable AniList notifications",
limitPanelAreaToScreenHeight: "Limit panel area to screen height",
diff --git a/src/lib/Locale/japanese.ts b/src/lib/Locale/japanese.ts
index 79e15e96..af309a25 100644
--- a/src/lib/Locale/japanese.ts
+++ b/src/lib/Locale/japanese.ts
@@ -75,8 +75,7 @@ const Japanese: Locale = {
motionAndAccessibility: {
title: "モーションとアクセシビリティ",
fields: {
- disablePageTransitionAnimations:
- "ページ遷移アニメーションを無効にする",
+ reduceMotion: "モーションを減らす",
disableNotifications: "詳細なサイト通知を無効にする",
enableAniListNotifications: "AniListの通知を有効にする",
limitPanelAreaToScreenHeight:
diff --git a/src/lib/Locale/layout.ts b/src/lib/Locale/layout.ts
index f5149b71..f317ab7f 100644
--- a/src/lib/Locale/layout.ts
+++ b/src/lib/Locale/layout.ts
@@ -80,7 +80,7 @@ export interface Locale {
motionAndAccessibility: {
title: LocaleValue;
fields: {
- disablePageTransitionAnimations: LocaleValue;
+ reduceMotion: LocaleValue;
disableNotifications: LocaleValue;
enableAniListNotifications: LocaleValue;
limitPanelAreaToScreenHeight: LocaleValue;
diff --git a/src/lib/Settings/Categories/Display.svelte b/src/lib/Settings/Categories/Display.svelte
index 8b1f0a43..7de57c5a 100644
--- a/src/lib/Settings/Categories/Display.svelte
+++ b/src/lib/Settings/Categories/Display.svelte
@@ -166,8 +166,7 @@ const onHelperChange = () => {
<b>{$locale().settings.display.categories.motionAndAccessibility.title}</b><br />
<SettingCheckboxToggle
setting="displayDisableAnimations"
- text={$locale().settings.display.categories.motionAndAccessibility.fields
- .disablePageTransitionAnimations}
+ text={$locale().settings.display.categories.motionAndAccessibility.fields.reduceMotion}
/>
<SettingCheckboxToggle
setting="displayDisableNotifications"
diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte
index a61d0a29..9ad33ca9 100644
--- a/src/routes/+layout.svelte
+++ b/src/routes/+layout.svelte
@@ -91,10 +91,19 @@ $: way = data.url.includes("/user")
$: if ($navigating) isMenuOpen = false;
+const reducesMotion = () =>
+ window.matchMedia("(prefers-reduced-motion: reduce)").matches ||
+ get(settings).displayDisableAnimations;
+
+$: if (browser)
+ document.documentElement.classList.toggle(
+ "reduce-motion",
+ $settings.displayDisableAnimations,
+ );
+
onNavigate((navigation) => {
if (!("startViewTransition" in document)) return;
- if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
- if (get(settings).displayDisableAnimations) return;
+ if (reducesMotion()) return;
const fromPath = navigation.from?.url.pathname ?? "/";
const toPath = navigation.to?.url.pathname ?? "/";
@@ -138,7 +147,7 @@ const animateDetails = (e: MouseEvent) => {
if (!summary) return;
const details = summary.parentElement as HTMLDetailsElement | null;
if (!details || details.tagName !== "DETAILS") return;
- if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
+ if (reducesMotion()) return;
e.preventDefault();
detailsAnimations.get(details)?.cancel();
@@ -182,7 +191,7 @@ const animateDetails = (e: MouseEvent) => {
onMount(async () => {
if (browser) {
- if (!window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
+ if (!reducesMotion()) {
lenis = new Lenis({ autoRaf: true });
lenisStore.set(lenis);
diff --git a/src/styles/normalise.css b/src/styles/normalise.css
index 37151e5f..d717e5f4 100644
--- a/src/styles/normalise.css
+++ b/src/styles/normalise.css
@@ -47,3 +47,12 @@ h6:before {
scroll-behavior: auto !important;
}
}
+
+html.reduce-motion *,
+html.reduce-motion *::before,
+html.reduce-motion *::after {
+ animation-duration: 0.01ms !important;
+ animation-iteration-count: 1 !important;
+ transition-duration: 0.01ms !important;
+ scroll-behavior: auto !important;
+}