From b1d68ac307ed87d63e83820cbdf843fff0fd9f7f Mon Sep 17 00:00:00 2001 From: polwex Date: Thu, 11 Sep 2025 01:48:14 +0700 Subject: init --- front/src/styles/ThemeSwitcher.tsx | 131 +++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 front/src/styles/ThemeSwitcher.tsx (limited to 'front/src/styles/ThemeSwitcher.tsx') diff --git a/front/src/styles/ThemeSwitcher.tsx b/front/src/styles/ThemeSwitcher.tsx new file mode 100644 index 0000000..425bed9 --- /dev/null +++ b/front/src/styles/ThemeSwitcher.tsx @@ -0,0 +1,131 @@ +import React, { useState } from "react"; +import { useTheme, type ThemeName } from "../styles/ThemeProvider"; +import "./ThemeSwitcher.css"; + +interface ThemeSwitcherProps { + variant?: "dropdown" | "buttons" | "compact"; + showLabel?: boolean; +} + +const themeIcons: Record = { + light: "☀️", + dark: "🌙", + sepia: "📜", + noir: "⚫", + ocean: "🌊", + forest: "🌲", + gruvbox: "🍂", +}; + +const themeLabels: Record = { + light: "Light", + dark: "Dark", + sepia: "Sepia", + noir: "Noir", + ocean: "Ocean", + forest: "Forest", + gruvbox: "Gruvbox", +}; + +export const ThemeSwitcher: React.FC = ({ + variant = "dropdown", + showLabel = true, +}) => { + const { themeName, setTheme, availableThemes } = useTheme(); + const [isOpen, setIsOpen] = useState(false); + + const handleThemeChange = (theme: ThemeName) => { + setTheme(theme); + setIsOpen(false); + }; + + const cycleTheme = () => { + const currentIndex = availableThemes.indexOf(themeName); + const nextIndex = (currentIndex + 1) % availableThemes.length; + setTheme(availableThemes[nextIndex]); + }; + + if (variant === "compact") { + return ( + + ); + } + + if (variant === "buttons") { + return ( +
+ {showLabel && Theme:} +
+ {availableThemes.map((theme) => ( + + ))} +
+
+ ); + } + + // Default dropdown variant + return ( +
+ + + {isOpen && ( + <> +
setIsOpen(false)} + aria-hidden="true" + /> +
+ {availableThemes.map((theme) => ( + + ))} +
+ + )} +
+ ); +}; -- cgit v1.2.3