- Tür/il/süre satırı sm'den itibaren adla aynı satırda (SATIR_GRUP) - lg'de hücre dolgusu bir kademe az, satır düğmeleri 36 px (§8) - 1280 px ölçüm: bölüm listesi 83 → 61 px; /sonuc 68 px (uzun adda 92) - Telefonda değişiklik yok (44 px düğme, alt alta düzen) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
40 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 (
PixelFieldile). - İ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.
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
shadcn Input, Select, Textarea, Slider. Etiket her alanda; hata mesajı alanın altında, ne olduğunu ve ne yapılacağını söyler. Sayısal alanlarda uç değerler (0, negatif, 1.000.000 üstü) ele alınır.
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. 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. - 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. Etkileşimli değildir; rozet (§4.2) değildir.
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. - 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ı)
UniLogo boy="sm"adın solunda,items-start. - 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.
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.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ı |
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).
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.