Files
kolaytercih/src/lib/tema-gecisi.ts
bilalgursen 5f7ea8bbcd 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>
2026-10-07 23:25:38 +03:00

57 lines
2.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Tema geçişi (DESIGN.md §2.3): açık ↔ koyu değişimi ekranı bir anda
// çevirmez; yeni tema, header'daki KolayTercih işaretinin biçiminde logodan
// başlayıp büyüyerek ekrana yayılır (View Transitions API + CSS maskesi,
// globals.css `.kt-tema-gecis`). Tarayıcı View Transitions bilmiyorsa ya da
// kullanıcı hareketi azaltmışsa tema düz değişir.
/** Header'daki işaretin kök elemanı (site-header.tsx, AnimasyonluMark). */
export const TEMA_ODAK_ID = "kt-tema-odak";
/** Geçiş sırasında <html>'de duran sınıf ve maskenin merkez değişkenleri. */
const GECIS_SINIFI = "kt-tema-gecis";
let suruyor = false;
/**
* `uygula` temayı değiştiren çağrıdır (ör. `setTheme("dark")`). Geçiş
* destekleniyorsa yeni tema işaretin bulunduğu noktadan maskeyle açılır;
* işaret ekranda değilse (krom gizli sayfalar) sol üst köşeden açılır.
*/
export function temayiGecisle(uygula: () => void) {
if (typeof document === "undefined") {
uygula();
return;
}
const azHareket = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (!document.startViewTransition || azHareket || suruyor) {
uygula();
return;
}
const odak = document.getElementById(TEMA_ODAK_ID)?.getBoundingClientRect();
const kok = document.documentElement;
const x = odak && odak.width > 0 ? odak.left + odak.width / 2 : 40;
const y = odak && odak.height > 0 ? odak.top + odak.height / 2 : 48;
// Maske merkezden ekranın en uzak köşesine kadar büyümeli.
const uzak = Math.hypot(
Math.max(x, window.innerWidth - x),
Math.max(y, window.innerHeight - y),
);
kok.style.setProperty("--kt-tema-x", `${x}px`);
kok.style.setProperty("--kt-tema-y", `${y}px`);
// İşaretin görünür karesi viewBox'ın ~%67'si; kenar bu oranla çarpılır ki
// en büyük hâlde köşe karesi bile ekranı aşsın.
kok.style.setProperty("--kt-tema-son", `${Math.ceil(uzak * 3.4)}px`);
kok.classList.add(GECIS_SINIFI);
suruyor = true;
const gecis = document.startViewTransition(uygula);
gecis.finished
.catch(() => {})
.finally(() => {
kok.classList.remove(GECIS_SINIFI);
suruyor = false;
});
}