You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
63 lines
2.2 KiB
TypeScript
63 lines
2.2 KiB
TypeScript
// frontend/components/settings/AppearanceTab.tsx — 테마(라이트/다크) — next-themes 실제 적용
|
|
"use client";
|
|
import { useEffect, useState } from "react";
|
|
import { useTheme } from "next-themes";
|
|
import { Icon } from "@/components/Icon";
|
|
import type { ToastFn } from "./SettingsClient";
|
|
|
|
const THEMES = [
|
|
{ id: "light", label: "라이트", icon: "sun" as const, desc: "밝은 글래스" },
|
|
{ id: "dark", label: "다크", icon: "moon" as const, desc: "어두운 글래스" },
|
|
];
|
|
|
|
export function AppearanceTab({ toast }: { toast: ToastFn }) {
|
|
const { theme, resolvedTheme, setTheme } = useTheme();
|
|
const [mounted, setMounted] = useState(false);
|
|
useEffect(() => setMounted(true), []);
|
|
|
|
const current = mounted ? (resolvedTheme ?? theme ?? "light") : "light";
|
|
|
|
const pick = (id: string) => {
|
|
setTheme(id);
|
|
toast(`${id === "dark" ? "다크" : "라이트"} 테마로 바꿨어요`, "blue");
|
|
};
|
|
|
|
return (
|
|
<section className="set-sec" aria-label="외관">
|
|
<header className="set-sechead">
|
|
<h2>외관</h2>
|
|
<p>테마는 이 브라우저에 저장돼요.</p>
|
|
</header>
|
|
|
|
<div className="set-card">
|
|
<div className="set-field">
|
|
<label>테마</label>
|
|
<div className="set-themes" role="radiogroup" aria-label="테마 선택">
|
|
{THEMES.map((t) => (
|
|
<button
|
|
key={t.id}
|
|
type="button"
|
|
role="radio"
|
|
aria-checked={current === t.id}
|
|
className={"set-theme th-" + t.id + (current === t.id ? " on" : "")}
|
|
onClick={() => pick(t.id)}
|
|
>
|
|
<span className="th-preview" aria-hidden>
|
|
<i className="th-bar" />
|
|
<i className="th-dot" />
|
|
</span>
|
|
<span className="th-label">
|
|
<Icon name={t.icon} />
|
|
<b>{t.label}</b>
|
|
<small>{t.desc}</small>
|
|
</span>
|
|
{current === t.id && <span className="th-check" aria-hidden><Icon name="tick" /></span>}
|
|
</button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|