9–10 Ekim oturumlarının commit'lenmemiş işi tek parça alındı (raporlar: docs/ekip-raporlari/2026-10-09, 2026-10-10): - Landing deneyim dili 1. dalga: sayfa geçişi (ViewTransition), piksel morf/şerit, sorun sahneleri, adım akışı, sayan sayı, mobil menü, adım göstergesi, logoya tepki; DESIGN.md §11 ve AGENTS.md kuralları, tasarım denetimine yeni kurallar - Tema: tema ikonu, D kısayolu, tema geçişi - PWA: manifest.ts ve ikonlar - Danışman: revizyon niyet modeli (OPENROUTER_NIYET_MODEL), sohbet geçmişi, soru API'si - /listem ve /sonuc tadımlığı bileşen denetimi düzeltmeleri - eslint: .venv-tts/ yok sayılır tsc, eslint ve tasarım denetimi sıfır hata. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
101 lines
4.0 KiB
TypeScript
101 lines
4.0 KiB
TypeScript
// Tema geçişi (DESIGN.md §2.3): açık ↔ koyu değişimi ekranı bir anda
|
||
// çevirmez; yeni tema header'daki KolayTercih işaretinden yumuşak bir halka
|
||
// gibi açılır — kenarı keskin değil, geniş ve tüylü; ışık yayılır gibi.
|
||
// Geçiş kısa ve hafiftir; BİTİNCE logonun kareleri yeni temanın biçimine
|
||
// dönüşür (koyuya: ay ve yıldız; açığa: güneş), kısa bir an durur ve
|
||
// yeniden logoya toplanır.
|
||
// Markanın yumuşak, oyunsu diline uysun diye sert kenar, piksel ya da ikinci
|
||
// bir şekil yok (9 Eki 2026).
|
||
//
|
||
// Nasıl: View Transitions API eski/yeni görüntü çiftini verir; yeni görüntü
|
||
// radyal degrade maskesiyle açılır. Yarıçapı CSS sürer (globals.css
|
||
// `.kt-tema-gecis`), buradan yalnız merkez ve son yarıçap verilir. Tarayıcı
|
||
// View Transitions bilmiyorsa ya da hareket azaltılmışsa tema düz değişir.
|
||
|
||
/** Geçiş sırasında <html>'de duran sınıf (globals.css). */
|
||
const GECIS_SINIFI = "kt-tema-gecis";
|
||
|
||
/** Geçiş bitince pencereye atılan olay; header'daki logo bunu dinleyip
|
||
* karelerini güneşe ya da aya dönüştürür (animasyonlu-mark.tsx). */
|
||
export const TEMA_GECIS_OLAYI = "kt-tema-gecis";
|
||
|
||
// Maskenin tam opak çekirdeği yarıçapın bu oranında biter, kalanı tüydür
|
||
// (globals.css'teki --kt-tema-cekirdek ile aynı olmalı): son yarıçap, çekirdek
|
||
// en uzak köşeyi de örtecek kadar büyük seçilir.
|
||
const CEKIRDEK = 0.55;
|
||
|
||
/** Sayfa geçişi ile logo dönüşümü arasındaki kısa nefes (ms). */
|
||
const LOGO_NEFESI = 80;
|
||
|
||
let suruyor = false;
|
||
|
||
/**
|
||
* `uygula` temayı değiştiren çağrıdır (ör. `setTheme("dark")`). Geçiş
|
||
* sürerken gelen istek yok sayılır: art arda D'ye basınca ekrandaki görüntü
|
||
* ile tema durumu birbirine girmesin.
|
||
*/
|
||
export function temayiGecisle(uygula: () => void) {
|
||
if (typeof document === "undefined") {
|
||
uygula();
|
||
return;
|
||
}
|
||
const azHareket = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||
if (azHareket) {
|
||
uygula();
|
||
return;
|
||
}
|
||
if (!document.startViewTransition) {
|
||
// Sayfa geçişi yok ama logo yine dönüşür; temanın sınıfı <html>'e
|
||
// yazılsın diye kısa bir an beklenir.
|
||
uygula();
|
||
window.setTimeout(
|
||
() => window.dispatchEvent(new Event(TEMA_GECIS_OLAYI)),
|
||
LOGO_NEFESI,
|
||
);
|
||
return;
|
||
}
|
||
if (suruyor) return;
|
||
|
||
const kok = document.documentElement;
|
||
// Halkanın merkezi header'daki logo; krom gizli sayfalarda sol üst köşe.
|
||
const logo = document
|
||
.querySelector('header a[aria-label="KolayTercih"]')
|
||
?.getBoundingClientRect();
|
||
const gorunur = logo && logo.width > 0 && logo.bottom > 0;
|
||
const x = gorunur ? logo.left + logo.height / 2 : 24;
|
||
const y = gorunur ? logo.top + logo.height / 2 : 24;
|
||
const enUzak = 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`);
|
||
kok.style.setProperty("--kt-tema-son", `${Math.ceil(enUzak / CEKIRDEK)}px`);
|
||
kok.classList.add(GECIS_SINIFI);
|
||
suruyor = true;
|
||
|
||
const gecis = document.startViewTransition(uygula);
|
||
// Sekme gizliyken / yeniden boyutlanırken tarayıcı geçişi iptal eder:
|
||
// `ready` reddedilir, tema yine uygulanmıştır; konsola hata düşmesin.
|
||
gecis.ready.catch(() => {});
|
||
gecis.finished
|
||
.catch(() => {})
|
||
.finally(() => {
|
||
kok.classList.remove(GECIS_SINIFI);
|
||
kok.style.removeProperty("--kt-tema-x");
|
||
kok.style.removeProperty("--kt-tema-y");
|
||
kok.style.removeProperty("--kt-tema-son");
|
||
suruyor = false;
|
||
// Sıra: önce sayfa geçişi biter, sonra logo dönüşür — ikisi üst üste
|
||
// binmez, göz önce temaya sonra logoya gider. Kısa nefes (LOGO_NEFESI):
|
||
// geçiş iptal olduysa (sekme gizli vb.) `finished` hemen döner ve
|
||
// temanın sınıfı <html>'e henüz yazılmamış olabilir; logo yanlış
|
||
// biçime dönüşmesin.
|
||
window.setTimeout(
|
||
() => window.dispatchEvent(new Event(TEMA_GECIS_OLAYI)),
|
||
LOGO_NEFESI,
|
||
);
|
||
});
|
||
}
|