feat(tema): açık / koyu / sistem teması
All checks were successful
Deploy / deploy (push) Successful in 6m23s
All checks were successful
Deploy / deploy (push) Successful in 6m23s
- TemaSaglayici (next-themes) + alt bilgide TemaSecici - globals.css: .dark bloğunda palet token'ları çevrilir; bileşenlere dark: sınıfı yazılmaz - yüzeyler bg-white → bg-card, koyu haplar text-slate-50, SVG'lerde sabit renk yerine değişken - DESIGN.md §2.3 + tasarim-denetim kuralları (yuzey-beyaz, koyu-hap-beyaz-yazi, dark-sinif), AGENTS.md karanlık mod bölümü - docs: koyu tema denetimi raporu Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
61
src/components/tema-secici.tsx
Normal file
61
src/components/tema-secici.tsx
Normal file
@@ -0,0 +1,61 @@
|
||||
"use client";
|
||||
|
||||
import { useSyncExternalStore } from "react";
|
||||
import { useTheme } from "next-themes";
|
||||
import { Monitor, Moon, Sun } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const SECENEKLER = [
|
||||
{ deger: "light", etiket: "Açık", ikon: Sun },
|
||||
{ deger: "dark", etiket: "Koyu", ikon: Moon },
|
||||
{ deger: "system", etiket: "Sistem", ikon: Monitor },
|
||||
] as const;
|
||||
|
||||
const aboneOlma = () => () => {};
|
||||
|
||||
/**
|
||||
* Tema seçici: açık / koyu / sistem (DESIGN.md §2.3). Seçili tema yalnızca
|
||||
* tarayıcıda bilinir; sunucu HTML'inde hiçbir seçenek işaretli gelmez,
|
||||
* hydration sonrası işaretlenir (yerleşim oynamaz).
|
||||
*/
|
||||
export function TemaSecici({ className }: { className?: string }) {
|
||||
const { theme, setTheme } = useTheme();
|
||||
const tarayicida = useSyncExternalStore(
|
||||
aboneOlma,
|
||||
() => true,
|
||||
() => false,
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
role="radiogroup"
|
||||
aria-label="Tema"
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 rounded-full border border-slate-200 bg-card p-1",
|
||||
className,
|
||||
)}
|
||||
>
|
||||
{SECENEKLER.map(({ deger, etiket, ikon: Ikon }) => {
|
||||
const secili = tarayicida && theme === deger;
|
||||
return (
|
||||
<button
|
||||
key={deger}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={secili}
|
||||
onClick={() => setTheme(deger)}
|
||||
className={cn(
|
||||
"inline-flex h-9 cursor-pointer items-center gap-1.5 rounded-full px-3 text-sm font-semibold transition-[background-color,color,transform] duration-150 outline-none focus-visible:ring-3 focus-visible:ring-ring/50 active:scale-[0.97]",
|
||||
secili
|
||||
? "bg-slate-900 text-slate-50"
|
||||
: "text-slate-600 hover:text-orange-500",
|
||||
)}
|
||||
>
|
||||
<Ikon className="size-4" aria-hidden />
|
||||
{etiket}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user