mirror of
https://github.com/Xevion/rdap.git
synced 2025-12-05 21:15:57 -06:00
refactor: simplify ThemeToggle with config-driven approach
Replace imperative theme toggling logic with declarative THEME_CONFIG object for cleaner, more maintainable code. Add type safety with Theme type and isTheme type guard.
This commit is contained in:
@@ -17,6 +17,8 @@ export default [
|
||||
// Base configuration with ignores
|
||||
{
|
||||
ignores: [
|
||||
".media/**",
|
||||
"coverage/**",
|
||||
".next/**",
|
||||
"node_modules/**",
|
||||
"out/**",
|
||||
|
||||
@@ -3,7 +3,21 @@
|
||||
import { useTheme } from "next-themes";
|
||||
import { IconButton } from "@radix-ui/themes";
|
||||
import { MoonIcon, SunIcon, DesktopIcon } from "@radix-ui/react-icons";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, type ReactElement } from "react";
|
||||
|
||||
type Theme = "light" | "dark" | "system";
|
||||
|
||||
const ICON_SIZE = 22;
|
||||
|
||||
const THEME_CONFIG: Record<Theme, { icon: ReactElement; next: Theme }> = {
|
||||
light: { icon: <SunIcon width={ICON_SIZE} height={ICON_SIZE} />, next: "dark" },
|
||||
dark: { icon: <MoonIcon width={ICON_SIZE} height={ICON_SIZE} />, next: "system" },
|
||||
system: { icon: <DesktopIcon width={ICON_SIZE} height={ICON_SIZE} />, next: "light" },
|
||||
};
|
||||
|
||||
const isTheme = (value: string | undefined): value is Theme => {
|
||||
return value === "light" || value === "dark" || value === "system";
|
||||
};
|
||||
|
||||
export const ThemeToggle = () => {
|
||||
const { theme, setTheme } = useTheme();
|
||||
@@ -18,44 +32,16 @@ export const ThemeToggle = () => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentTheme: Theme = isTheme(theme) ? theme : "system";
|
||||
const { icon, next } = THEME_CONFIG[currentTheme];
|
||||
|
||||
const toggleTheme = () => {
|
||||
if (theme === "light") {
|
||||
setTheme("dark");
|
||||
} else if (theme === "dark") {
|
||||
setTheme("system");
|
||||
} else {
|
||||
setTheme("light");
|
||||
}
|
||||
setTheme(next);
|
||||
};
|
||||
|
||||
const getNextTheme = () => {
|
||||
if (theme === "light") return "dark";
|
||||
if (theme === "dark") return "system";
|
||||
return "light";
|
||||
};
|
||||
|
||||
const getIcon = () => {
|
||||
if (theme === "light") {
|
||||
return <SunIcon width="22" height="22" />;
|
||||
} else if (theme === "dark") {
|
||||
return <MoonIcon width="22" height="22" />;
|
||||
} else {
|
||||
return <DesktopIcon width="22" height="22" />;
|
||||
}
|
||||
};
|
||||
|
||||
const nextTheme = getNextTheme();
|
||||
const themeLabel = theme === "system" ? "system" : theme === "light" ? "light" : "dark";
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
size="3"
|
||||
variant="ghost"
|
||||
onClick={toggleTheme}
|
||||
aria-label="Toggle theme"
|
||||
title={`Current: ${themeLabel} mode. Click to switch to ${nextTheme} mode`}
|
||||
>
|
||||
{getIcon()}
|
||||
<IconButton size="3" variant="ghost" onClick={toggleTheme} aria-label="Toggle theme">
|
||||
{icon}
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user