From b6262aa388e77b1b3cc3288b6d9d3534f8e6a896 Mon Sep 17 00:00:00 2001 From: Derek Chen Date: Fri, 21 Mar 2025 16:54:15 -0500 Subject: [PATCH 1/3] feat: adding setting to OptionsStore --- src/shared/storage/OptionsStore.ts | 6 ++++++ src/views/components/settings/Settings.tsx | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/src/shared/storage/OptionsStore.ts b/src/shared/storage/OptionsStore.ts index ce45c9342..179ea4fac 100644 --- a/src/shared/storage/OptionsStore.ts +++ b/src/shared/storage/OptionsStore.ts @@ -18,6 +18,10 @@ export interface IOptionsStore { /** whether we should open the calendar in a new tab; default is to focus an existing calendar tab */ alwaysOpenCalendarInNewTab: boolean; + + /** whether animations should be reduced or not + */ + enableReducedMotion: boolean; } export const OptionsStore = createSyncStore({ @@ -26,6 +30,7 @@ export const OptionsStore = createSyncStore({ enableScrollToLoad: true, enableDataRefreshing: false, alwaysOpenCalendarInNewTab: false, + enableReducedMotion: false, }); /** @@ -40,6 +45,7 @@ export const initSettings = async () => enableScrollToLoad: await OptionsStore.get('enableScrollToLoad'), enableDataRefreshing: await OptionsStore.get('enableDataRefreshing'), alwaysOpenCalendarInNewTab: await OptionsStore.get('alwaysOpenCalendarInNewTab'), + enableReducedMotion: await OptionsStore.get('enableReducedMotion'), }) satisfies IOptionsStore; // Clothing retailer right diff --git a/src/views/components/settings/Settings.tsx b/src/views/components/settings/Settings.tsx index 0d756ea15..1ed8d3157 100644 --- a/src/views/components/settings/Settings.tsx +++ b/src/views/components/settings/Settings.tsx @@ -94,6 +94,7 @@ export default function Settings(): JSX.Element { const [loadAllCourses, setLoadAllCourses] = useState(false); const [_enableDataRefreshing, setEnableDataRefreshing] = useState(false); const [calendarNewTab, setCalendarNewTab] = useState(false); + const [reducedMotion, setReducedMotion] = useState(false); const showMigrationDialog = useMigrationDialog(); @@ -189,6 +190,10 @@ export default function Settings(): JSX.Element { // console.log('alwaysOpenCalendarInNewTab', newValue); }); + const l6 = OptionsStore.listen('enableReducedMotion', async ({ newValue }) => { + setReducedMotion(newValue); + }); + // Remove listeners when the component is unmounted return () => { OptionsStore.removeListener(l1); @@ -196,6 +201,7 @@ export default function Settings(): JSX.Element { OptionsStore.removeListener(l3); OptionsStore.removeListener(l4); OptionsStore.removeListener(l5); + OptionsStore.removeListener(l6); DevStore.removeListener(ds_l1); From 18d8ccbbf8daf61a20b2685b7e25b8328872a134 Mon Sep 17 00:00:00 2001 From: Derek Chen Date: Fri, 21 Mar 2025 17:08:06 -0500 Subject: [PATCH 2/3] feat: settings page --- src/views/components/settings/Settings.tsx | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/views/components/settings/Settings.tsx b/src/views/components/settings/Settings.tsx index 1ed8d3157..44eff5ab3 100644 --- a/src/views/components/settings/Settings.tsx +++ b/src/views/components/settings/Settings.tsx @@ -493,6 +493,24 @@ export default function Settings(): JSX.Element { /> +
+
+ + Reduced Motion + +

+ Disable animations and transitions for users who prefer reduced motion. +

+
+ { + setReducedMotion(!reducedMotion); + OptionsStore.set('enableReducedMotion', !reducedMotion); + }} + /> +
+
From 3daca68615d0d6f8027ec2d24b127f284fae727c Mon Sep 17 00:00:00 2001 From: Derek Chen Date: Sun, 15 Jun 2025 19:19:05 -0500 Subject: [PATCH 3/3] feat: dialog motion reduced --- src/views/components/common/Dialog.tsx | 33 ++++++++++++++++--- .../common/DialogProvider/DialogProvider.tsx | 2 ++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/views/components/common/Dialog.tsx b/src/views/components/common/Dialog.tsx index c0490e91a..cee83dc90 100644 --- a/src/views/components/common/Dialog.tsx +++ b/src/views/components/common/Dialog.tsx @@ -12,6 +12,9 @@ import type { PropsWithChildren } from 'react'; import React, { Fragment } from 'react'; import ExtensionRoot from './ExtensionRoot/ExtensionRoot'; +import { useEffect } from 'react'; +import { useState } from 'react'; +import { OptionsStore } from 'src/shared/storage/OptionsStore'; /** * Represents the props for the _Dialog component @@ -32,16 +35,30 @@ export type DialogProps = _DialogProps & Omit): JSX.Element { const { children, className, open, title, description, ...rest } = props; + const [reducedMotion, setReducedMotion] = useState(false); + + useEffect(() => { + OptionsStore.get('enableReducedMotion').then(val => { + setReducedMotion(val); + }); + const listener = OptionsStore.listen('enableReducedMotion', ({ newValue }) => { + setReducedMotion(newValue); + }); + }, []); return ( @@ -50,10 +67,18 @@ export default function Dialog(props: PropsWithChildren): JSX.Eleme
diff --git a/src/views/components/common/DialogProvider/DialogProvider.tsx b/src/views/components/common/DialogProvider/DialogProvider.tsx index 8f23d609f..b5189e70a 100644 --- a/src/views/components/common/DialogProvider/DialogProvider.tsx +++ b/src/views/components/common/DialogProvider/DialogProvider.tsx @@ -5,6 +5,8 @@ import React, { useCallback, useRef, useState } from 'react'; import Dialog from '../Dialog'; import Text from '../Text/Text'; +import { useEffect } from 'react'; +import { OptionsStore } from 'src/shared/storage/OptionsStore'; type DialogElement = (show: boolean) => ReactNode;