feat(tema): D kısayolu, logodan yayılan tema geçişi, /surum-notlari beta sayfası (→ 1.1.0)

- lib/tema-gecisi.ts: View Transitions + CSS maskesi (kolay-tercih-mark.svg),
  merkez header'daki işaret; reduced-motion ve desteksiz tarayıcıda düz geçiş
- tema-kisayolu.tsx: D tuşu açık ↔ koyu (yazı alanı/değiştirici tuşta pasif)
- tema-secici.tsx: seçim de maskeyle oynar, altında Kbd ile D ipucu
- /surum-notlari: beta açıklaması, geri bildirim (destek@kolaytercih.com),
  sürüm günlüğü; Beta rozeti ve footer buraya bağlanır, sitemap'e eklendi
- DESIGN.md §2.3 notu

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-07 23:25:38 +03:00
parent b2bab50337
commit 5f7ea8bbcd
13 changed files with 395 additions and 42 deletions

View File

@@ -0,0 +1,38 @@
"use client";
import { useEffect } from "react";
import { useTheme } from "next-themes";
import { temayiGecisle } from "@/lib/tema-gecisi";
/** Tuş yazı alanında basıldıysa kısayol değildir. */
function yaziAlanindaMi(hedef: EventTarget | null) {
if (!(hedef instanceof HTMLElement)) return false;
if (hedef.isContentEditable) return true;
const etiket = hedef.tagName;
return etiket === "INPUT" || etiket === "TEXTAREA" || etiket === "SELECT";
}
/**
* Klavye kısayolu: `D` açık ↔ koyu temayı değiştirir (ipucu footer'daki
* TemaSecici'nin altında, Kbd ile). Değiştirici tuşla (⌘/Ctrl/Alt) ya da yazı
* alanındayken çalışmaz; "sistem" seçiliyken o anki çözümlenmiş temanın
* tersine, açık bir seçime geçer. Geçiş logodan yayılan maskeyle oynar.
*/
export function TemaKisayolu() {
const { resolvedTheme, setTheme } = useTheme();
useEffect(() => {
const dinle = (e: KeyboardEvent) => {
if (e.key !== "d" && e.key !== "D") return;
if (e.metaKey || e.ctrlKey || e.altKey || e.repeat) return;
if (yaziAlanindaMi(e.target)) return;
e.preventDefault();
const hedef = resolvedTheme === "dark" ? "light" : "dark";
temayiGecisle(() => setTheme(hedef));
};
window.addEventListener("keydown", dinle);
return () => window.removeEventListener("keydown", dinle);
}, [resolvedTheme, setTheme]);
return null;
}