FEAT: Implement quick settings context;

UPDATE: Enhance quick settings UI & theme settings;
This commit is contained in:
Chris-1010
2025-02-18 00:49:18 +00:00
parent fde7c70b54
commit ef1921c207
3 changed files with 111 additions and 28 deletions

View File

@@ -1,17 +1,23 @@
import React from "react"; import React from "react";
import Theme from "./ThemeSetting"; import ThemeSetting from "./ThemeSetting";
import { useTheme } from "../../context/ThemeContext"; import { useTheme } from "../../context/ThemeContext";
import { useQuickSettings } from "../../context/QuickSettingsContext";
const QuickSettings: React.FC = () => { const QuickSettings: React.FC = () => {
const { theme } = useTheme(); const { theme } = useTheme();
const { showQuickSettings } = useQuickSettings();
return ( return (
<div <div
className="fixed top-0 right-0 w-[250px] h-screen p-4 z-[90] overflow-y-auto" className={`fixed top-0 right-0 w-[20vw] h-screen p-4 flex flex-col items-center overflow-y-auto ${
showQuickSettings ? "opacity-100 z-[90]" : "opacity-0 z-[-1]"
} transition-all duration-300 ease-in-out`}
style={{ backgroundColor: "var(--bg-color)", color: "var(--text-color)" }} style={{ backgroundColor: "var(--bg-color)", color: "var(--text-color)" }}
> >
<h3 className="text-xl">Current Theme: {theme}</h3> <h1 className="text-[2rem] font-black">Quick Settings</h1>
<Theme /> <div id="quick-settings-menu" className="flex flex-col flex-grow my-8 gap-4">
<ThemeSetting />
</div>
</div> </div>
); );
}; };

View File

@@ -1,19 +1,52 @@
import React from "react"; import React from "react";
import { Sun as SunIcon, Moon as MoonIcon, Droplet as BlueIcon, Leaf as GreenIcon, Flame as OrangeIcon } from "lucide-react"; import { Sun, Moon, Droplet, Leaf, Flame } from "lucide-react";
import { useTheme } from "../../context/ThemeContext"; import { useTheme } from "../../context/ThemeContext";
const themeIcons = { const themeConfig = {
light: <SunIcon size={27} className="text-yellow-400" />, light: {
dark: <MoonIcon size={27} className="text-white" />, icon: Sun,
blue: <BlueIcon size={27} className="text-blue-500" />, color: "text-yellow-400",
green: <GreenIcon size={27} className="text-green-500" />, background: "bg-white",
orange: <OrangeIcon size={27} className="text-orange-500" />, hoverBg: "hover:bg-gray-100",
}; label: "Light Theme",
},
dark: {
icon: Moon,
color: "text-white",
background: "bg-gray-800",
hoverBg: "hover:bg-gray-700",
label: "Dark Theme",
},
blue: {
icon: Droplet,
color: "text-blue-500",
background: "bg-blue-50",
hoverBg: "hover:bg-blue-100",
label: "Blue Theme",
},
green: {
icon: Leaf,
color: "text-green-500",
background: "bg-green-50",
hoverBg: "hover:bg-green-100",
label: "Green Theme",
},
orange: {
icon: Flame,
color: "text-orange-500",
background: "bg-orange-50",
hoverBg: "hover:bg-orange-100",
label: "Orange Theme",
},
} as const;
const themes = ["light", "dark", "blue", "green", "orange"]; const themes = Object.keys(themeConfig) as Array<keyof typeof themeConfig>;
const ThemeSetting: React.FC = () => { const ThemeSetting: React.FC = () => {
const { theme, setTheme } = useTheme(); const { theme, setTheme } = useTheme() as {
theme: keyof typeof themeConfig;
setTheme: (theme: keyof typeof themeConfig) => void;
};
const handleNextTheme = () => { const handleNextTheme = () => {
const currentIndex = themes.indexOf(theme); const currentIndex = themes.indexOf(theme);
@@ -23,22 +56,34 @@ const ThemeSetting: React.FC = () => {
document.body.setAttribute("data-theme", nextTheme); document.body.setAttribute("data-theme", nextTheme);
}; };
const currentTheme = themeConfig[theme as keyof typeof themeConfig];
const Icon = currentTheme.icon;
return ( return (
<button <div className="flex flex-row gap-4">
onClick={handleNextTheme} <h3 className="text-xl flex-grow">Current Theme: </h3>
className="p-2 text-[1.5rem] flex items-center gap-2 rounded-md border transition-all" <button
> onClick={handleNextTheme}
{themeIcons[theme as keyof typeof themeIcons]} {theme} className={`
group px-4 py-2 rounded-lg
w-[50%]
flex items-center gap-3
border border-gray-200
${currentTheme.background}
${currentTheme.hoverBg}
transition-all duration-200
focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500
`}
aria-label={`Switch theme. Current theme: ${currentTheme.label}`}
>
<Icon
size={24}
className={`${currentTheme.color} transition-transform group-hover:scale-110`}
/>
<span className="capitalize font-medium">{theme}</span>
</button> </button>
</div>
); );
}; };
export default ThemeSetting; export default ThemeSetting;
{/*
${isMode ?
`text-white bg-[#3478ef] hover:text-[#3478ef] hover:bg-[#000000]
border-[#3478ef] hover:border-[##3478ef]` :
`text-yellow-400 bg-white hover:text-yellow-400 hover:bg-white
border-yellow-400 hover:border-yellow-400`}
hover:border-b-4 hover:border-l-4 active:border-b-2 active:border-l-2 transition-all `} */}

View File

@@ -0,0 +1,32 @@
import { createContext, useContext, useState, ReactNode } from "react";
interface QuickSettingsContextType {
showQuickSettings: boolean;
setShowQuickSettings: (show: boolean) => void;
}
const QuickSettingsContext = createContext<
QuickSettingsContextType | undefined
>(undefined);
export function QuickSettingsProvider({ children }: { children: ReactNode }) {
const [showQuickSettings, setShowQuickSettings] = useState(false);
return (
<QuickSettingsContext.Provider
value={{ showQuickSettings, setShowQuickSettings }}
>
{children}
</QuickSettingsContext.Provider>
);
}
export function useQuickSettings() {
const context = useContext(QuickSettingsContext);
if (context === undefined) {
throw new Error(
"useQuickSettings must be used within a QuickSettingsProvider"
);
}
return context;
}