feat(arayüz): Tailwind + shadcn/ui tasarım sistemi, tema ve biçimlendirme

- Tailwind v4 + shadcn/ui (Radix), Inter yazı tipi (yerel)
- Tasarım token'ları: 4 ana grup (renk körlüğüne uygun) ve durum renkleri, WCAG AA
- Aydınlık / Karanlık / Sistem teması (ilk açılışta parlama yok)
- lib/format.ts: para (1.250,00 ₺), miktar, yüzde, tarih (GG.AA.YYYY), tutar ayrıştırma
- Vitest: 22 biçimlendirme testi; npm test artık frontend'i de çalıştırır
- Butonlar mobil dokunma alanına (≥44 px) göre büyütüldü

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-12 00:06:27 +03:00
parent 6eb5440d4d
commit 440523b176
22 changed files with 6051 additions and 115 deletions
+38
View File
@@ -0,0 +1,38 @@
import { Monitor, Moon, Sun } from 'lucide-react'
import { cn } from '@/lib/utils'
import { useTheme, type Theme } from '@/lib/theme'
const OPTIONS: { value: Theme; label: string; icon: typeof Sun }[] = [
{ value: 'light', label: 'Aydınlık', icon: Sun },
{ value: 'dark', label: 'Karanlık', icon: Moon },
{ value: 'system', label: 'Sistem', icon: Monitor },
]
/** Aydınlık / Karanlık / Sistem seçici (radyo grubu gibi davranır, klavyeyle gezilebilir). */
export function ThemeToggle({ className }: { className?: string }) {
const { theme, setTheme } = useTheme()
return (
<div
role="radiogroup"
aria-label="Tema"
className={cn('inline-flex rounded-lg border bg-muted p-1', className)}
>
{OPTIONS.map(({ value, label, icon: Icon }) => (
<button
key={value}
type="button"
role="radio"
aria-checked={theme === value}
onClick={() => setTheme(value)}
className={cn(
'inline-flex min-h-11 min-w-11 items-center justify-center gap-2 rounded-md px-3 text-sm font-medium text-muted-foreground transition-colors',
theme === value && 'bg-background text-foreground shadow-sm',
)}
>
<Icon className="size-4" aria-hidden />
<span>{label}</span>
</button>
))}
</div>
)
}