Skip to content

Commit 0f8b9de

Browse files
committed
feat: reduce motion
1 parent 4fad3cf commit 0f8b9de

File tree

7 files changed

+109
-176
lines changed

7 files changed

+109
-176
lines changed

src/App.jsx

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import ContactModal from './components/ContactModal';
88
import GenericModal from './components/GenericModal';
99
import DigitalRain from './components/DigitalRain';
1010
import BSOD from './components/BSOD';
11-
import { AnimationProvider } from './context/AnimationContext';
11+
import { AnimationProvider, useAnimation } from './context/AnimationContext';
1212
import { CommandPaletteProvider } from './context/CommandPaletteContext';
1313
import { VisualSettingsProvider } from './context/VisualSettingsContext';
1414
import { AchievementProvider } from './context/AchievementContext';
@@ -19,6 +19,16 @@ import { SiteConfigProvider } from './context/SiteConfigContext';
1919
import { CloudMusicProvider } from './context/CloudMusicContext';
2020
import { DndProvider } from './context/DndContext';
2121
import TinyCloudPlayer from './app/apps/CloudMusicPlayer/components/TinyCloudPlayer';
22+
import { MotionConfig } from 'framer-motion';
23+
24+
const MotionConfigWrapper = ({ children }) => {
25+
const { reduceMotion } = useAnimation();
26+
return (
27+
<MotionConfig reducedMotion={reduceMotion ? "always" : "never"}>
28+
{children}
29+
</MotionConfig>
30+
);
31+
};
2232

2333
function App() {
2434
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -57,49 +67,51 @@ function App() {
5767

5868
return (
5969
<AnimationProvider>
60-
<Router>
61-
<ToastProvider>
62-
<SiteConfigProvider>
63-
<CloudMusicProvider>
64-
<DndProvider>
65-
<AchievementProvider>
66-
<AchievementListeners />
67-
<HomepageOrderProvider>
68-
<VisualSettingsProvider>
69-
<DigitalRain isActive={isRainActive} />
70-
<BSOD isActive={isBSODActive} toggleBSOD={toggleBSOD} />
71-
<ScrollToTop />
72-
<TinyCloudPlayer />
73-
<CommandPaletteProvider>
74-
<SidePanelProvider>
75-
<Layout
76-
toggleModal={toggleModal}
77-
isSearchVisible={isSearchVisible}
78-
toggleSearch={toggleSearch}
79-
openGenericModal={openGenericModal}
80-
toggleDigitalRain={toggleDigitalRain}
81-
toggleBSOD={toggleBSOD}
82-
>
83-
<AnimatedRoutes />
84-
</Layout>
85-
</SidePanelProvider>
86-
</CommandPaletteProvider>
87-
<ContactModal isOpen={isModalOpen} onClose={toggleModal} />
88-
<GenericModal
89-
isOpen={isGenericModalOpen}
90-
onClose={closeGenericModal}
91-
title={genericModalContent.title}
92-
>
93-
{genericModalContent.content}
94-
</GenericModal>
95-
</VisualSettingsProvider>
96-
</HomepageOrderProvider>
97-
</AchievementProvider>
98-
</DndProvider>
99-
</CloudMusicProvider>
100-
</SiteConfigProvider>
101-
</ToastProvider>
102-
</Router>
70+
<MotionConfigWrapper>
71+
<Router>
72+
<ToastProvider>
73+
<SiteConfigProvider>
74+
<CloudMusicProvider>
75+
<DndProvider>
76+
<AchievementProvider>
77+
<AchievementListeners />
78+
<HomepageOrderProvider>
79+
<VisualSettingsProvider>
80+
<DigitalRain isActive={isRainActive} />
81+
<BSOD isActive={isBSODActive} toggleBSOD={toggleBSOD} />
82+
<ScrollToTop />
83+
<TinyCloudPlayer />
84+
<CommandPaletteProvider>
85+
<SidePanelProvider>
86+
<Layout
87+
toggleModal={toggleModal}
88+
isSearchVisible={isSearchVisible}
89+
toggleSearch={toggleSearch}
90+
openGenericModal={openGenericModal}
91+
toggleDigitalRain={toggleDigitalRain}
92+
toggleBSOD={toggleBSOD}
93+
>
94+
<AnimatedRoutes />
95+
</Layout>
96+
</SidePanelProvider>
97+
</CommandPaletteProvider>
98+
<ContactModal isOpen={isModalOpen} onClose={toggleModal} />
99+
<GenericModal
100+
isOpen={isGenericModalOpen}
101+
onClose={closeGenericModal}
102+
title={genericModalContent.title}
103+
>
104+
{genericModalContent.content}
105+
</GenericModal>
106+
</VisualSettingsProvider>
107+
</HomepageOrderProvider>
108+
</AchievementProvider>
109+
</DndProvider>
110+
</CloudMusicProvider>
111+
</SiteConfigProvider>
112+
</ToastProvider>
113+
</Router>
114+
</MotionConfigWrapper>
103115
</AnimationProvider>
104116
);
105117
}

src/context/AnimationContext.jsx

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,25 @@
11
import React, { createContext, useContext } from 'react';
22
import usePersistentState from '../hooks/usePersistentState';
3-
import {
4-
KEY_IS_ANIMATION_ENABLED,
5-
KEY_SHOW_ANIMATIONS_HOMEPAGE,
6-
KEY_SHOW_ANIMATIONS_INNER_PAGES,
7-
} from '../utils/LocalStorageManager';
83

94
const AnimationContext = createContext();
105

116
export const AnimationProvider = ({ children }) => {
12-
const [isAnimationEnabled, setIsAnimationEnabled] = usePersistentState(
13-
KEY_IS_ANIMATION_ENABLED,
14-
true,
7+
// We use the existing key but invert the logic mentally or rename it.
8+
// Let's use a new key for clarity: reduceMotion
9+
const [reduceMotion, setReduceMotion] = usePersistentState(
10+
'reduceMotion',
11+
false,
1512
);
1613

17-
const [showAnimationsHomepage, setShowAnimationsHomepage] =
18-
usePersistentState(KEY_SHOW_ANIMATIONS_HOMEPAGE, true);
19-
20-
const [showAnimationsInnerPages, setShowAnimationsInnerPages] =
21-
usePersistentState(KEY_SHOW_ANIMATIONS_INNER_PAGES, false);
22-
23-
const toggleAnimation = () => {
24-
setIsAnimationEnabled((prev) => !prev);
25-
};
26-
27-
const toggleShowAnimationsHomepage = () => {
28-
setShowAnimationsHomepage((prev) => !prev);
29-
};
30-
31-
const toggleShowAnimationsInnerPages = () => {
32-
setShowAnimationsInnerPages((prev) => !prev);
14+
const toggleReduceMotion = () => {
15+
setReduceMotion((prev) => !prev);
3316
};
3417

3518
return (
3619
<AnimationContext.Provider
3720
value={{
38-
isAnimationEnabled,
39-
toggleAnimation,
40-
showAnimationsHomepage,
41-
toggleShowAnimationsHomepage,
42-
showAnimationsInnerPages,
43-
toggleShowAnimationsInnerPages,
21+
reduceMotion,
22+
toggleReduceMotion,
4423
}}
4524
>
4625
{children}
@@ -50,4 +29,4 @@ export const AnimationProvider = ({ children }) => {
5029

5130
export const useAnimation = () => {
5231
return useContext(AnimationContext);
53-
};
32+
};

src/data/commands.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,8 @@ export const commands = [
134134
category: 'Visual Effects & Fun',
135135
items: [
136136
{
137-
title: 'Toggle Animations',
138-
description: 'Enable/Disable all animations in Fezcodex.',
137+
title: 'Toggle Reduced Motion',
138+
description: 'Reduce or disable all animations in Fezcodex.',
139139
color: 'slate',
140140
commandId: 'toggleAnimations',
141141
},

src/hooks/useCommandRegistry.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export const useCommandRegistry = ({
3737
items,
3838
}) => {
3939
const navigate = useNavigate();
40-
const { isAnimationEnabled, toggleAnimation } = useAnimation();
40+
const { reduceMotion, toggleReduceMotion } = useAnimation();
4141
const { addToast } = useToast();
4242
const { unlockAchievement } = useAchievements();
4343
const aboutData = useAboutData();
@@ -67,10 +67,10 @@ export const useCommandRegistry = ({
6767

6868
const commandHandlers = useMemo(() => ({
6969
toggleAnimations: () => {
70-
toggleAnimation();
70+
toggleReduceMotion();
7171
addToast({
7272
title: 'Settings Updated',
73-
message: `Animations have been ${!isAnimationEnabled ? 'enabled' : 'disabled'}.`,
73+
message: `Reduced Motion has been ${!reduceMotion ? 'enabled' : 'disabled'}.`,
7474
});
7575
},
7676
resetSidebarState: () => {
@@ -547,11 +547,11 @@ export const useCommandRegistry = ({
547547
},
548548
}), [
549549
addToast,
550-
isAnimationEnabled,
550+
reduceMotion,
551551
items,
552552
navigate,
553553
openGenericModal,
554-
toggleAnimation,
554+
toggleReduceMotion,
555555
unlockAchievement,
556556
toggleDigitalRain,
557557
aboutData,

src/hooks/useSearchableData.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ const useSearchableData = () => {
152152
commandId: 'randomPost',
153153
},
154154
{
155-
title: 'Toggle Animations',
155+
title: 'Toggle Reduced Motion',
156156
type: 'command',
157157
commandId: 'toggleAnimations',
158158
},

src/pages/brutalist-views/BrutalistSettingsPage.jsx

Lines changed: 16 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { useEffect } from 'react';
22
import { Link, useLocation } from 'react-router-dom';
3-
import { motion, AnimatePresence } from 'framer-motion';
3+
import { motion } from 'framer-motion';
44
import {
55
ArrowLeftIcon,
66
TrophyIcon,
@@ -76,12 +76,8 @@ const SettingsPage = () => {
7676
}, [unlockAchievement]);
7777

7878
const {
79-
isAnimationEnabled,
80-
toggleAnimation,
81-
showAnimationsHomepage,
82-
toggleShowAnimationsHomepage,
83-
showAnimationsInnerPages,
84-
toggleShowAnimationsInnerPages,
79+
reduceMotion,
80+
toggleReduceMotion,
8581
} = useAnimation();
8682

8783
const {
@@ -427,54 +423,23 @@ const SettingsPage = () => {
427423
>
428424
<div className="space-y-8">
429425
<div className="p-6 border border-white/5 bg-white/[0.01] rounded-sm">
430-
<div className="flex items-center justify-between mb-8 pb-8 border-b border-white/5">
431-
<h3 className="text-lg font-bold text-white">
432-
Global Animations
433-
</h3>
426+
<div className="flex items-center justify-between">
427+
<div>
428+
<h3 className="text-lg font-bold text-white mb-1">
429+
Reduce Motion
430+
</h3>
431+
<p className="text-sm text-gray-500 max-w-md">
432+
Disables all Framer Motion animations across the application for a faster, more stable experience.
433+
</p>
434+
</div>
434435
<CustomToggle
435-
id="enable-animations"
436-
label={isAnimationEnabled ? 'Enabled' : 'Disabled'}
437-
checked={isAnimationEnabled}
438-
onChange={toggleAnimation}
436+
id="reduce-motion"
437+
label={reduceMotion ? 'Enabled' : 'Disabled'}
438+
checked={reduceMotion}
439+
onChange={toggleReduceMotion}
439440
fontClass="font-outfit"
440441
/>
441442
</div>
442-
443-
<AnimatePresence>
444-
{isAnimationEnabled && (
445-
<motion.div
446-
initial={{ height: 0, opacity: 0 }}
447-
animate={{ height: 'auto', opacity: 1 }}
448-
exit={{ height: 0, opacity: 0 }}
449-
className="grid grid-cols-1 md:grid-cols-2 gap-8 overflow-hidden"
450-
>
451-
<CustomToggle
452-
id="show-animations-homepage"
453-
label="Homepage Motion"
454-
checked={showAnimationsHomepage}
455-
onChange={toggleShowAnimationsHomepage}
456-
fontClass="font-outfit"
457-
/>
458-
<CustomToggle
459-
id="show-animations-inner-pages"
460-
label="Interior Page Motion"
461-
checked={showAnimationsInnerPages}
462-
onChange={toggleShowAnimationsInnerPages}
463-
fontClass="font-outfit"
464-
/>
465-
</motion.div>
466-
)}
467-
</AnimatePresence>
468-
469-
{!isAnimationEnabled && (
470-
<div className="flex items-center gap-3 text-gray-500 font-mono text-[10px] uppercase tracking-widest">
471-
<WarningIcon size={16} />
472-
<span>
473-
Animation controls are disabled when global animations are
474-
off.
475-
</span>
476-
</div>
477-
)}
478443
</div>
479444
</div>
480445
</Section>

0 commit comments

Comments
 (0)