feat(tema): sayfa geçişi kısa ve hafif (600 ms), logo dönüşümü geçiş bitince oynar; DESIGN §4.22 logo morph

- Sıra: önce sayfa geçişi biter, kısa nefes (80 ms), sonra logo güneşe/aya
  dönüşür; üst üste binmez. Geçiş iptal olsa da logo doğru biçime dönüşür.
- View Transitions olmayan tarayıcıda da logo dönüşür.
- DESIGN.md §4.22: logo biçim dönüşümü tasarım diline eklendi (biçim tablosu,
  koreografi, kurallar); §6 hareket ve §7 Yap/Yapma satırları.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-10-09 00:48:41 +03:00
parent 49d88cd72f
commit 1b51903e71
4 changed files with 73 additions and 13 deletions

View File

@@ -483,7 +483,8 @@
değil: yarıçapın %55'ine kadar tam opak, oradan kenara doğru tüy gibi
söner (--kt-tema-cekirdek; JS'teki CEKIRDEK ile aynı olmalı) — ışık
yayılır gibi, sert çizgi yok. Yarıçap (--kt-tema-r) 0 → --kt-tema-son
yumuşak kalkıp yumuşak durur. Merkez ve son yarıçap JS'ten gelir.
yumuşak kalkıp yumuşak durur; kısa ve hafif (600 ms) — asıl gösteri,
geçiş bitince oynayan logo dönüşümüdür. Merkez ve son yarıçap JS'ten gelir.
Hareket azaltılmışsa JS geçişi hiç başlatmaz, tema düz değişir. */
@property --kt-tema-r {
syntax: "<length>";
@@ -509,7 +510,7 @@
#000 calc(var(--kt-tema-r) * var(--kt-tema-cekirdek)),
transparent var(--kt-tema-r)
);
animation: kt-tema-halka 1100ms cubic-bezier(0.45, 0, 0.2, 1) both;
animation: kt-tema-halka 600ms cubic-bezier(0.4, 0, 0.2, 1) both;
}
@keyframes kt-tema-halka {
from {

View File

@@ -103,7 +103,7 @@ function merkezde(cx: number, cy: number, boyut: number): string {
return `${((cx - boyut / 2) / boyut) * 100}% ${((cy - boyut / 2) / boyut) * 100}%`;
}
// Tema geçişi biçimi (DESIGN.md §2.3): geçiş logodan yayılırken kareler
// Tema geçişi biçimi (DESIGN.md §2.3): sayfa geçişi bitince kareler
// neye geçildiğini gösterir, kısa bir an durur ve yeniden logoya toplanır.
// - Koyuya: şeftali kare hilale, mavi kare hilalin kucağındaki yıldıza;
// turuncu söner.
@@ -404,7 +404,7 @@ export function AnimasyonluMark({
const cik = () => kontrolRef.current?.ayarla(null, true);
hoverHedefi.addEventListener("mouseenter", gir);
hoverHedefi.addEventListener("mouseleave", cik);
// Tema geçişi başlarken (lib/tema-gecisi.ts) kareler yeni temanın
// Tema geçişi bitince (lib/tema-gecisi.ts) kareler yeni temanın
// biçimine dönüşür: koyuya geçişte ay ve yıldızlar, açığa geçişte güneş.
// Olay anında <html> yeni temanın sınıfını taşır.
const temaGecti = () =>

View File

@@ -1,8 +1,9 @@
// 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.
// Aynı anda logonun kareleri yeni temanın biçimine dönüşür (koyuya: ay ve
// yıldızlar; açığa: güneş), kısa bir an durur ve yeniden logoya toplanır.
// 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).
//
@@ -14,7 +15,7 @@
/** Geçiş sırasında <html>'de duran sınıf (globals.css). */
const GECIS_SINIFI = "kt-tema-gecis";
/** Geçiş başlarken pencereye atılan olay; header'daki logo bunu dinleyip
/** 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";
@@ -23,6 +24,9 @@ export const TEMA_GECIS_OLAYI = "kt-tema-gecis";
// 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;
/**
@@ -36,10 +40,20 @@ export function temayiGecisle(uygula: () => void) {
return;
}
const azHareket = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
if (!document.startViewTransition || azHareket) {
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;
@@ -64,9 +78,7 @@ export function temayiGecisle(uygula: () => void) {
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
.then(() => window.dispatchEvent(new Event(TEMA_GECIS_OLAYI)))
.catch(() => {});
gecis.ready.catch(() => {});
gecis.finished
.catch(() => {})
.finally(() => {
@@ -75,5 +87,14 @@ export function temayiGecisle(uygula: () => void) {
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,
);
});
}