Skip to content

Commit 4629c6c

Browse files
committed
feat: mirror mode.
1 parent d76d066 commit 4629c6c

File tree

6 files changed

+105
-49
lines changed

6 files changed

+105
-49
lines changed

src/components/CommandPalette.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ const CommandPalette = ({isOpen, setIsOpen, openGenericModal, toggleDigitalRain}
5252
const {
5353
isInverted, toggleInvert,
5454
isRetro, toggleRetro,
55-
isParty, toggleParty
55+
isParty, toggleParty,
56+
isMirror, toggleMirror
5657
} = useVisualSettings();
57-
5858
const filteredItems = filterItems(items, searchTerm);
5959

6060
useEffect(() => {
@@ -187,6 +187,14 @@ const CommandPalette = ({isOpen, setIsOpen, openGenericModal, toggleDigitalRain}
187187
duration: 2000
188188
});
189189
break;
190+
case 'toggleMirrorMode':
191+
toggleMirror();
192+
addToast({
193+
title: !isMirror ? 'Mirror Mode On' : 'Mirror Mode Off',
194+
message: !isMirror ? 'Through the looking glass...' : 'Reflections normalized.',
195+
duration: 2000
196+
});
197+
break;
190198
case 'showTime': {
191199
openGenericModal('Current Time', <LiveClock/>);
192200
break;

src/context/VisualSettingsContext.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const VisualSettingsProvider = ({children}) => {
1111
const [isInverted, setIsInverted] = usePersistentState('is-inverted', false);
1212
const [isRetro, setIsRetro] = usePersistentState('is-retro', false);
1313
const [isParty, setIsParty] = usePersistentState('is-party', false);
14+
const [isMirror, setIsMirror] = usePersistentState('is-mirror', false);
1415

1516
useEffect(() => {
1617
if (isInverted) {
@@ -19,7 +20,6 @@ export const VisualSettingsProvider = ({children}) => {
1920
document.body.classList.remove('invert-mode');
2021
}
2122
}, [isInverted]);
22-
2323
useEffect(() => {
2424
if (isRetro) {
2525
document.documentElement.classList.add('retro-mode');
@@ -36,12 +36,24 @@ export const VisualSettingsProvider = ({children}) => {
3636
}
3737
}, [isParty]);
3838

39+
useEffect(() => {
40+
if (isMirror) {
41+
document.documentElement.classList.add('mirror-mode');
42+
} else {
43+
document.documentElement.classList.remove('mirror-mode');
44+
}
45+
}, [isMirror]);
3946
const toggleInvert = () => setIsInverted(prev => !prev);
4047
const toggleRetro = () => setIsRetro(prev => !prev);
4148
const toggleParty = () => setIsParty(prev => !prev);
42-
43-
return (<VisualSettingsContext.Provider value={{
44-
isInverted, toggleInvert, isRetro, toggleRetro, isParty, toggleParty
49+
const toggleMirror = () => setIsMirror(prev => !prev);
50+
51+
return (
52+
<VisualSettingsContext.Provider value={{
53+
isInverted, toggleInvert,
54+
isRetro, toggleRetro,
55+
isParty, toggleParty,
56+
isMirror, toggleMirror
4557
}}>
4658
{children}
4759
</VisualSettingsContext.Provider>);

src/hooks/useSearchableData.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ const useSearchableData = () => {
107107
{ title: 'Toggle Invert Colors', type: 'command', commandId: 'toggleInvertColors' },
108108
{ title: 'Party Mode', type: 'command', commandId: 'partyMode' },
109109
{ title: 'Toggle Retro Mode', type: 'command', commandId: 'toggleRetroMode' },
110+
{ title: 'Toggle Mirror Mode', type: 'command', commandId: 'toggleMirrorMode' },
110111
];
111112

112113
setItems([...staticRoutes, ...customCommands, ...allPosts, ...allProjects, ...allLogs, ...allApps]);

src/index.css

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ body {
1515
font-style: normal !important;
1616
-webkit-font-smoothing: antialiased;
1717
-moz-osx-font-smoothing: grayscale;
18-
transition: filter 0.5s ease; /* Smooth transition for filters */
18+
transition: filter 0.5s ease, transform 0.5s ease; /* Smooth transition for filters and transforms */
1919
}
2020

2121
code {
@@ -275,3 +275,21 @@ html.retro-mode::before {
275275
html.retro-mode body {
276276
text-shadow: 1px 0 2px rgba(255,0,0,0.7), -1px 0 2px rgba(0,255,255,0.7);
277277
}
278+
279+
/* Mirror Mode */
280+
html.mirror-mode {
281+
transform: scaleX(-1);
282+
height: 100%;
283+
overflow: hidden;
284+
}
285+
286+
html.mirror-mode body {
287+
height: 100%;
288+
overflow: hidden;
289+
}
290+
291+
html.mirror-mode #root {
292+
height: 100%;
293+
overflow-y: auto;
294+
overflow-x: hidden;
295+
}

src/pages/CommandsPage.js

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const commandsData = [
5050
{ title: "Toggle Invert Colors", description: "Inverts all colors on the page. (Easter Egg)", color: "orange" },
5151
{ title: "Party Mode", description: "Cycles hue colors for a disco effect. (Easter Egg)", color: "amber" },
5252
{ title: "Toggle Retro Mode", description: "Enables a retro CRT scanline effect. (Easter Egg)", color: "yellow" },
53+
{ title: "Toggle Mirror Mode", description: "Mirrors the entire page horizontally. (Easter Egg)", color: "indigo" },
5354
]
5455
},
5556
{
@@ -64,6 +65,31 @@ const commandsData = [
6465
}
6566
];
6667

68+
const colorClasses = {
69+
red: { bg: 'bg-red-900', border: 'border-red-700', text: 'text-red-300' },
70+
orange: { bg: 'bg-orange-900', border: 'border-orange-700', text: 'text-orange-300' },
71+
amber: { bg: 'bg-amber-900', border: 'border-amber-700', text: 'text-amber-300' },
72+
yellow: { bg: 'bg-yellow-900', border: 'border-yellow-700', text: 'text-yellow-300' },
73+
lime: { bg: 'bg-lime-900', border: 'border-lime-700', text: 'text-lime-300' },
74+
green: { bg: 'bg-green-900', border: 'border-green-700', text: 'text-green-300' },
75+
emerald: { bg: 'bg-emerald-900', border: 'border-emerald-700', text: 'text-emerald-300' },
76+
teal: { bg: 'bg-teal-900', border: 'border-teal-700', text: 'text-teal-300' },
77+
cyan: { bg: 'bg-cyan-900', border: 'border-cyan-700', text: 'text-cyan-300' },
78+
sky: { bg: 'bg-sky-900', border: 'border-sky-700', text: 'text-sky-300' },
79+
blue: { bg: 'bg-blue-900', border: 'border-blue-700', text: 'text-blue-300' },
80+
indigo: { bg: 'bg-indigo-900', border: 'border-indigo-700', text: 'text-indigo-300' },
81+
violet: { bg: 'bg-violet-900', border: 'border-violet-700', text: 'text-violet-300' },
82+
purple: { bg: 'bg-purple-900', border: 'border-purple-700', text: 'text-purple-300' },
83+
fuchsia: { bg: 'bg-fuchsia-900', border: 'border-fuchsia-700', text: 'text-fuchsia-300' },
84+
pink: { bg: 'bg-pink-900', border: 'border-pink-700', text: 'text-pink-300' },
85+
rose: { bg: 'bg-rose-900', border: 'border-rose-700', text: 'text-rose-300' },
86+
slate: { bg: 'bg-slate-900', border: 'border-slate-700', text: 'text-slate-300' },
87+
gray: { bg: 'bg-gray-900', border: 'border-gray-700', text: 'text-gray-300' },
88+
zinc: { bg: 'bg-zinc-900', border: 'border-zinc-700', text: 'text-zinc-300' },
89+
neutral: { bg: 'bg-neutral-900', border: 'border-neutral-700', text: 'text-neutral-300' },
90+
stone: { bg: 'bg-stone-900', border: 'border-stone-700', text: 'text-stone-300' },
91+
};
92+
6793
function CommandsPage() {
6894
useSeo({
6995
title: 'All Commands | Fezcodex',
@@ -154,16 +180,19 @@ function CommandsPage() {
154180
<div key={catIndex} className="mb-8">
155181
<h2 className="text-2xl font-semibold text-gray-200 mb-4 border-b border-gray-700 pb-2 inline-block">{category.category}</h2>
156182
<div className="grid grid-cols-1 gap-4">
157-
{category.items.map((cmd, cmdIndex) => (
158-
<div
159-
key={cmdIndex}
160-
className={`bg-${cmd.color}-900 bg-opacity-30 border border-${cmd.color}-700 text-${cmd.color}-300 px-4 py-3 rounded relative`}
161-
role="alert"
162-
>
163-
<strong className="font-bold">{cmd.title}:</strong>
164-
<span className="block sm:inline ml-2">{cmd.description}</span>
165-
</div>
166-
))}
183+
{category.items.map((cmd, cmdIndex) => {
184+
const classes = colorClasses[cmd.color] || colorClasses.gray;
185+
return (
186+
<div
187+
key={cmdIndex}
188+
className={`${classes.bg} bg-opacity-30 border ${classes.border} ${classes.text} px-4 py-3 rounded relative`}
189+
role="alert"
190+
>
191+
<strong className="font-bold">{cmd.title}:</strong>
192+
<span className="block sm:inline ml-2">{cmd.description}</span>
193+
</div>
194+
);
195+
})}
167196
</div>
168197
</div>
169198
))}

src/pages/SettingsPage.js

Lines changed: 20 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import React from 'react';
22
import {Link} from 'react-router-dom';
3-
import {ArrowLeft, ArrowLeftIcon} from '@phosphor-icons/react';
3+
import {ArrowLeftIcon} from '@phosphor-icons/react';
44
import {useAnimation} from '../context/AnimationContext';
55
import {useVisualSettings} from '../context/VisualSettingsContext';
66
import colors from '../config/colors';
77
import CustomToggle from '../components/CustomToggle';
88
import useSeo from '../hooks/useSeo';
99
import {useToast} from '../hooks/useToast';
1010
import {
11-
KEY_SIDEBAR_STATE,
12-
KEY_APPS_COLLAPSED_CATEGORIES,
13-
remove as removeLocalStorageItem,
11+
KEY_SIDEBAR_STATE, KEY_APPS_COLLAPSED_CATEGORIES, remove as removeLocalStorageItem,
1412
} from '../utils/LocalStorageManager';
1513

1614
const SettingsPage = () => {
@@ -38,14 +36,13 @@ const SettingsPage = () => {
3836
const {
3937
isInverted, toggleInvert,
4038
isRetro, toggleRetro,
41-
isParty, toggleParty
39+
isParty, toggleParty,
40+
isMirror, toggleMirror
4241
} = useVisualSettings();
4342

4443
const {addToast} = useToast();
45-
4644
const handleResetSidebarState = () => {
4745
removeLocalStorageItem(KEY_SIDEBAR_STATE);
48-
4946
addToast({
5047
title: 'Success',
5148
message: 'Sidebar state has been reset. The page will now reload.',
@@ -56,10 +53,8 @@ const SettingsPage = () => {
5653
window.location.reload();
5754
}, 3000);
5855
};
59-
6056
const handleResetAppsState = () => {
6157
removeLocalStorageItem(KEY_APPS_COLLAPSED_CATEGORIES);
62-
6358
addToast({
6459
title: 'Success',
6560
message: 'App categories state has been reset. The page will now reload.',
@@ -85,14 +80,9 @@ const SettingsPage = () => {
8580
<ArrowLeftIcon className="text-xl transition-transform group-hover:-translate-x-1"/> Back to Home
8681
</Link>
8782
<div className="mx-auto max-w-2xl text-center">
88-
<h1 className="text-4xl font-semibold tracking-tight text-white sm:text-6xl">
89-
Settings
90-
</h1>
91-
<p className="mt-6 text-lg leading-8 text-gray-300">
92-
Manage your application preferences.
93-
</p>
83+
<h1 className="text-4xl font-semibold tracking-tight text-white sm:text-6xl"> Settings </h1>
84+
<p className="mt-6 text-lg leading-8 text-gray-300"> Manage your application preferences. </p>
9485
</div>
95-
9686
<div className="flex justify-center items-center mt-16">
9787
<div
9888
className="group bg-transparent border rounded-lg shadow-2xl p-6 flex flex-col justify-between relative transform overflow-hidden h-full w-full max-w-4xl"
@@ -111,24 +101,19 @@ const SettingsPage = () => {
111101
Application Settings
112102
</h1>
113103
<hr className="border-gray-700 mb-4"/>
114-
115104
{/* Client-Side Notification */}
116105
<div
117106
className="bg-yellow-900 bg-opacity-30 border border-yellow-700 text-yellow-300 px-4 py-3 rounded relative mb-6"
118107
role="alert"
119108
>
120109
<strong className="font-bold">Client-Side Only:</strong>
121110
<span className="block sm:inline ml-2">
122-
Your preferences are stored locally in your browser. No data
123-
is sent to any server.
111+
Your preferences are stored locally in your browser. No data
112+
is sent to any server.
124113
</span>
125114
</div>
126-
127-
<h1 className="text-3xl font-arvo font-normal mb-4 text-app">
128-
Animation Settings
129-
</h1>
115+
<h1 className="text-3xl font-arvo font-normal mb-4 text-app"> Animation Settings </h1>
130116
<hr className="border-gray-700 mb-4"/>
131-
132117
<div className="mb-6 ml-4 mr-4">
133118
<CustomToggle
134119
id="enable-animations"
@@ -163,19 +148,17 @@ const SettingsPage = () => {
163148
>
164149
<strong className="font-bold">Animations Disabled:</strong>
165150
<span className="block sm:inline ml-2">
166-
Animation options are disabled because "Enable Animations"
167-
is off.
168-
</span>
151+
Animation options are disabled because "Enable Animations"
152+
is off.
153+
</span>
169154
</div>
170155
)}
171156
</div>
172-
173157
{/* Visual Effects Settings */}
174158
<h1 className="text-3xl font-arvo font-normal mb-4 text-app">
175159
Visual Effects
176160
</h1>
177161
<hr className="border-gray-700 mb-4"/>
178-
179162
<div className="mb-6 ml-4 mr-4">
180163
<CustomToggle
181164
id="enable-invert-colors"
@@ -197,8 +180,14 @@ const SettingsPage = () => {
197180
checked={isParty}
198181
onChange={toggleParty}
199182
/>
183+
<div className="mb-4"></div>
184+
<CustomToggle
185+
id="enable-mirror-mode"
186+
label="> Mirror Mode"
187+
checked={isMirror}
188+
onChange={toggleMirror}
189+
/>
200190
</div>
201-
202191
{/* Sidebar Stuff */}
203192
<h1 className="text-3xl font-arvo font-normal mb-4 text-app">
204193
Sidebar Settings
@@ -264,8 +253,7 @@ const SettingsPage = () => {
264253
</div>
265254
</div>
266255
</div>
267-
</div>
268-
);
256+
</div>);
269257
};
270258

271259
export default SettingsPage;

0 commit comments

Comments
 (0)