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 Theme from "./ThemeSetting";
import ThemeSetting from "./ThemeSetting";
import { useTheme } from "../../context/ThemeContext";
import { useQuickSettings } from "../../context/QuickSettingsContext";
const QuickSettings: React.FC = () => {
const { theme } = useTheme();
const { showQuickSettings } = useQuickSettings();
return (
<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)" }}
>
<h3 className="text-xl">Current Theme: {theme}</h3>
<Theme />
<h1 className="text-[2rem] font-black">Quick Settings</h1>
<div id="quick-settings-menu" className="flex flex-col flex-grow my-8 gap-4">
<ThemeSetting />
</div>
</div>
);
};

View File

@@ -1,19 +1,52 @@
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";
const themeIcons = {
light: <SunIcon size={27} className="text-yellow-400" />,
dark: <MoonIcon size={27} className="text-white" />,
blue: <BlueIcon size={27} className="text-blue-500" />,
green: <GreenIcon size={27} className="text-green-500" />,
orange: <OrangeIcon size={27} className="text-orange-500" />,
};
const themeConfig = {
light: {
icon: Sun,
color: "text-yellow-400",
background: "bg-white",
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 { theme, setTheme } = useTheme();
const { theme, setTheme } = useTheme() as {
theme: keyof typeof themeConfig;
setTheme: (theme: keyof typeof themeConfig) => void;
};
const handleNextTheme = () => {
const currentIndex = themes.indexOf(theme);
@@ -23,22 +56,34 @@ const ThemeSetting: React.FC = () => {
document.body.setAttribute("data-theme", nextTheme);
};
const currentTheme = themeConfig[theme as keyof typeof themeConfig];
const Icon = currentTheme.icon;
return (
<button
onClick={handleNextTheme}
className="p-2 text-[1.5rem] flex items-center gap-2 rounded-md border transition-all"
>
{themeIcons[theme as keyof typeof themeIcons]} {theme}
<div className="flex flex-row gap-4">
<h3 className="text-xl flex-grow">Current Theme: </h3>
<button
onClick={handleNextTheme}
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>
</div>
);
};
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;
}