- viewBox 0,7 s gecikmeyle 1,1 s güçlü ease-out ile ilin çevresindeki kutuya kayar (en çok 2,4 kat; ülke haritasında şehir işaretine 1,8 kat); kutu SVG oranında ve harita dışına taşmaz. Hareketi azalt: doğrudan odak. - usePixelHeat viewBox'ı her taramada canlı okur; yakınlaşmış haritada da imleç doğru kareyi ısıtır (hero davranışı değişmez). - DESIGN.md §4.17 yakınlaşma notu. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
57 KiB
KolayTercih görsel dili (DESIGN.md)
Bu dosya sitenin görsel dilinin tek yazılı kaynağıdır. Yeni ekran, bileşen, modal, kart
ya da buton çizmeden önce okunur; mevcut arayüz değiştirilirken buna bakılır. Değerler koddan
çıkarılmıştır (src/app/globals.css, src/app/layout.tsx, src/components/pixel-decor.tsx,
src/components/ui/*, src/app/page.tsx, src/features/katalog/components/universite-icerik.tsx);
kodla çelişirse kod değil, bu dosya düzeltilir ve çelişki raporlanır. Kural ihlallerini
pnpm tasarim:denetim yakalar.
Biçim: Google Stitch'in DESIGN.md düzeni (9 bölüm). Sabit değerler Tailwind sınıfı olarak verilir; kodda da sınıf kullanılır, hex/oklch elle yazılmaz.
Canlı referans ekran: /universite/ankara-universitesi (23 Eyl 2026'da Bilal'le birlikte
bu belgedeki "şişko ve sade" dile göre baştan tasarlandı). Bir kural belirsiz kalırsa o sayfanın
kodu (universite-icerik.tsx, universite-program-tablosu.tsx, akademik-ayrinti.tsx,
nav-baslik.tsx) ölçüdür. Site genelinde dönüşüm bu ekranı örnek alır.
1. Görsel tema ve atmosfer
Bir cümle: Beyaz, bol nefesli, şişko ve sade — kullanıcıya "basit bir şey kullanıyorum" hissi veren, Apple uygulamaları kadar kolay anlaşılır bir arayüz; mavi bilgi + turuncu aksiyon; her yüzeyde küçük bir piksel imzası (hero'daki dot-matrix Türkiye haritasının ve logodaki üç karenin dili) dolaşır.
1.1 Temel his: şişko ve sade
Referans: header (src/components/site-header.tsx ve içindeki arama/kullanıcı hapları), hero
ve üniversite sayfası. Bu hissi veren şeyler, ekrandan bağımsız:
- İri dokunma alanı. Butonlar ve haplar 44–48 px (
h-11/h-12), tam yuvarlak. - İri yazı, az eleman. Bir ekranda az şey var ve her biri büyük. Küçük gri yazı yığını yok.
- Sayı kahramandır. Bir veri gösteriliyorsa sayı kartın en büyük öğesidir; etiket ve açıklama onun altında ikinci planda.
- Sık bakılan önde, ayrıntı bir dokunuş derinde (Apple'ın "önce ortak yol, gelişmiş seçenekler bir seviye aşağıda" ilkesi). Sayfada en çok dört özet sayı; fazlası ayrıntı satırının açtığı alt sayfaya (§4.10).
- Nefes alanı korunur. Harita gibi görsel dinlenme alanları küçültülmez, sıkıştırılmaz, bilgiyle doldurulmaz. Sadeleştirmek = bu alanları silmek değil, etraflarındaki kalabalığı azaltmaktır.
- Verimli ama havadar. Alt sayfa ve paneller dikine uzamaz; ilişkili öğeler yan yana dizilir, aralarında boşluk kalır (§5.3).
- Doğal duruş. Eşit, hizalı ızgaralar yerine logodaki üç kare gibi hafif kaymış yerleşim (§4.11). Her şey birbirine cetvelle hizalıysa ekran "tablo" gibi durur.
- Basınca tepki. Her tıklanabilir öğe basınca hafifçe küçülür (
active:scale-[0.97], geniş satırlarda[0.99]), üzerine gelince turuncuya döner (§2.1).
1.2 Genel kurallar
- Zemin her zaman beyaz; koyu zemin yalnızca CTA bandı ve çekmece başlığı gibi tek bir
vurgu yüzeyinde (
PixelMasonryile: büyüklü küçüklü, hafif kaymış kareler). - İmza dekoratiftir ama rastgele değildir: deterministik ızgara (hücre 10, nokta 7.4, rx 2),
imleç yaklaşınca turuncuya ısınan pikseller (
usePixelHeat), uzaklaşınca yavaş soğuma. Piksel veri taşıyorsa (ör.PixelSira) kalır; iki bölüm arasına süs olarak konmuş piksel ayraç alt sayfalarda ve kompakt panellerde kullanılmaz. - Ton: öğrenciye "sen" diyen, sakin, vaatsiz. Süs yok, gösteriş yok; hareket yalnızca bir şey söylüyorsa var.
- Karanlık mod yoktur.
dark:sınıfı yazılmaz (.darktoken'ları shadcn kalıntısıdır).
2. Renk paleti ve rolleri
| Rol | Sınıf | Nerede |
|---|---|---|
Bilgi/vurgu mavisi (primary) |
text-primary, bg-primary/10, border-primary/30 |
Rozet metni, ikon kutusu, hero'daki italik vurgu, linklerin durağan rengi |
| Aksiyon turuncusu | bg-orange-500 hover:bg-orange-600 text-white |
Funnel CTA butonları. Bir ekranda tek turuncu buton |
| Hover turuncusu | hover:text-orange-500, hover:border-orange-500, hover:bg-orange-50/60, group-hover:text-orange-500 |
Link, kart, satır ve ikincil butonların üzerine gelme hâli (§2.1); liste satırı adı hariç (mavi kalır) |
| Piksel vurgusu | fill-orange-500 (opaklık 0.55–0.85) |
Yalnızca piksel süslerinin "sıcak" noktaları |
| Başlık metni | text-slate-900 |
h1–h3, kart başlıkları, iri sayılar |
| Gövde metni | text-slate-600 |
Paragraf, açıklama |
| İkincil metin | text-slate-500 |
Meta bilgi, yardımcı satır, kart açıklaması |
| Silik metin | text-slate-400 |
İpucu, devre dışı, placeholder, sayının yanındaki birim (/ 198) |
| Kenarlık | border-slate-200 (landing kartlarında border-slate-200/70) |
Kart, rozet, çarpı, giriş alanı |
| İç zemin | bg-slate-50 |
Kartın içindeki ikincil kutu, tablo başlığı |
| Nötr hover zemini | hover:bg-slate-100 |
Yalnız kapatma çarpısı ve ghost buton |
| Risk: güvenli | emerald-500 / text-emerald-600 |
Her zaman "Güvenli" metniyle |
| Risk: az riskli | amber-500 / text-amber-600 |
Her zaman "Az riskli" metniyle |
| Risk: riskli | red-500 / text-red-600 |
Her zaman "Riskli" metniyle |
| Uyarı kutusu | border-amber-200 bg-amber-50 text-amber-900 |
Bilgilendirme notu |
| Gösterge karesi | Dolu zemin + beyaz yazı: bg-orange-500, bg-primary, bg-indigo-500, bg-green-600; rounded-3xl |
Yalnız sayı gösterge kareleri (§4.11). Renk sempati katar, anlam taşımaz: etiket her karede yazılı |
| Hata | text-destructive, text-red-600 |
Form hatası |
2.1 Hover: tek turuncu
Bilal'in kararı (23 Eyl 2026): üzerine gelme hâlinde sitenin turuncusu kullanılır ve bu
turuncu tek tondur: orange-500 — CTA butonunun turuncusuyla birebir aynı değer.
- Link / metin:
transition-colors hover:text-orange-500(altı çizili linklerdehover:underlinekalır). - Tıklanabilir kart / satır:
hover:border-orange-500 hover:bg-orange-50/60; içindeki iri sayı ya da başlıkgroup-hover:text-orange-500; sağdaki okgroup-hover:translate-x-0.5 group-hover:text-orange-500. - İkincil (outline) buton:
hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500. - İstisna — liste satırındaki adlar mavi kalır: program/üniversite listelerinde satırın
adı (bölüm ya da üniversite sayfasına giden link)
hover:text-primary hover:underline. Bilal'in kararı (23 Eyl 2026): uzun bir listede imleç satırdan satıra geçerken yanıp sönen turuncu adlar yorucu; mavi sakin kalır. Satırın butonları ve listedeki diğer linkler §2.1'e uyar. - Yapılmaz: hover'da
text-primary/border-primary(eski mavi hover — yukarıdaki istisna dışında),orange-600yazı,orange-300kenarlık — aynı ekranda iki turuncu tonu göze "farklı turuncu" diye batar. Tek istisna: turuncu CTA'nın kendi zemininin hover'ı (hover:bg-orange-600), kanonik. - Geçiş notu: kodda hâlâ
hover:text-primary/hover:border-primary/30kullanan yerler var (landing kartı dahil); tarama sırasında bu kurala çevrilir. Denetim bunlarımavi-hoveruyarısıyla listeler; liste satırı adındaki uyarı istisnadır, dokunulmaz.
2.2 Palet kuralları
- Nötr yalnızca slate.
gray,zinc,neutral,stoneyazılmaz. indigo,purple,violet,fuchsia,pink,cyan,teal,lime,green,yellowyeni kullanım açmaz. Tek istisna "Gösterge karesi" satırındaki dolubg-indigo-500vebg-green-600zeminleri (Bilal'in kararı, 23 Eyl 2026); yazı, kenarlık ya da başka ton/opaklıkta bu renkler yine yasak. (bg-violet-50 text-violet-600tek bir mevcut durum çipidir; yeni yere taşıma — üniversite sayfasında "Vakıf" çipi bu yüzden hap + ikonla değiştirildi, §4.12.)- Gradyan metin (
bg-clip-text text-transparent) ve parlama gölgesi (shadow-[0_0_…]) yok. - Hex/oklch değeri sınıf içine yazılmaz (
text-[#…]); token ya da Tailwind tonu kullanılır. Risk renklerinin SVG karşılığısrc/lib/risk.tsiçindekiRISK_PIN_RENK'ten okunur. - Renk tek başına anlam taşımaz: risk rengi her zaman metin etiketiyle birlikte gider
(
RISK_ETIKET,DILIM_ETIKET— üçüncü dilimin görünen adı "Güvenli"). Tür ayrımı (devlet / vakıf) da renkle değil ikon + metinle yapılır. - Renkli dolu zeminde beyaz yazı: turuncu ve yeşil zeminde küçük beyaz yazı WCAG AA'nın
altında kalır (sitenin turuncu CTA'sı da aynı ikiliyi kullanır). Bu zeminlerde etiket
font-bold, sayı en aztext-3xl; uzun metin konmaz.
3. Tipografi
Dört yazı tipi, her birinin tek bir işi var:
| Sınıf | Yazı tipi | İş |
|---|---|---|
font-heading |
Cal Sans | Tüm başlıklar (h1–h3, kart başlığı) ve iri sayılar. Her zaman font-bold ile |
font-sans (varsayılan) |
Clarity City 400–800 | Gövde, buton, form, tablo |
font-bricolage |
Bricolage Grotesque (opsz ekseni) | Vurgu: hero'da italik mavi span, logo yazısı, üst çubuktaki sayfa adı (§4.14), küçük etiketler/çipler |
font-mono |
Geist Mono | Yalnızca kod/markdown blokları. Arayüzde kullanılmaz |
Ölçek (kopyala, uydurma):
- Hero h1:
font-heading text-5xl font-bold tracking-[0.015em] sm:text-6xl; vurgu kelimesi<span className="font-bricolage italic tracking-tighter font-bold text-primary"> - Alt sayfa h1 (katalog, rehber):
font-heading text-3xl font-bold leading-tight text-slate-900 sm:text-5xl - Bölüm h2:
font-heading text-3xl font-bold sm:text-4xl(istenirsetext-slate-900); alt sayfada liste bölümü başlığıfont-heading text-2xl font-bold text-slate-900 sm:text-3xl - Panel/kart h3:
font-heading text-xl font-bold· grup başlığı (fakülte vb.):font-heading text-xl font-bold text-slate-900 sm:text-2xl - Küçük başlık:
font-heading text-base font-bold text-slate-900 - Bölüm giriş paragrafı:
max-w-xl text-lg leading-relaxed text-slate-600 - Sayfa özet paragrafı:
text-base leading-relaxed text-slate-600 sm:text-lg - Gövde:
text-base leading-relaxed(açıklama, liste satırı adı) ya datext-sm(kart açıklaması, tablo hücresi, meta) - Etiket/rozet metni:
text-xs font-semibold
İri sayı ölçeği (§1.1 "sayı kahramandır"):
| Yer | Sınıf |
|---|---|
| Özet kartı sayısı | font-heading text-4xl font-bold leading-none tracking-tight text-slate-900 sm:text-5xl |
| Gösterge karesi, büyük | font-heading text-5xl font-bold leading-none tracking-tight |
| Gösterge karesi, orta | font-heading text-3xl font-bold leading-none |
Sayının birimi (/ 198, kişi) |
text-base font-semibold text-slate-400 (renkli zeminde text-white/80) |
Alt sınırlar:
- Gövde metni telefonda 16 px'in (
text-base) altına inmez;text-smyalnız ikincil bilgide,text-xsyalnız ince yazıda (kaynak satırı, eksen etiketi, çip). - 12 px altı yok:
text-[10px],text-[11px]yazılmaz (denetim uyarır). - Büyük harfli minik etiket yok:
uppercase tracking-wide text-xskalıbı ("PROGRAM", "TOPLAM KONTENJAN") yazılmaz; etiket büyük-küçük harfli,text-sm font-semibold. - İri sayıda
tabular-numsyok: Cal Sans'ta sabit genişlikli rakam "daktilo" gibi aralıklı durur ("13.88 9").tabular-numsyalnızfont-sanstablo sütunlarında. - Yasak: Inter, Roboto, Arial, sistem fontu, serif,
font-[…]keyfi font.
4. Bileşen stilleri (tek kaynaklar)
Bir eleman iki yerde görünüyorsa stili tek kaynaktan gelir. Aşağıdakiler yeniden tasarlanmaz.
§4.8–§4.15 üniversite sayfasında doğdu; ikinci bir ekranda gerektiğinde kopyalanmaz, ortak
bir dosyaya (src/components/…) çıkarılıp iki yer de oradan kullanır.
4.1 Buton — src/components/ui/button.tsx
- Her buton
rounded-full;h-9varsayılan,h-11/h-12funnel CTA'ları (44 px dokunma hedefi),size-9ikon butonu. - Odak:
focus-visible:ring-3 focus-visible:ring-ring/50; basıncaactive:translate-y-px. - Turuncu CTA (kanonik):
Metin önce, ok sonda. Başta ikon yok.
<Button size="lg" className="cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600"> Listemi oluştur <ArrowRight className="size-4" aria-hidden /> </Button>Sparklesyok. İstenirseactive:scale-[0.97]. - İkincil gezinme butonu ("Tüm sıralamayı gör →"):
<Button asChild size="lg" variant="outline" className="cursor-pointer px-6 transition-[background-color,border-color,color,transform] duration-150 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97]"> <Link href="…">Tüm sıralamayı gör<ArrowRight className="size-4" aria-hidden /></Link> </Button> - Sessiz:
variant="ghost"; link görünümü:variant="link".
4.2 Rozet (bölüm başlığı üstündeki kapsül) — SectionEyebrow, src/components/pixel-decor.tsx
<SectionEyebrow>Nasıl çalışır?</SectionEyebrow>
Sınıfı: inline-flex items-center gap-2 rounded-full border border-slate-200 bg-white px-3.5 py-1.5 text-xs font-semibold text-primary + başta PixelMark.
@/components/ui/badge kullanılmaz; elle pill span yazılmaz. Filtre çipleri, nav butonları
ve kimlik hapları (§4.12) bu kuralın dışındadır. Rozet sayfa bölüm başlıklarının üstündedir;
çekmece ve modal başlıklarında kullanılmaz (§4.10, Bilal 24 Eyl 2026).
4.3 Modal kapatma çarpısı — DialogContent varsayılanı, src/components/ui/dialog.tsx
absolute top-3 right-3 z-10 flex size-9 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-popover text-slate-500 transition-[background-color,transform] duration-150 hover:bg-slate-100 hover:text-slate-800 active:scale-[0.96] + <XIcon className="size-4" aria-hidden /> + sr-only "Kapat".
Özel yerleşim gerekiyorsa showCloseButton={false} ver ve aynı sınıf setini kopyala.
Alt sayfada (Drawer) aynı sınıf seti DrawerClose üstünde kullanılır (§4.10).
4.4 Kart ve kutu
- Landing/öne çıkan kart:
<Card className="relative h-full overflow-hidden border-slate-200/70 shadow-sm transition-all duration-300 hover:-translate-y-1 hover:border-orange-500 hover:shadow-lg hover:shadow-orange-500/5">+ sağ üstte<PixelCorner className="absolute right-4 top-4" />. (Kodda hâlâhover:border-primary/30 hover:shadow-primary/5; §2.1 geçiş notu.) - Sade kutu (form, panel, liste satırı):
rounded-2xl border border-slate-200 bg-white(+p-5/p-6). Küçük iç kutu:rounded-xl border border-slate-200 bg-slate-50. Not kutusu:rounded-lg. - İkon kutusu:
flex size-11 items-center justify-center rounded-xl bg-primary/10içindesize-5 text-primaryikon. Kart içinde sayının yanında küçük hâli:size-8 … sm:size-10+size-4 sm:size-5ikon (§4.8). - Gölge:
shadow-smvarsayılan; hover'dashadow-lg shadow-orange-500/5. Başka gölge yok.
4.5 Risk çipi / etiketi — RiskEtiketi, src/components/risk-etiketi.tsx
Tablolar, çekmece ve rapor listesi <RiskEtiketi risk={…} /> kullanır; elle yazılmaz.
Nokta + metin: <span className="size-2 rounded-full bg-emerald-500" /> yanında text-xs font-semibold text-emerald-600; metin RISK_ETIKET'ten. Renk tek başına asla.
4.6 Form alanı — Input, Select, Textarea (src/components/ui/)
Form alanı da bir haptır: üst çubuktaki arama/kullanıcı haplarıyla aynı kalıp (48 px, tam
yuvarlak, slate-200 kenarlık, 16 px yazı). shadcn'in ince varsayılanı (h-8 rounded-lg border-input md:text-sm) bu projede yoktur; temel bileşenler 24 Eyl 2026'da bu dile çevrildi.
- Metin alanı (
Input):h-12 w-full rounded-full border border-slate-200 bg-white px-5 text-base text-slate-900 placeholder:text-slate-400; hoverborder-slate-300; odakborder-primary ring-3 ring-ring/50; hata (aria-invalid)border-red-500 ring-3 ring-red-500/20; devre dışıbg-slate-50 opacity-50.md:text-smyok — gövde 16 px altına inmez (§3) ve iOS odakta yakınlaştırmaz. Kullanım yerinde yükseklik/köşe/zemin yazılmaz (classNameyalnız yerleşim için:sm:flex-1,pl-12). Tek istisna hero: telefonda bir kademe iri,h-14 text-lg sm:h-12 sm:text-base. - Başta ikon (sıralama alanındaki kupa): kapsayıcı
relative, ikonpointer-events-none absolute left-5 top-1/2 size-4 -translate-y-1/2 text-slate-400, alanpl-12. - Seçim (
SelectTrigger): aynı hap —h-12 pl-5 pr-4 text-base, oktext-slate-400;size="sm"→h-9 px-4 text-sm(yalnız masaüstü tablo aksiyonu, §8). Açılan listerounded-2xl border border-slate-200 bg-white p-1.5 shadow-lg; satırrounded-full py-2 pl-4 pr-9 text-base, klavye/odakbg-slate-100, seçili işaretitext-primary. - Çok satır (
Textarea): hap değil sade kutu (§4.4):min-h-24 rounded-2xl border border-slate-200 bg-white px-5 py-3 text-base; hover/odak/hata metin alanıyla aynı. Sohbet kutusu (prompt-input.tsx) kenarlıksız ve şeffaf üstüne yazar; tek istisna. - Kenarlıksız ham
<input>yalnız kendi hap kabının içinde: il arama (sihirbaz-adimlar.tsx,h-11 rounded-full border-slate-200kap) ve katalog arama modalı (üst şeritteh-16). Kenarlıklı ham input yazılmaz;Inputkullanılır. - Etiket her alanda: görünür
text-sm font-semibold text-slate-700ya dasr-only. Hata mesajı alanın altındarole="alert"+text-sm font-medium text-red-600; ne olduğunu ve ne yapılacağını söyler (§10.4). Sayısal alanlarda uç değerler (0, negatif, 1.000.000 üstü) ele alınır. - Alan + buton yan yana:
flex flex-col gap-3 sm:flex-row; butonh-12(§4.1size="lg"), alansm:flex-1. Telefonda alt alta, ikisi de tam genişlik. - Denetim:
ince-form-alani(hata) —Input/SelectTrigger/Textareaüstüneh-7–h-10,rounded-sm/md/lg/xl,bg-background/border-inputyazılmış;ham-input(uyarı) — kenarlıklı ham<input>.
4.7 İkonlar
Yalnızca lucide-react. Boyut: size-4 buton/satır içi (varsayılan), size-5 ikon kutusu, size-3.5 küçük çip, size-6 üstü yalnızca boş durum. Dekoratif ikon aria-hidden; tek başına ikon buton aria-label ya da sr-only metin taşır. Emoji ikon olarak kullanılmaz.
4.8 Özet kartı — OzetKart, src/components/ozet-kart.tsx
Apple Fitness özet kartının sitenin ölçüleriyle hâli. Sayfada en çok dört tane (harita yanındaki 2×2).
┌──────────────────────┐
│ 13.889 [👥] │ ← sayı solda, iri; ikon kutusu sağda, küçük
│ Kontenjan │ ← başlık text-base font-semibold text-slate-900
│ 2026 toplamı │ ← açıklama text-sm text-slate-500, tek satır
└──────────────────────┘
- Kap:
flex flex-col rounded-2xl border border-slate-200 bg-white p-4 sm:p-5. - Sayı satırı:
flex items-start justify-between gap-1.5; sayı §3 "Özet kartı sayısı"; ikon kutusuflex size-8 shrink-0 items-center justify-center rounded-xl bg-primary/10 sm:size-10. dlanlamı içindt(başlık) DOM'da önce gelir, görsel sıraorder-*ile kurulur.- Telefonda kart iç genişliği ~131 px: en uzun sayı ("13.889", 36 px'te ~90 px) + 32 px ikon
sığar. Daha uzun sayı gelecekse önce ölç (§9.2), sonra yaz. Ölçülen sınır: 36 px'te
"1.618.988" 123 px — ikonun altına girer. 6–7 haneli sayı birimle kısalır: 245.300 →
245+ birimbin, 1.618.988 →1,62+ birimmilyon(bölüm sayfasındakikartSayisi). - Kullanıldığı yerler: üniversite ve bölüm sayfası (bölümde dört kart: Program, Devlet,
Vakıf, En iyi sıralama;
grid grid-cols-2 gap-4 lg:grid-cols-4, haritası olmadığı için). - Tıklanabilir kart (ör. Türkiye sırası → sıralama sayfası): kartın tamamı link olur
(
after:absolute after:inset-0gerilmiş link), iç kaynak linkirelative z-10ile üstte kalır; hover §2.1. - Açıklama altında veri görseli gerekiyorsa (ör.
PixelSira)ekyuvasına konur.
4.9 Ayrıntı satırı — AkademikAyrinti, akademik-ayrinti.tsx
Özet kartlarının altında "fazlası burada" satırı (Apple Sağlık'taki "Tüm verileri göster").
mt-4 flex w-full items-center gap-4 rounded-2xl border border-slate-200 bg-white p-4 sm:p-5- hover §2.1 +
active:scale-[0.99].
- hover §2.1 +
- Solda ikon kutusu (
size-11), ortada iki satır: başlıkfont-heading text-lg font-bold, altında önizlemetruncate text-sm text-slate-500— içeride ne olduğunu söyler ("Hoca başına 25 öğrenci"), boş "Daha fazla" yazmaz. SağdaChevronRight size-5 text-slate-400. - Dokununca alt sayfa açılır (§4.10).
4.10 Alt sayfa (Drawer) içeriği
Ayrıntı her zaman alttan açılan sayfada (Drawer handleOnly, tutamaçlı); ekranın ortasında
açılan modal değil. Çekmece kabı ve çarpı cta-sira-form.tsx'teki çekmeceyle birebir:
DrawerContent className="max-h-[92dvh] bg-white sm:mx-auto sm:max-w-2xl sm:border-x sm:border-slate-200 sm:shadow-2xl".
İçerik kuralları (Apple ayrıntı sayfası):
- Her ekranda ortalı: başlık
px-10 text-center font-heading text-2xl font-bold, altında bağlam (text-sm text-slate-500, ör. üniversite adı). - Kart yok. Çekmece zaten bir yüzey; içine çerçeveli kart koymak "pencere içinde pencere" olur. Gösterge kareleri (§4.11) bu kuralın istisnası değildir — onlar çerçevesiz, dolu renk.
- Süs ayraç yok. Bölümler arasına piksel ayraç ya da çizgi konmaz; ayrım boşlukla ve
yan yana dizilişle yapılır. Yalnız en alttaki kaynak satırı
border-t border-slate-100. - Tek ekrana sığar: 375×812'de kaydırmasız. Dikine uzuyorsa öğeler yan yana dizilir, kareler kısaltılır, not kısaltılır — içerik silinmez (§9.2 ölçüm).
- Sıra: gösterge kareleri → tek cümlelik not (
text-sm text-slate-500) → ikincil buton (§4.1) → kaynaklar (logo solda,text-xsiki satır). - Liste çekmecesi (
liste-cekmecesi.tsx, 24 Eyl 2026): başlık aynı düzende (temizle düğmesi çarpıyla aynı sınıf setinde solda). Satırlar çerçeveli kart değil, düz liste satırı (border-b border-slate-100); ad §4.15 gibi sarar, risk + taban sıra adın altında, çıkar düğmesisize-11çerçevesizCircleMinus— çarpı yalnız çekmeceyi kapatır (Bilal, 25 Eyl 2026: "2 çarpı var"). Listeler uzun olduğu için bu çekmece kaydırılır (tek ekran kuralının tek istisnası); alt bandı telefonda alt alta dizilir ki listeye en az ~280 px kalsın. - Rozet yok, ek liste yok (Bilal, 24 Eyl 2026: "buralarda badge kullanma"): çekmece ve
sihirbaz modallarının başlığı üstünde
SectionEyebrowdurmaz; başlık + tek cümle bağlam yeter. "Saniyede gör" çekmecesi (cta-sira-form.tsx) bu düzene çevrildi:DrawerTitleortalı,DrawerDescriptionbağlam, altında form; "neler alacaksın" çizgili ikon listesi kaldırıldı (bağlam cümlesi zaten söylüyor). Sihirbaz adımlarında çekmece başlığısr-only, görünür başlık adımın kendisinde. Denetim:modal-rozet(hata). - Arama motoru uyarısı: çekmece içeriği sayfa açılırken HTML'de yoktur (kapalıyken çizilmez). Google'ın görmesi gereken metin ve zorunlu atıflar (ör. URAP sırası + payda + dönem + aktif bağlantı) çekmeceye taşınmaz, sayfada da görünür kalır.
4.11 Gösterge kareleri (masonry)
Birden çok sayıyı alt sayfada göstermenin yolu. Logodaki üç kare gibi: iki sütun, sağdaki aşağı kaymış, kare boyları farklı — ne tepeler ne bitişler hizalı.
┌────────┐
│ Türkiye│ ┌────────┐
│ sırası │ │ Hoca │
│ 5. │ │ başına │
│ İlk %3 │ │ 25 │
└────────┘ └────────┘
┌────────┐ ┌────────┐
│ 56.128 │ │ 2.225 │
└────────┘ │ │
└────────┘
- Kap:
flex w-full max-w-md items-start gap-3; iki sütunflex flex-1 flex-col gap-3, sağdakimt-12. - Kare:
flex flex-col items-center justify-center rounded-3xl px-3 text-white+ zemin (§2 "Gösterge karesi") +min-h-*ile farklı boy (ör. 40 / 24 / 32 / doğal). - Ölçüyle doğrula: komşu kareler arasında tepe ve bitiş farkı en az 24 px. 8 px fark "yanlışlıkla hizalanmış" görünür (§9.2).
- Etiket
text-sm font-bold text-white/90; sayı §3 gösterge ölçeği; vurgu satırıtext-base font-bold. - Renk sırası: en önemli gösterge turuncu, ikincisi mavi, sonra indigo, yeşil.
4.12 Kimlik hapları (tür, il)
Başlığın altında kurumun kimliği; navbar haplarının ölçüsünde:
inline-flex h-10 items-center gap-2 rounded-full border border-slate-200 bg-white px-4 text-sm font-semibold text-slate-800
- başta
size-4 text-primaryikon (Landmarkdevlet,Building2vakıf,MapPinil). Tür renkle değil ikonla ayrılır. Rozet (§4.2) değildir. Tür hapı etkileşimsizdir; il hapı şehir sayfasına linktir (Bilal, 24 Eyl 2026: "şehirlerin geçtiği her yer tıklanabilir") — aynı sınıf +hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500 active:scale-[0.97]. Kural genel: bir şehir adı nerede geçerse geçsin (/universitelerlistesi, bölüm/sonuç/listem/ tadımlık satırlarındaki tür-il-süre metası)ilSayfaHref(il)ile/universiteler/[il]'e gider; satır metasındaSATIR_IKINCIL_LINK. İstisna: satırın tamamı zaten link olan yerler (URAP sıralaması, arama sonucu) — iç içe<a>olmaz, orada düz metin kalır.
4.13 Piksel sıra şeridi — PixelSira, src/components/pixel-decor.tsx
Bir sıranın (ör. 198 içinde 5.) yerini tek satır piksel şeridinde gösterir; sıranın düştüğü dilim turuncu yanar, geri kalanı hero dokusunda. Veri taşıyan piksel olduğu için süs ayraç yasağına girmez.
- Açık zeminde:
<PixelSira sira={5} toplam={198} className="h-4" />(8 hücre varsayılan). - Renkli dolu zeminde:
zemin="koyu"— işaret beyaz yanar, ısı fırçası kapanır. - Anlamı her zaman yanındaki metin taşır ("5. / 198", "İlk %3"); şerit
aria-hidden.
4.14 Üst çubuk başlık geçişi — NavBaslik, nav-baslik.tsx
iOS'taki büyük başlık davranışı: sayfa h1'i üst çubuğun altına girince üst çubuktaki "KolayTercih" yazısı yukarı kayıp söner, yerine sayfanın logosu + adı gelir; dokununca sayfa başına döner. Katalog detay sayfalarında (üniversite, bölüm) zorunlu; yeni detay sayfası eklenince aynısı yapılır:
<NavBaslik baslikId="uni-baslik" ad={uni.ad} logo={<UniLogo slug={slug} ad={uni.ad} boy="xs" />} />
<h1 id="uni-baslik" …>…</h1>
Logosu olmayan sayfada logo verilmez; üst çubukta yalnız ad görünür (bölüm sayfası —
Bilal'in kararı: yerine ikon konmaz, üst çubukta süs ikona gerek yok). Logo sunucuda üretilip
verilir (logo listesi istemciye inmez).
Hareket: yay bounce: 0, duration: 0.35, giriş ve çıkış aynı yoldan; "hareketi azalt"ta yalnız
opaklık.
4.15 Liste satırı (program/üniversite listeleri) — src/components/liste-satiri.ts
Sınıf dizileri tek dosyada (SATIR_AD, SATIR_META, SATIR_CIP, SATIR_MOBIL_SAYI,
SATIR_BUTON_KABI…); üniversite, bölüm ve /sonuc tabloları oradan okur. Yeni bir liste
tablosu bu sabitleri kullanır, sınıfı elle yazmaz.
- Risk sütunu (
/sonuc) sm'den itibaren ayrı sütun; telefonda adın altındaki sayı satırına iner. Etiket §4.5:size-2nokta +text-xs font-semibold text-{renk}-600+RISK_ETIKET. - Veride BÜYÜK HARF gelen üniversite adı ekranda
trBaslikDuzeniile yazılır. - Ad kesilmez, sarar:
whitespace-normal+block text-base font-semibold leading-snug.truncateile "İngiliz Dili ve E…" yazılmaz. - Ad linkinin hover'ı mavi:
transition-colors hover:text-primary hover:underline(§2.1 istisnası). - Telefonda yalnız ad + satır butonları sütun olarak kalır; sayısal sütunlar (taban sıra vb.)
adın altındaki satıra iner:
mt-1.5 flex items-center gap-1.5 text-sm text-slate-500 sm:hiddeniçinde değerfont-semibold text-slate-900. - Üniversite alt satırı tek akan satır, telefonda bir kademe küçük (Bilal, 24 Eyl 2026:
"mobilde çok şişko, her şey iç içe; üni adını daha küçük yazabiliriz"): adın altında üniversite
adı (
SATIR_ALT_AD) ile tür çipi/il/süre (SATIR_META)SATIR_ALT_GRUPiçinde her genişlikte yan yana akar, sığmazsa sarar; telefondatext-xs, sm'dentext-sm./sonuc, rapor listesi, tadımlık satırı ve çekmece satırı (liste-cekmecesi.tsx) böyledir. Bu, §3 "text-xs yalnız ince yazıda" kuralının bilinçli istisnasıdır (12 px tabanının üstünde). Katalog listelerinde (ad zaten üniversite/bölüm)SATIR_GRUP: telefonda ad kendi satırında, çipler 8 px altında; sm'den aynı satırda. Ölçüm 375 px, bölüm sayfası: satır 129 px ve yüksekliği metin değil, alt alta iki 44 px düğme belirliyor — metin küçültmek orayı kısaltmaz. - Tür çipi:
rounded-full bg-slate-100 px-2.5 py-0.5 text-xs font-semibold text-slate-700. - Satır butonları varsayılan
size-11(44 px);size-8gibi küçültme verilmez. Telefonda iki buton alt alta durur (inline-flex flex-col items-center gap-2 sm:flex-row, sütunw-14 sm:w-28): yan yana 96 px yiyip adı 157 px'e sıkıştırıyordu, alt alta 273 px kalıyor (24 Eyl 2026 ölçümü). - Rapor listesinde (
rapor-listesi.tsx) telefonda logo gizlenir (hidden sm:block): solda sıra numarası zaten satırı çapalıyor, logo adı üç satıra sıkıştırıyordu (satır 214 → 152 px). Açılan ayrıntı iç kutularırounded-xl, etikettext-sm font-semibold text-slate-900, metintext-base. - Geniş ekranda ince satır (Bilal, 25 Eyl 2026: "geniş ekranda listeler çok kalın"):
sm'den itibaren tür/il/süre satırı adla aynı satıra çıkar (
SATIR_GRUP); lg'de hücre dolgusupy-3ve satır düğmeleri 36 px (SATIR_DUGME_BOYU, §8 masaüstü tablo istisnası). Ölçüm 1280 px, bölüm listesi: 83 → 61 px. Telefonda değişmez (44 px düğme). - Satırda logo varsa (bölüm sayfası,
/sonuc, rapor listesi)UniLogo boy="sm"adın solunda,items-start.sm= 48 px (size-12 rounded-xl; 36 px'ten büyütüldü — Bilal, 24 Eyl 2026: "listelerde üni logoları çok küçük kalmış"). Çekmecede üniversite satırının içindekixs(28 px) metin içi kalır. - Program varyantı ("… (İngilizce) (Burslu)") adın altında ayrı satır
mt-0.5 block text-sm leading-snug text-slate-600; tür çipine yapıştırılıp kesilmez. - Tür çipi devlet/vakıf için de aynı slate çip; vakıf violet değildir (§2.2).
- Tablo başlığı
h-12 text-sm font-semibold text-slate-500; hücre dolgusupy-4 pl-4 sm:pl-5.
4.16 Bildirim (toast) — src/components/ui/sonner.tsx + globals.css
Tema light'a sabit (karanlık mod yok, §1.2): sistem koyu temadayken sonner açıklamayı beyaza
yakın griye çevirip beyaz zeminde okunmaz ediyordu (Bilal, 24 Eyl 2026: "toast açıklaması
okunmuyor"). Kutu rounded-2xl border-slate-200; başlık font-semibold text-slate-900; açıklama
text-slate-600; aksiyon düğmesi üst çubuktaki koyu hap (h-9 rounded-full bg-slate-900 beyaz
yazı, hover slate-700). Metin §10.4: ne oldu + ne yapılacak; kilometre taşı toast'ları
(program-ekle-butonu.tsx) tek cümle açıklama + tek aksiyon taşır.
4.17 Şehir çipleri — SehirCipleri, src/features/katalog/components/sehir-cipleri.tsx
Şehre göre üniversite gezinmesi (/universiteler üstü ve /universiteler/[il] altı).
Sihirbazın il çipiyle aynı kalıp; etkileşimli çip olduğu için rozet (§4.2) değildir:
inline-flex h-10 cursor-pointer items-center gap-1.5 rounded-full border px-3.5 text-sm font-semibold transition-[background-color,border-color,color,transform] duration-150 active:scale-[0.97]
- pasif
border-slate-200 bg-white text-slate-700 hover:border-orange-500 hover:bg-orange-50/60 hover:text-orange-500, bulunulan şehirborder-primary bg-primary text-white+aria-current="page". Ad yanında üniversite sayısıfont-normal tabular-nums text-slate-400(aktiftetext-white/80).
- Çip satırında yalnız 2+ üniversiteli şehirler (≈28) durur; 90'ı aşkın şehrin tamamı
/universiteler#tum-sehirleraltındaki A–Z üç sütunlu metin listesindedir (§1.1 "sık bakılan önde, ayrıntı bir dokunuş derinde"). Satırın sonunda "Tüm şehirler (N)" çipi. - Şehir sayfası (
il-icerik.tsx) katalog detay düzenindedir (§5.2): yol satırı, başlık yüzeyi (SehirYuzeyi:relative isolate overflow-hidden rounded-3xl border border-slate-200 bg-white p-6 sm:p-8,PikselZemin ton="acik"seed 31, harita kabıharic), içinde h1 "İstanbul Üniversiteleri Taban Puanları 2026", kimlik hapları (MapPinil + üniversite sayısı), özet paragraf; sağda (lg, 24rem sütun) ya da altta (telefon) şehri temsil eden piksel haritaSehirPikselHaritasi. Sonra kompaktCtaSiraForm,PagePixelDivider(seed 71), devlet / vakıf / KKTC-yurt dışı öbekleri (UniLinkleri), "Diğer şehirler" çipleri ve mavi CTA bandı. Şehir adıtrBaslikDuzeni+ tire sonrası baş harf (Bakü-Azerbaycan). Bir üniversite programı olan her ilde sayılır (ODTÜ Ankara + KKTC). - Şehir piksel haritası —
sehir-piksel-haritasi.tsx: hero'daki dot-matrix Türkiye'nin kendisi (Bilal, 24 Eyl 2026: ince taramalı ilk sürüm "oyunsu Apple/Duolingo hissine uymuyor" diye geri alındı; seçenekler A/B/C arasından "A, pikseller C'deki gibi iri" seçildi). Izgara 72 sütun × 31 satır (scripts/il-izgara-uret.ts→src/lib/il-izgara-verisi.ts; her il en az 2×2 kare), kare hücrenin %74'ü, altı farklı opaklık, kıyının altına seyrelen serpinti,text-primaryzemin, imleç yaklaşınca turuncuya ısınma (usePixelHeat). Bulunulan ilin karelerifill-orange-500, hücrenin %88'i kadar iri, 35 ms arayla belirir (kt-piksel-belir) ve grup hâlinde nabız atar (animate-pulse3.6 s); hareketi azalt açıkken dolu ve durağan. KKTC/yurt dışı: ülke kontürü mavi doku, şehir merkezinde 2×2 hücrelik tek iri turuncu kare; şehri bilinmeyen "KIBRIS" için ülkenin tamamı turuncu. Markup hero'daki gibi deterministik string (dangerouslySetInnerHTML).role="img"+ "İstanbul Türkiye haritasında". Üniversite sayfasının konum kartı (universite-konum-haritasi.tsx) aynı bileşeni kullanır. Veri taşıyan pikseldir (§1.2), süs ayraç yasağına girmez. - Yakınlaşma (Bilal, 24 Eyl 2026: "ilin bulunduğu yere doğru harita büyüsün, sayfa
yüklendikten sonra delay ile motion ile"): SSR tüm ülke; yüklenince 0,7 s sonra viewBox 1,1 s
boyunca güçlü ease-out (
0.23, 1, 0.32, 1) ile ilin çevresindeki kutuya kayar — en çok 2,4 kat (ülke haritasında şehir işaretine 1,8 kat), kutu SVG ile aynı oranda ve harita dışına taşmaz. Kareler büyür, il kadraja gelir; ısı fırçası viewBox'ı canlı okur. Hareketi azalt açıkken kutuya doğrudan atlanır. Sayfa başına tek yakınlaşma; imleçle geri alınmaz.
5. Yerleşim
5.1 Genel
- Sayfa kabı:
mx-auto max-w-6xl px-4. Metin sütunu:max-w-xl(paragraf) /max-w-2xl–max-w-3xl(uzun içerik). - Landing bölümü:
<section className="py-20 sm:py-24">; alt sayfalarpy-12–py-16. - Bölüm başlık bloğu (kanonik):
Ardından içerik
<div className="flex flex-col items-center gap-4 text-center"> <SectionEyebrow>Sorun</SectionEyebrow> <h2 className="font-heading text-3xl font-bold sm:text-4xl">…</h2> <p className="max-w-xl text-lg leading-relaxed text-slate-600">…</p> </div>mt-12; kart ızgarasıgrid gap-6 md:grid-cols-3(yalnızca gerçekten üç eşdeğer öğe varsa; üçe tamamlamak için içerik uydurulmaz). - Alt sayfa başlığının altında
PagePixelDivider(mt-6/mt-8), her sayfada farklı seed. - Landing bölümleri arasında çizgi yok;
PixelDivider(mx-auto w-56, farklı seed). - Boşluk ölçeği: 4 → 6 → 8 → 12 → 16/20 → 24. Ara değer (
mt-7,gap-5) yeni yerde açılmaz. - Mobil önce (trafiğin ~%90'ı 375 px): uzun adlar sarar (§4.15); tablo yatay kaydırmaz,
dar ekranda sütunlar satır altına iner; sabit alt çubuk klavyeyle çakışmaz;
vhyerinedvh.
5.2 Geniş ekran dışında ortala
Alt sayfaların (katalog, detay) başlık bloğu lg (1024 px) altında ortalı, lg'de sola
yaslıdır — mobil uygulama gibi telefonda ve tablette her şey ortada, masaüstünde tablo ve
kartlarla aynı hizada:
- Yol satırı:
flex flex-wrap items-center justify-center gap-1.5 text-sm text-slate-500 lg:justify-start - Logo + h1:
flex flex-col items-center gap-4 text-center lg:flex-row lg:text-left— logo telefonda başlığın üstünde, ortada. - Kimlik hapları:
flex flex-wrap items-center justify-center gap-2 lg:justify-start - Özet paragraf:
mx-auto … text-center lg:mx-0 lg:text-left - Sayfa ayracı:
mx-auto … lg:mx-0; liste bölümü ve grup başlıklarıtext-center lg:text-left. - Ortalanmaz: liste/tablo satırlarının içeriği (göz satırdan satıra kayarken ortalı liste yorar), form alanları, uzun rehber metni.
- Alt sayfa (§4.10) içeriği her ekranda ortalıdır.
5.2.1 Sayfalama — Sayfalama, sayfalama.tsx
Haplar h-11 (44 px), hover §2.1. Telefonda (sm altı) tek satır kalsın diye yalnız Önceki ·
aktif sayfa · Sonraki görünür; diğer numaralar hidden sm:inline-flex ile HTML'de durur
(tarayıcı botları tüm sayfaları görür). 375 px'te 7 sayfalık şerit iki satıra kırılıyordu.
5.2.2 Dilim sekmeleri (Hayal / Dengeli / Güvenli) — program-tablosu.tsx
Tek satırda üç hap 375 px'e sığmıyordu (418 px, sayfa yana kayıyordu). Telefonda
grid w-full grid-cols-3, hapın içinde ikon+ad üstte, sayı altta; sm'den tek satır. Hap en az
44 px (min-h-11), hover §2.1.
5.2.3 Karşılaştırma tablosu (ana sayfa) — yatay kaydırma yok
Dört sütunlu tablo yalnız lg'de. Altında her özellik kendi satırında (başlık ortalı
text-base font-semibold), üç cevap altında üç sütun; KolayTercih sütunu bg-primary/5
kutuda. Sütun adları üstte yapışık: sticky top-24 sm:top-32 (site başlığı telefonda 96 px,
sm'den itibaren 128 px — ölçüldü). Bilal, 25 Eyl 2026: "kaydırması gerekiyor, olmamalı".
5.3 Verimli ve havadar
- İlişkili öğeler yan yana dizilir (iki sütun) — tek sütunda alt alta uzayan panel yapılmaz.
- Yan yana dizmek "hepsini tek şeride sıkıştırmak" değildir: 23 Eyl'de denenen yatay "bilgi şeridi" (harita dahil altı değer tek satırda, yana kayan) reddedildi — harita küçüldü, sayılar ezildi, ekran kalabalıklaştı.
6. Derinlik, katman ve hareket
Derinlik gölgeyle değil piksel katmanı ve hareket farkıyla verilir: başlık bloğu gövdeden hafif hızlı akar (Parallax strength={16} başlık, 7 içerik, 26 ayraç). Kartlar hover'da 4 px yükselir. Modal arka planı bg-black/10 + hafif blur. Yığın: içerik < sabit bar < çekmece/modal (z-50).
Hareket kuralları (Apple, motion/react):
- Varsayılan yay:
{ type: "spring", bounce: 0, duration: 0.35 }— sekmesiz, sakin. Sekme yalnızca kullanıcı bir şeyi fırlattıysa (sürükle-bırak). - Giriş ve çıkış aynı yoldan (aşağıdan geldiyse aşağı gider).
- Basınca anında tepki:
active:scale-[0.97](buton),[0.99](geniş satır),[0.96](çarpı). - Hover'da ok
translate-x-0.5kayar; kart yükselmesi yalnız landing kartında. - Kaydırmaya bağlı tetik
IntersectionObserverile (kaydırma dinleyicisi değil). - "Hareketi azalt": kayma/yay yok, yalnız opaklık (
useReducedMotion,motion-reduce:transition-opacity).
7. Yap / Yapma
| Yap | Yapma (AI izi) |
|---|---|
Rozet için SectionEyebrow |
Badge import'u, elle rounded-full border … px-3.5 py-1.5 span |
CTA: metin + sondaki ArrowRight |
Başta Sparkles/yıldız ikonu, "✨" |
| Nötr = slate; vurgu = primary mavi; aksiyon ve hover = orange-500 | indigo/purple primary, mor→mavi gradyan, gray/zinc nötr |
Hover'da tek turuncu (orange-500); liste satırı adı mavi (§2.1 istisnası) |
Liste dışında hover'da mavi; aynı ekranda orange-600 yazı + orange-300 kenarlık |
Kart: rounded-2xl border-slate-200 bg-white shadow-sm |
Her şeyde rounded-3xl, camsı backdrop-blur kartlar, parlama gölgesi |
| Sayı kartın en iri öğesi, ikon sağda küçük | İkon üstte büyük, sayı küçük; BÜYÜK HARFLİ text-xs etiket |
| Sayfada ≤4 özet sayı, fazlası ayrıntı satırı → alt sayfa | 6+ kartı sayfaya dizmek ya da hepsini yatay şeride sıkıştırmak |
| Harita gibi nefes alanını olduğu gibi bırakmak | Nefes alanını küçültüp bilgi şeridine gömmek |
| Alt sayfada kartsız, ortalı, tek ekrana sığan içerik | Çekmece içinde çerçeveli kart; bölümler arasında süs piksel ayraç |
| Gösterge kareleri masonry (kaymış sütun, farklı boy) | Hizalı eşit ızgara; 8 px'lik "neredeyse hizalı" kaymalar |
| Liste satırında ad sarar, sayı alt satıra iner | truncate ile yarım ad; 32 px satır butonu |
Hareket: Reveal, piksel ısısı, kt-unblur, sekmesiz yay; animate-ping yalnızca "şu anda canlı" noktasında |
Her elemanda fade-up, whileHover scale 1.05, animate-bounce |
Başlık font-heading, vurgu font-bricolage |
Inter/Roboto/serif, tek kelimelik BÜYÜK HARF etiket, 10–11 px yazı |
| Risk rengi + metin etiketi; tür ayrımı ikonla | Renk tek başına, "yerleşirsin" gibi vaat cümlesi |
| Üç kart yalnızca üç gerçek öğe varsa | Hero + üç kart iskeleti refleksi |
| Beyaz zemin, tek koyu vurgu yüzeyi | İstenmemiş karanlık mod, dark: sınıfı |
Kapatma çarpısı DialogContent varsayılanı |
Başka boyut/renkte çarpı |
Form alanı hap: Input/SelectTrigger varsayılanı (h-12 rounded-full), yalnız yerleşim sınıfı eklenir |
Kullanım yerinde h-9 rounded-lg bg-background; kenarlıklı ham <input>; md:text-sm |
8. Duyarlılık
- Kırılma noktaları: 375 (temel), 640
sm:, 768md:, 1024lg:. Her bileşen önce 375'te tasarlanır. Ortalı ↔ sola yaslı geçişilg'dedir (§5.2). - Dokunma hedefi en az 44 px (
h-11,size-11); satır içi küçük butonh-9yalnızca masaüstü tablo aksiyonlarında. - Başlık ölçeği bir kademe düşer (
text-3xl→sm:text-5xlalt sayfa h1), gövde 16 px altına inmez. - Modal genişliği
max-w-[calc(100%-2rem)]; ayrıntı her zaman çekmecede (Drawer), alttan açılır. - Çekmece içeriği 375×812'de kaydırmasız sığar (§4.10).
prefers-reduced-motion: her animasyonun sade karşılığı var (motion-reduce:animate-none,.kt-unblur-sade,useReducedMotion).
9. Ajan için brief şablonu ve iş akışı
9.1 Brief
Yeni bir UI işi istenince önce şu beş satır doldurulur, sonra kod yazılır:
Amaç: Kim, hangi ekranda, ne yapacak? (ör. veli, /paket, fiyatı karşılaştırıp satın alacak)
Referans: Sitedeki en yakın mevcut ekran/bileşen (dosya yolu). Yoksa üniversite sayfası.
Tek kaynak: Kullanılacak kanonik parçalar (SectionEyebrow, Button+ArrowRight, OzetKart, AkademikAyrinti, NavBaslik…)
Durumlar: boş / yükleniyor / hata / başarılı / girişsiz / kredisiz — hangileri var?
His: Ekranın tek ana işi ne? Hangi 4 sayı önde, ne bir dokunuş derinde?
"Modern", "temiz", "şık" gibi yön belirtmeyen kelimeler kullanılmaz; yön = bu dosya.
9.2 Ölç, tahmin etme
Bu dilde sorunların çoğu koddan görünmez (taşma, sığma, hizalanma). Tasarım işinde:
- Sığma: metin genişliğini tarayıcıda ölç (gizli
span+getBoundingClientRect); "sanırım sığar" ile yazma. Örnek: özet kartında "13.889" 36 px'te 95 px. - Hizasızlık: masonry'de karelerin
top/bottomdeğerlerini ölç; komşu fark ≥ 24 px. - Tek ekran: çekmecede kaydırma kabının
scrollHeight≤clientHeight(375×812). - Genişlikler: 375 / 768 / 1280 px'te bak; ortalı ↔ sola yaslı geçişini
lg'de doğrula. - Uç veri: en uzun ad ("Adana Alparslan Türkeş Bilim ve Teknoloji Üniversitesi"), en büyük sayı, verisi eksik kurum (URAP'ta olmayan, istatistiği olmayan).
9.3 Tuzaklar (23 Eyl 2026'da yaşandı)
- Prettier'ı toplu çalıştırma. Depo prettier düzeninde değil; bir dosyayı prettier'dan geçirmek yüzlerce satırlık biçim farkı üretir ve başkasının kaydedilmemiş işine karışır. Yalnız kendi yazdığın satırları elle düzenle.
- Geliştirme sunucusunda ilk tık. Kod değişikliğinden hemen sonra sunucu derleyip sayfayı tazeleyebilir; o anda yapılan tıklama boşa gider. "Çekmece açılmıyor" demeden önce sayfa hazır olduktan sonra tekrar dene.
- Sayfada ikinci
<header>. Bölüm sayfasında içerik<header>'ı var; site üst çubuğunuquerySelector("header")ile değil, bilinen bir öğeninclosest("header")'ı ile bul. - "use client" dosyasından sabit import etme. Sunucu bileşeni o sabiti değer olarak değil istemci referansı olarak alır; paylaşılan sabit ayrı dosyada durur ya da elle yazılır.
9.4 Site taraması için denetim uyarıları
pnpm tasarim:denetim bu dilin eski izlerini uyarı olarak listeler (lint'i kırmaz, dönüşüm
listesidir): minik-yazi (10–11 px), buyuk-harf-etiket (uppercase + tracking-wide),
mavi-hover (§2.1), iri-sayi-tabular (Cal Sans + tabular-nums), ham-input (§4.6 kenarlıklı ham input).
mavi-hover §4.15 kanonik liste satırı adını (text-base font-semibold leading-snug +
hover:text-primary hover:underline aynı satırda) kendiliğinden atlar — istisna uyarı
vermez (Bilal'in kararı, 24 Eyl 2026). Eski truncate text-sm adlar yine uyarır; önce §4.15'e
çevrilir.
Bir ekranı dönüştüren ajan o ekrandaki uyarıları sıfırlar ya da neden kaldığını yazar.
Bilerek bırakılan uyarılar (24 Eyl 2026 taraması sonunda 12):
meraklisina-demo.tsx(8 × minik-yazi): SVGviewBox640 birim; 375 px'te 0,54 ölçekle çiziliyor, 11 birimlik yazı ekranda 5,9 px (ölçüldü). 12'ye çıkarmak yalnız 6,5 px eder ve etiketler çakışır — çözüm telefona ayrı (dikey) çizim; ayrı iş.secimlerim-paneli.tsx(4): hiçbir yerde kullanılmıyor (ölü kod); dönüştürülmedi, silinmesi ayrı iş.
9.5 Bitirmeden
pnpm tasarim:denetim sıfır hata (uyarılar raporda listelenir) + 375 px'te tek bakış (taşma,
üst üste binme, dokunma hedefi, çekmece tek ekran) + §9.2 ölçümleri.
10. Samimi ton, ilerleme ve kutlama (öğrenci ekranları)
Bilal'in isteği (25 Eyl 2026): "Duolingo gibi basit ve oyunsu, Apple gibi irdeleyici, samimi."
Araştırma ve kaynaklar: docs/tasarim/2026-09-25-samimi-arayuz-arastirmasi.md. Özü: bizim
öğrencimiz için samimi = güven; neşe dayatılmaz.
10.1 Her ekranın tek cümlelik cevabı
- Öğrenci ekranı
h1ile açılır ve ilk paragraf öğrencinin kendi durumunu sayıyla söyler. Örnek (/sonuc,SonucBasligi): "85.000. sıradasın (Sayısal). 4.760 program sana açık; aşağıda riskine göre ayrıldı." - Altında liste durumu (
ListeDurumuSatiri): boşsa ne yapılacağı, doluysa "Listende 5/24 program · 19 yer kaldı" düğmesi (çekmeceyi açar).
10.2 İlerleme
- Sayıyla ve dürüst: "7/24", "Adım 2/3: Şehir". Yüzde, sahte hız, yapay ilerleme yok.
- Sihirbaz adım göstergesi adlı (Alan · Şehir · Öncelik); dolum
scale-xile soldan,duration-300 ease-[cubic-bezier(0.23,1,0.32,1)], hareketi azalt'ta geçişsiz. - Liste çekmecesinde risk dağılımı metinle (
RiskEtiketi+ sayı). Riskleri bilinen 6+ tercihli listede güvenli yoksa tek cümle ipucu — vaat değil, gerekçe.
10.3 Kutlama
- Yalnız öğrencinin kendi yaptığı küçük adımda: ilk program (1/24) ve dolu liste (24/24). Bir kez, sakin bir bildirimle; aradaki eklemeler sessiz (düğme ✓, sayaç artar).
- Yerleşme gibi sonuçlarda kutlama yok; açıkta kalan öğrenciye neşeli dil yok.
- Hareket:
starting:scale-95 starting:opacity-0+ güçlü ease-out, 300 ms altı; konfeti, ses, sekme (bounce) yok. Hareketi azalt'ta yalnız opaklık.
10.4 Metin
- Sen dili, etken çatı, fiil düğme ("Listemi aç", "Sıralamamı gir"). Şirin/zekice etiket yok.
- Hata: ne olduğu + ne yapılacağı; suçlama ve ünlem yok. "Hay aksi", "Eyvah", "Oops" yok
(denetim:
samimiyetsiz-unlem). "Buraya tıkla" yok; link ne açtığını söyler. - Bekleme metni "…" ile biter ("Kontrol ediliyor…").
- "Kredi" dili: gerçek parayı sanal birime çevirmek aldatıcı desenler listesinde ("para birimi karmaşası"). Kredinin TL karşılığı pakete göre değiştiği için (≈4–5 TL) ekranda TL gösterip göstermemek Bilal'in kararına bırakıldı (25 Eyl 2026, açık).
10.5 Geri alınabilir işlem
- Listeden çıkarma ve listeyi temizleme anında olur ama 8 sn "Geri al" bildirimi verir;
çıkanlar eski sıralarına döner (
geriAlinabilirCikar,liste-cekmecesi.tsx). Beklenen işlemde "Emin misin?" penceresi açılmaz (Apple: beklenen kayıpta uyarı yok).
10.6 Anlamsal yapı
- Sayfa başına tek
h1; bölümlerh2. Başlıklardatext-balance. - Odak almayan durum değişikliği ekran okuyucuya duyurulur:
role="status"(liste sayacı, sihirbaz adımı, bekleme). Bildirimler (sonner) bunu kendisi yapar. - Açılır satır:
aria-expanded+aria-controls(APG disclosure). - Site geneli "İçeriğe geç" linki
layout.tsx'te; içerik kabı#icerik. - Çekmece kaydırma alanı
overscroll-contain.
10.7 Almadıklarımız (Duolingo'dan)
Seri (streak), kayıp korkusu, puan/XP, rozet koleksiyonu, liderlik tablosu, maskot, sahte aciliyet/kıtlık, utandırarak onay. Tercih günlük alışkanlık değil, tek seferlik kaygılı bir karar.
10.8 CTA bandı — CtaBandi, src/components/cta-bandi.tsx
Kanonik CTA bandı — mavi zemin + PixelMasonry (Bilal'in kararı, 24 Eyl 2026: "Kendi Listem"
çekmecesindeki bandın eski hâli daha güzeldi; örnek odur). Kabuk tek kaynaktan gelir, içerik
çağıranındır:
<CtaBandi seed={8}> {/* buyuk: ortalı, px-5 py-8 sm:p-12 */}
<h2 className="font-heading text-2xl font-bold text-balance sm:text-3xl">…</h2>
<p className="mx-auto mt-3 max-w-xl text-base leading-relaxed text-white/90">…</p>
<Button size="lg" className="mt-6 w-full cursor-pointer bg-orange-500 text-white hover:bg-orange-600 active:scale-[0.97] sm:w-auto">
Yapay Zeka listemi kur<ArrowRight className="size-4" aria-hidden />
</Button>
</CtaBandi>
<CtaBandi etiket="div" boyut="kompakt" className="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between sm:gap-4">
…başlık + alt satır solda, buton sağda (çekmece)…
</CtaBandi>
Çekmecedeki kompakt bandın açık hâli (bileşenin ürettiği sınıflar):
<div className="relative isolate flex flex-col gap-3 overflow-hidden rounded-2xl bg-primary px-5 py-4 text-left text-white sm:flex-row sm:items-center sm:justify-between sm:gap-4 sm:py-5">
<div aria-hidden className="pointer-events-none absolute inset-x-0 -inset-y-6 -z-10 text-white">
<PixelMasonry seed={8} />
</div>
<div className="min-w-0">
<p className="font-heading text-xl font-bold sm:text-2xl">Risk analizini biz yaptık</p>
<p className="mt-1 hidden truncate text-sm leading-relaxed text-white sm:block">
Her seçimin yerleşme riski hazır — son kararı sen ver.
</p>
</div>
<Button size="lg" className="h-12 w-full shrink-0 cursor-pointer bg-orange-500 text-white transition-colors duration-200 hover:bg-orange-600 active:scale-[0.97] sm:w-auto">
Listemde aç
<ArrowRight className="size-4" aria-hidden />
</Button>
</div>
- Zemin
bg-primary(sitenin mavisi), köşerounded-2xl, yazı beyaz; alt satır da beyaz (text-white,slate-300değil). Piksel dokusuPixelMasonry(Bilal, 24 Eyl 2026: "arka planda büyüklü küçüklü, masonry şeklinde"): 2–4 hücrelik kareler 4×4'lük makro hücrelere kaymış düşer, çakışmaz ama hizaya girmez. Doku kabın gerçek ölçüsüne göre üretilir (ResizeObserver; sabit çizimi ölçeklemek yüksek kartlarda görünen kısmı boş banda düşürüyordu, 24 Eyl 2026'da yaşandı): kısa kenarın %30'u kadar kenar çerçevesi kenara doğru yoğunlaşır, orta tamamen boş; küçük kare yok (2–4 hücre), iri kare daha silik; durağan — imleç ısı fırçasına katılmaz, üzerine gelince hiçbir şey olmaz (Bilal, 24 Eyl 2026); yalnız seyrek turuncu vurgu kareleri kendi kendine yavaşça nefes alır. Kaprelative isolate overflow-hidden, doku-inset-y-6 -z-10. Eşit ızgaralı eskiPixelFieldkaldırıldı. - Tek turuncu buton, metin önce ok sonda (§4.1). Telefonda alt alta ve tam genişlik;
sm'de yan yana, buton sağda. - Büyük (sayfa kapanışı) hâlinde aynı band ortalı ve iri:
px-5 py-8 text-center sm:p-12,-inset-y-10, h2font-heading text-2xl font-bold sm:text-3xl, paragraftext-white/90. - Kullanıldığı yerler:
/sonuc'taki üç panel (sihirbaz, giriş bekleyen, "24 tercihlik listen hazır"),/meraklisinakapanış kartı (DemoKapanisCta), katalog altındakiCtaSiraFormkart varyantı, "Kendi Listem" çekmecesinin altı (kompakt), katalog üstü kompakt satırın kayıtlı sıralamalı hâli ("Sıralaman … tabanlarının neresinde? · Sıralaman kayıtlı: …"; Bilal, 24 Eyl 2026: "bu kısma piksel dokusu ekle"). O satır CLS için teksectioniçinde iki hâl taşıdığındanCtaBandi'yi sarmaz; kompakt bandın sınıf setini birebir alır (relative isolate overflow-hidden rounded-2xl bg-primary px-5 py-4 text-left text-white sm:py-5+ ilk çocukPikselZemin), kenarlık saydam kalır ki iki hâlin kutusu aynı olsun. Aynı sayfadaki iki band farklıseedalır.
Piksel zemin yalnız CTA ve başlık yüzeylerinde — PikselZemin, src/components/piksel-zemin.tsx
(Bilal, 24 Eyl 2026: önce "her CTA benzeri kısmın arkasında olmalı", sonra "/sonuc'taki kartın
arkasına da piksel koymuşsun; pikseller CTA'larda olacak sadece"). CTA yüzeyi = çağrı yüzeyi:
mavi CtaBandi, koyu kapanış kartı PikselCtaYuzeyi, arama penceresindeki koyu kart.
Ton ikidir: ton="koyu" (renkli zemin, beyaz kareler) ve ton="acik" (beyaz zemin,
text-slate-400 kareler; turuncu vurgu kareleri aynı). Bilal (24 Eyl 2026): "her kısımda mavi
arka kullanmışsın, çeşitlendir; beyaz arka planda piksel de güzel görünüyor" — bu yüzden
CtaBandi ton="beyaz" (slate kenarlık, koyu yazı, paragraf text-slate-600) var ve aynı
sayfada iki bant üst üste gelmesin diye dönüşümlü kullanılır: /universiteler altı ve
/meraklisina kapanışı beyaz; şehir sayfası altı, /sonuc panelleri, çekmece altı mavi.
Şehir sayfasının başlık yüzeyi (§4.17) de açık tonlu piksel zemindir. Beyaz içerik kartlarına (tadımlık, /listem üretim/kilit kartları, paket kartı, kaydet
bandı, katalog üstü kompakt satırın form hâli, boş durumlar, sıralama-yok sayfası)
konmaz — 24 Eyl'de denendi ve geri alındı. Aynı kompakt satırın kayıtlı sıralamalı hâli
ise formsuz tek butonlu bir çağrı olduğundan mavi banttır ve dokuyu alır (yukarıda). Kap relative isolate overflow-hidden; zemin ilk çocuk; kareler beyaz.
Doku kabın gerçek ölçüsüne göre üretilir: yalnız kenar çerçevesinde (kısa kenarın %30'u), orta
tamamen boş; küçük kare yok, 2–4 hücrelik (17/27/37 px) kareler, iri olan seyrek ve daha
silik (Bilal: "çok fazla piksel, küçük olanlar hiç olmasın").
Kapanış yüzeyi — PikselCtaYuzeyi, src/components/piksel-cta-yuzeyi.tsx (yalnız ana
sayfa kapanışı "Tercih listen, pişmanlık listesi olmasın"). Bilal'in kararı (24 Eyl 2026):
"orası bayağı iyiydi; özellikle 24'lük pikseller tablo gibi — bu tür kreatif, interaktif şeyler
çok güzel." Arama penceresindeki kartın dili: rounded-3xl border border-blue-400/20 bg-slate-950 text-white, arka planda PixelMasonry (seed ile), tek turuncu CTA. Yazılıp silinen satır
yok (Bilal, 24 Eyl 2026: kaldırıldı); FUNNEL_METINLERI yalnız arama penceresindeki kartta
(arama-funnel-karti.tsx) kalır.
- Kreatif —
PikselListe,src/components/piksel-liste.tsx: 24 kare = 24 tercih, hero'nun nokta ölçüsüyle (hücre 10, nokta 7.4, rx 2). Örnek modda liste kendini kurar (5 hayal · 13 dengeli · 6 güvenli, 110 ms arayla), yalnız ekrandayken. İmleç yakın kareleri büyütür; kart içindeki düğmeye imleç/odak gelince 24 kare birden dolar; dokunmada basılan kare ve komşuları nabız atar (kt-piksel-nabiz). Hareketi azalt: dolu, durağan. Renk her zamanPikselListeAciklamametniyle. - Piksel tablosunun arkası boş kalır (Bilal, 24 Eyl 2026: "arkasına çok piksel yığılmış"):
tablo kabı
haricile zemine verilir, doku onun çevresini (14 px payla) her genişlikte boş bırakır. Kural genel: bir kreatif ya da iri sayı piksel zeminin üstüne geliyorsaharicile boşaltılır; doku ile kreatif üst üste binmez. - Bu yüzey sayfada bir kez ve yalnız kapanışta durur; ara paneller ve çekmece mavi banttır. Yeni bir kreatif fikri (veriyi piksele çeviren, imlece tepki veren) önce burada denenir.
- Çekmece başlığında denenen "gerçek liste" pikseli (12×2, her kare tercihin riski) kaldırıldı: başlığı çok dolu gösteriyordu (Bilal, 24 Eyl 2026). Başlık sayı + ilerleme çubuğu + risk dağılımı metniyle kalır.