v1-beta-tema #9

Merged
bilal merged 19 commits from v1-beta-tema into main 2026-10-09 02:30:44 +03:00
4 changed files with 32 additions and 103 deletions
Showing only changes of commit 4c84a1a974 - Show all commits

View File

@@ -136,10 +136,11 @@ Seçici `src/components/tema-secici.tsx` (footer'da), sağlayıcı `src/componen
**Geçiş ve kısayol (7 Eki 2026):** tema değişimi anlık değildir; yeni tema **Geçiş ve kısayol (7 Eki 2026):** tema değişimi anlık değildir; yeni tema
KolayTercih işaretinin biçiminde önce ekranın altından ortaya süzülür, sonra KolayTercih işaretinin biçiminde önce ekranın altından ortaya süzülür, sonra
merkezden büyüyerek ekranı kaplar — büyüme boyunca logo normal, boşluklu merkezden büyüyerek ekranı kaplar — büyüme boyunca logo normal, boşluklu
hâliyle görünür; en büyük haline yaklaştıkça kareler arası boşluklar hâliyle görünür; büyümenin ikinci yarısında kareler arasında kalan eski
merkezden dışa doğru yumuşak biçimde kapanır (View Transitions + CSS görüntü tam ekran dolguyla yeni temaya solar. Ekranda tek silüet vardır,
ikinci bir şekil büyümez ("logo içinde logo" olmaz). (View Transitions + CSS
maskesi, maskeyi motion sürer: `src/lib/tema-gecisi.ts`, `globals.css` maskesi, maskeyi motion sürer: `src/lib/tema-gecisi.ts`, `globals.css`
`.kt-tema-gecis`; hareket azaltılmışsa düz değişir). `.kt-tema-gecis`; hareket azaltılmışsa düz değişir.)
`D` tuşu açık ↔ koyu geçişi yapar (`src/components/tema-kisayolu.tsx`); ipucu seçicinin `D` tuşu açık ↔ koyu geçişi yapar (`src/components/tema-kisayolu.tsx`); ipucu seçicinin
altında `Kbd` ile durur, başka yere kopyalanmaz. Header'daki Beta rozeti `/surum-notlari`na altında `Kbd` ile durur, başka yere kopyalanmaz. Header'daki Beta rozeti `/surum-notlari`na
bağlantıdır. bağlantıdır.

View File

@@ -1,15 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 180 180" role="img" aria-labelledby="title">
<title id="title">KolayTercih</title>
<!-- Tema geçişi maskesinin KAPANIŞ katmanı (globals.css .kt-tema-gecis):
büyüme boyunca normal çizim (kolay-tercih-mark.svg) boşluklu görünür;
en büyük hâle yaklaştıkça bu dolu çizim merkezden dışa büyür
(boy = --kt-tema-kenar × --kt-tema-kapanis) ve kareler arası boşlukları
kapatır. Dış sınırlar orijinalle aynı: x 27–147, y 29–151.
Sol kare sağ sütuna girer (27+77=104 > 91) ki birleşim yeri kaymasın;
sağ sütun iki kareyi birleştirir (dikey boşluk). --kt-tema-kapanis
tam 1 olduğunda siluet orijinalin tam katmanıdır; ara değerlerde
merkezden dışa büyür, boşlukların kapanışı kenarlara doğru yumuşak
olur. -->
<rect x="27" y="56" width="77" height="57" rx="13" fill="#000"/>
<rect x="91" y="29" width="56" height="122" rx="13" fill="#000"/>
</svg>

Before

Width:  |  Height:  |  Size: 1019 B

View File

@@ -478,22 +478,22 @@
} }
/* Tema geçişi (DESIGN.md §2.3, lib/tema-gecisi.ts): tema değişirken yeni /* Tema geçişi (DESIGN.md §2.3, lib/tema-gecisi.ts): tema değişirken yeni
görüntü, KolayTercih işaretinin biçiminde önce ekranın ALTINDAN ortaya görüntü, KolayTercih işaretinin biçiminde önce ekranın altından ortaya
süzülür, sonra merkezden büyüyerek ekranı kaplar. Eski görüntü yerinde süzülür, sonra merkezden büyüyerek ekranı kaplar. Eski görüntü yerinde
durur; yeni görüntünün maskesi üç katman (hepsi `add` ile toplanır, durur; yeni görüntünün maskesi iki katman (mask-composite varsayılanı
mask-composite varsayılanı add — bu yüzden sıralama yalnızca okunurluk add, toplanır):
içindir): (1) işaretin çizimi (kolay-tercih-mark.svg'nin gömülü kopyası — üç kare,
(1) işaretin NORMAL çizimi (kolay-tercih-mark.svg'nin gömülü kopyası — kareler arası boşluk aralarındaki boşlukla, logo logonun kendisi gibi durur), merkezi
görünür, logo logonun kendisi gibi durur), merkezi --kt-tema-x/y'de, --kt-tema-x/y'de, boyu --kt-tema-kenar;
boyu --kt-tema-kenar: uçuş ve büyüme boyunca bu görünür; (2) tam ekran dolgu, alfası --kt-tema-dolgu (0 → 1): büyümenin ikinci
(2) aynı geometride BOŞLUKLARI DOLU çizim (kolay-tercih-mark-dolu.svg), yarısında kareler arasında ve ekran kenarlarında kalan eski görüntü
boyu --kt-tema-kenar × --kt-tema-kapanis (0 → 1): logo en büyük haline yumuşakça yeni temaya solar. İkinci bir şekil yok — "logo içinde logo"
ulaşmaya yakın dolu çizim merkezden dışa doğru büyür, kareler arası görünmesin (8 Eki 2026, Bilal).
boşlukları yumuşak biçimde kapatır; SVG data URI olarak gömülü, dosyadan url() ile DEĞİL: Chrome, view
(3) tam ekran dolgu: --kt-tema-dolgu (0 → 1) ile işaret ekranı tam transition pseudo elemanında dosyadan yüklenen birden çok maske
kapsadıktan sonra dış çentiklerde kalan eski zeminin son anda dolması. katmanını tümden şeffaf çiziyordu. Çizim public/kolay-tercih-mark.svg
Yuvarlak büyüme yok — logo ekranı kaplayınca geçiş tamamlanır. ile aynı geometridir; o değişirse burası da güncellenir.
Konum, boy ve dolgular motion ile sürülür (lib/tema-gecisi.ts); buradaki Konum, boy ve dolgu motion ile sürülür (lib/tema-gecisi.ts); buradaki
kt-tema-omur yalnızca geçişin pseudo elemanı motion bitene kadar yaşasın kt-tema-omur yalnızca geçişin pseudo elemanı motion bitene kadar yaşasın
diye durur (süre --kt-tema-sure, JS'den gelir). Hareket azaltılmışsa JS diye durur (süre --kt-tema-sure, JS'den gelir). Hareket azaltılmışsa JS
geçişi hiç başlatmaz, tema düz değişir. */ geçişi hiç başlatmaz, tema düz değişir. */
@@ -502,11 +502,6 @@
inherits: true; inherits: true;
initial-value: 0px; initial-value: 0px;
} }
@property --kt-tema-kapanis {
syntax: "<number>";
inherits: true;
initial-value: 0;
}
@property --kt-tema-dolgu { @property --kt-tema-dolgu {
syntax: "<number>"; syntax: "<number>";
inherits: true; inherits: true;
@@ -526,15 +521,7 @@
} }
.kt-tema-gecis::view-transition-new(root) { .kt-tema-gecis::view-transition-new(root) {
z-index: 2; z-index: 2;
/* İki SVG de data URI olarak gömülü, dosyadan url() ile DEĞİL: Chrome'da
view-transition pseudo elemanı dosyadan yüklenen ikinci bir maske
katmanını (boyu 0'dan büyük olduğu an) tümden şeffaf çiziyor — logo
hiç görünmüyordu (8 Eki 2026 tanısı). Gömülü hâlde iki katman da
doğru birleşiyor. Çizimler public/kolay-tercih-mark.svg ve
public/kolay-tercih-mark-dolu.svg ile aynı geometridir; oradaki dosya
değişirse burası da güncellenir. */
mask-image: mask-image:
url("data:image/svg+xml,<svg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20180%20180%22><rect%20x=%2227%22%20y=%2256%22%20width=%2277%22%20height=%2257%22%20rx=%2213%22/><rect%20x=%2291%22%20y=%2229%22%20width=%2256%22%20height=%22122%22%20rx=%2213%22/></svg>"),
url("data:image/svg+xml,<svg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20180%20180%22><rect%20x=%2227%22%20y=%2256%22%20width=%2257%22%20height=%2257%22%20rx=%2213%22/><rect%20x=%2291%22%20y=%2229%22%20width=%2256%22%20height=%2256%22%20rx=%2213%22/><rect%20x=%2291%22%20y=%2295%22%20width=%2256%22%20height=%2256%22%20rx=%2213%22/></svg>"), url("data:image/svg+xml,<svg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20180%20180%22><rect%20x=%2227%22%20y=%2256%22%20width=%2257%22%20height=%2257%22%20rx=%2213%22/><rect%20x=%2291%22%20y=%2229%22%20width=%2256%22%20height=%2256%22%20rx=%2213%22/><rect%20x=%2291%22%20y=%2295%22%20width=%2256%22%20height=%2256%22%20rx=%2213%22/></svg>"),
linear-gradient( linear-gradient(
rgb(0 0 0 / var(--kt-tema-dolgu)), rgb(0 0 0 / var(--kt-tema-dolgu)),
@@ -542,13 +529,9 @@
); );
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-size: mask-size:
calc(var(--kt-tema-kenar) * var(--kt-tema-kapanis))
calc(var(--kt-tema-kenar) * var(--kt-tema-kapanis)),
var(--kt-tema-kenar) var(--kt-tema-kenar), var(--kt-tema-kenar) var(--kt-tema-kenar),
100% 100%; 100% 100%;
mask-position: mask-position:
calc(var(--kt-tema-x) - var(--kt-tema-kenar) * var(--kt-tema-kapanis) / 2)
calc(var(--kt-tema-y) - var(--kt-tema-kenar) * var(--kt-tema-kapanis) / 2),
calc(var(--kt-tema-x) - var(--kt-tema-kenar) / 2) calc(var(--kt-tema-x) - var(--kt-tema-kenar) / 2)
calc(var(--kt-tema-y) - var(--kt-tema-kenar) / 2), calc(var(--kt-tema-y) - var(--kt-tema-kenar) / 2),
0 0; 0 0;

View File

@@ -2,8 +2,7 @@
// çevirmez; yeni tema, KolayTercih işaretinin biçiminde önce ekranın altından // çevirmez; yeni tema, KolayTercih işaretinin biçiminde önce ekranın altından
// ortaya süzülür, sonra merkezden büyüyerek ekranı kaplar. View Transitions // ortaya süzülür, sonra merkezden büyüyerek ekranı kaplar. View Transitions
// API + CSS maskesi (globals.css `.kt-tema-gecis`) eski/yeni görüntü çiftini // API + CSS maskesi (globals.css `.kt-tema-gecis`) eski/yeni görüntü çiftini
// kurar; maskenin konumu, boyu, boşluk kapanışı ve son dolgu motion ile // kurar; maskenin konumu, boyu ve son dolgu motion ile sürülür. Tarayıcı View Transitions bilmiyorsa ya da kullanıcı hareketi
// sürülür. Tarayıcı View Transitions bilmiyorsa ya da kullanıcı hareketi
// azaltmışsa tema düz değişir. // azaltmışsa tema düz değişir.
import { animate, type AnimationPlaybackControls } from "motion"; import { animate, type AnimationPlaybackControls } from "motion";
@@ -11,32 +10,18 @@ import { animate, type AnimationPlaybackControls } from "motion";
/** Geçiş sırasında <html>'de duran sınıf (globals.css). */ /** Geçiş sırasında <html>'de duran sınıf (globals.css). */
const GECIS_SINIFI = "kt-tema-gecis"; const GECIS_SINIFI = "kt-tema-gecis";
// Saniye. Faz 1 (uçuş): işaret ekranın altından ortaya gelir — normal, // Saniye. Faz 1 (uçuş): işaret ekranın altından ortaya gelir. Faz 2
// boşluklu hâliyle. Faz 2 (kaplama): merkezden büyüyerek ekranı aşar; // (kaplama): merkezden büyüyerek ekranı aşar; DOLGU_BASI'ndan sonra tam ekran
// kaplamanın KAPANIS_BASI…KAPANIS_BITIS aralığında dolu çizim merkezden // dolgu alfası yükselir ve kareler arasında / kenarlarda kalan eski görüntü
// dışa büyür ve kareler arası boşlukları kapatır (en büyük hâle ulaşmadan). // yeni temaya solar. Ekranda tek silüet vardır, ikinci bir şekil büyümez.
// EASE fazlar arasında geçişin eski koreografisiyle aynı hissi verir.
const UCUS_SURE = 0.45; const UCUS_SURE = 0.45;
const KAPLAMA_SURE = 0.6; const KAPLAMA_SURE = 0.6;
const KAPANIS_BASI = 0.55; const DOLGU_BASI = 0.5;
const KAPANIS_BITIS = 0.9;
const EASE = [0.65, 0, 0.35, 1] as const; const EASE = [0.65, 0, 0.35, 1] as const;
// CSS'teki kt-tema-omur'un süresi: motion bitmeden pseudo eleman kalkmasın // CSS'teki kt-tema-omur'un süresi: motion bitmeden pseudo eleman kalkmasın
// diye toplamın biraz üstü (globals.css'te --kt-tema-sure ile okunur). // diye toplamın biraz üstü (globals.css'te --kt-tema-sure ile okunur).
const GECIS_SURESI = UCUS_SURE + KAPLAMA_SURE + 0.1; const GECIS_SURESI = UCUS_SURE + KAPLAMA_SURE + 0.1;
// İşaretin dış kenarları (public/kolay-tercih-mark-dolu.svg, 180'lik viewBox;
// orijinal logonun boşlukları doldurulmuş çizimi, dış uzantılar aynı):
// x 27–147, y 29–151. Merkeze (90) göre oranlar — dolgu, bu sınır kutusu
// ekranı tam kapsadığı andan itibaren dolar; erken dolarsa ekrandaki eski
// zemin topluca solardı.
const KENAR_ORAN = {
sol: (90 - 27) / 180,
sag: (147 - 90) / 180,
ust: (90 - 29) / 180,
alt: (151 - 90) / 180,
} as const;
let suruyor = false; let suruyor = false;
/** /**
@@ -73,27 +58,13 @@ export function temayiGecisle(uygula: () => void) {
const merkezY = boy / 2; const merkezY = boy / 2;
const baslangicY = boy + ucusKenar / 2; const baslangicY = boy + ucusKenar / 2;
// Kaplama merkezden ekranın en uzak köşesine kadar büyümeli. İşaretin // Kaplama merkezden ekranın en uzak köşesine kadar büyümeli. İşaretin
// görünür karesi viewBox'ın ~%67'si; kenar bu oranla çarpılır ki en büyük // görünür karesi viewBox'ın ~%67'si; kenar bu oranla çarpılır ki kareler
// hâlde köşe karesi bile ekranı aşsın (eski hesapla aynı çarpan). // ekranı geniş ölçüde kaplasın — kalan boşlukları dolgu solması kapatır.
const sonKenar = Math.ceil(Math.hypot(merkezX, merkezY) * 3.4); const sonKenar = Math.ceil(Math.hypot(merkezX, merkezY) * 3);
// Dolgu, işaretin dış kutusu ekranı tam kapsadığı anda başlar (erken
// dolarsa marka henüz ekrana ulaşmadan eski zemin topluca solardı). Alt
// sınır 0.9: kapsama hesaba katılmayan dar bir marjla geç kalırsa bile
// dolgu kaplamanın son ~%10'unda bitsin; aksi hâlde ekranın köşelerinde
// eski zemin belirgin biçimde kalır.
const kapsaKenar = Math.max(
en / 2 / Math.max(KENAR_ORAN.sol, KENAR_ORAN.sag),
boy / 2 / Math.max(KENAR_ORAN.ust, KENAR_ORAN.alt),
);
const dolguBasi = Math.min(
1,
Math.max((kapsaKenar - ucusKenar) / (sonKenar - ucusKenar), 0.9),
);
kok.style.setProperty("--kt-tema-x", `${merkezX}px`); kok.style.setProperty("--kt-tema-x", `${merkezX}px`);
kok.style.setProperty("--kt-tema-y", `${baslangicY}px`); kok.style.setProperty("--kt-tema-y", `${baslangicY}px`);
kok.style.setProperty("--kt-tema-kenar", `${ucusKenar}px`); kok.style.setProperty("--kt-tema-kenar", `${ucusKenar}px`);
kok.style.setProperty("--kt-tema-kapanis", "0");
kok.style.setProperty("--kt-tema-dolgu", "0"); kok.style.setProperty("--kt-tema-dolgu", "0");
kok.style.setProperty("--kt-tema-sure", `${GECIS_SURESI}s`); kok.style.setProperty("--kt-tema-sure", `${GECIS_SURESI}s`);
kok.classList.add(GECIS_SINIFI); kok.classList.add(GECIS_SINIFI);
@@ -118,22 +89,11 @@ export function temayiGecisle(uygula: () => void) {
ease: EASE, ease: EASE,
onUpdate: (kenar) => kok.style.setProperty("--kt-tema-kenar", `${kenar}px`), onUpdate: (kenar) => kok.style.setProperty("--kt-tema-kenar", `${kenar}px`),
}), }),
// Kapanış: dolu çizimin boyu kenar × kapanış — büyümenin ortasından // Dolgu: büyümenin ikinci yarısında kareler arasında ve ekran
// sonuna doğru boşluklar merkezden dışa dolar, logo en büyük hâle // kenarlarında kalan eski görüntü yeni temaya solar.
// ulaşmadan kapanır. Boyut sürüldüğü için ek bir katmanın alfa
// çakışması gerekmez; maske toplamı (add) değişmez.
animate(0, 1, { animate(0, 1, {
duration: KAPLAMA_SURE * (KAPANIS_BITIS - KAPANIS_BASI), duration: KAPLAMA_SURE * (1 - DOLGU_BASI),
delay: UCUS_SURE + KAPLAMA_SURE * KAPANIS_BASI, delay: UCUS_SURE + KAPLAMA_SURE * DOLGU_BASI,
ease: EASE,
onUpdate: (kapanis) => kok.style.setProperty("--kt-tema-kapanis", `${kapanis}`),
}),
// Dolgu: işaretin dış çentiklerinde kalan eski zemin son anda dolar —
// ekranı kapsayan boşluklar (kareler arası şeritler) maskenin kendisinde
// dolu çizimle kapanmıştır, burada değil.
animate(0, 1, {
duration: KAPLAMA_SURE * (1 - dolguBasi),
delay: UCUS_SURE + KAPLAMA_SURE * dolguBasi,
ease: EASE, ease: EASE,
onUpdate: (dolgu) => kok.style.setProperty("--kt-tema-dolgu", `${dolgu}`), onUpdate: (dolgu) => kok.style.setProperty("--kt-tema-dolgu", `${dolgu}`),
}), }),