feat(tasarim): görsel dilin tek kaynağı DESIGN.md, proje skill'i ve tasarım denetim betiği
All checks were successful
Deploy / deploy (push) Successful in 5m33s
All checks were successful
Deploy / deploy (push) Successful in 5m33s
- docs/tasarim/DESIGN.md: 9 bölümlük görsel dil belgesi (renk rolleri, tipografi, tek kaynak bileşenlerin sınıf dizileri, yerleşim, yap/yapma, brief şablonu) - kolaytercih-tasarim skill'i: UI işinde tetiklenir, belgeye götürür, örnek verir; tasarimci ve yazilimci ajanlarına skills: ile önyüklenir - scripts/tasarim-denetim.ts: 13 kural (Badge, CTA'da Sparkles, palet dışı ton, gradyan metin, parlama, hareket spam'i, çarpı, font); pnpm lint'e bağlandı - ui-ux-pro-max genel kataloğu skills'ten .agents/skills-devre-disi/ altına taşındı - AGENTS.md: DESIGN.md kuralı; rozet sınıfı koda göre düzeltildi (font-bricolage yoktu) - arama-funnel-karti: palet dışı text-cyan-300 → text-orange-500 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
181
docs/tasarim/DESIGN.md
Normal file
181
docs/tasarim/DESIGN.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# 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`); 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.
|
||||
|
||||
---
|
||||
|
||||
## 1. Görsel tema ve atmosfer
|
||||
|
||||
**Bir cümle:** Beyaz, bol nefesli, mavi bilgi + turuncu aksiyon; her yüzeyde küçük bir
|
||||
**piksel imzası** (hero'daki dot-matrix Türkiye haritasının dili) dolaşır.
|
||||
|
||||
- Zemin her zaman beyaz; koyu zemin yalnızca CTA bandı ve çekmece başlığı gibi tek bir
|
||||
vurgu yüzeyinde (`PixelField` ile).
|
||||
- İ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.
|
||||
- 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 (`.dark` token'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, linkler, kart hover kenarlığı |
|
||||
| **Aksiyon turuncusu** | `bg-orange-500 hover:bg-orange-600 text-white` | Funnel CTA butonları. Bir ekranda **tek** turuncu buton |
|
||||
| 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ı |
|
||||
| Gövde metni | `text-slate-600` | Paragraf, açıklama |
|
||||
| İkincil metin | `text-slate-500` | Meta bilgi, yardımcı satır |
|
||||
| Silik metin | `text-slate-400` | İpucu, devre dışı, placeholder |
|
||||
| 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ığı |
|
||||
| Hover zemini | `hover:bg-slate-100` | Çarpı, 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 |
|
||||
| Hata | `text-destructive`, `text-red-600` | Form hatası |
|
||||
|
||||
Kurallar:
|
||||
- Nötr yalnızca **slate**. `gray`, `zinc`, `neutral`, `stone` yazılmaz.
|
||||
- `indigo`, `purple`, `violet`, `fuchsia`, `pink`, `cyan`, `teal`, `lime`, `green`, `yellow`
|
||||
yeni kullanım açmaz. (`bg-violet-50 text-violet-600` tek bir mevcut durum çipidir; yeni yere taşıma.)
|
||||
- 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.ts` içindeki `RISK_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").
|
||||
|
||||
## 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ığı). 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, küçük etiketler/çipler, sayısal rozetler |
|
||||
| `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">`
|
||||
- Bölüm h2: `font-heading text-3xl font-bold sm:text-4xl` (istenirse `text-slate-900`)
|
||||
- Panel/kart h3: `font-heading text-xl font-bold` · liste satırı başlığı: `font-heading text-lg font-bold text-slate-900`
|
||||
- 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`
|
||||
- Gövde: `text-sm` (tablo, form, kart içi) ya da `text-base leading-relaxed` (açıklama)
|
||||
- Etiket/rozet metni: `text-xs font-semibold`
|
||||
- Yasak: Inter, Roboto, Arial, sistem fontu, serif, `font-[…]` keyfi font; tek kelimelik
|
||||
büyük harf etiketler (uppercase yok, rozet metni büyük-küçük harfli yazılır).
|
||||
|
||||
## 4. Bileşen stilleri (tek kaynaklar)
|
||||
|
||||
Bir eleman iki yerde görünüyorsa stili tek kaynaktan gelir. Aşağıdakiler yeniden tasarlanmaz.
|
||||
|
||||
### 4.1 Buton — `src/components/ui/button.tsx`
|
||||
- Her buton `rounded-full`; `h-9` varsayılan, `h-11`/`h-12` funnel CTA'ları (44 px dokunma hedefi), `size-9` ikon butonu.
|
||||
- Odak: `focus-visible:ring-3 focus-visible:ring-ring/50`; basınca `active:translate-y-px`.
|
||||
- **Turuncu CTA (kanonik):**
|
||||
```tsx
|
||||
<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>
|
||||
```
|
||||
Metin önce, ok sonda. Başta ikon yok. `Sparkles` yok. İstenirse `active:scale-[0.97]`.
|
||||
- İkincil: `variant="outline"`; 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`
|
||||
```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 ve nav butonları bu kuralın dışındadır (onlar etkileşimlidir).
|
||||
|
||||
### 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.
|
||||
|
||||
### 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-primary/30 hover:shadow-lg hover:shadow-primary/5">` + sağ üstte `<PixelCorner className="absolute right-4 top-4" />`.
|
||||
- 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/10` içinde `size-5 text-primary` ikon.
|
||||
- Gölge: `shadow-sm` varsayılan; hover'da `shadow-lg shadow-primary/5`. Başka gölge yok.
|
||||
|
||||
### 4.5 Risk çipi / etiketi
|
||||
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.
|
||||
|
||||
## 5. Yerleşim
|
||||
|
||||
- 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 sayfalar `py-12`–`py-16`.
|
||||
- Bölüm başlık bloğu (kanonik):
|
||||
```tsx
|
||||
<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>
|
||||
```
|
||||
Ardından içerik `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 üniversite/program adları `min-w-0` + sarma ya da `truncate`; tablo yatay kaydırmaz, kart olur; sabit alt çubuk klavyeyle çakışmaz; `vh` yerine `dvh`.
|
||||
|
||||
## 6. Derinlik ve katman
|
||||
|
||||
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`).
|
||||
|
||||
## 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 = orange-500 | `indigo/purple` primary, mor→mavi gradyan, `gray/zinc` nötr |
|
||||
| Kart: `rounded-2xl border-slate-200 bg-white shadow-sm` | Her şeyde `rounded-3xl`, camsı `backdrop-blur` kartlar, parlama gölgesi |
|
||||
| Hareket: `Reveal` (bölüm girişi), piksel ısısı, `kt-unblur`; `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 |
|
||||
| Risk rengi + metin etiketi | 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:`, 768 `md:`, 1024 `lg:`. Her bileşen önce 375'te tasarlanır.
|
||||
- Dokunma hedefi en az 44 px (`h-11`, `size-11`); satır içi küçük buton `h-9` yalnızca masaüstü tablo aksiyonlarında.
|
||||
- Başlık ölçeği bir kademe düşer (`text-3xl` → `sm:text-4xl`), gövde 16 px altına inmez.
|
||||
- Modal genişliği `max-w-[calc(100%-2rem)]`; çekmece (`Drawer`) mobilde alttan açılır.
|
||||
- `prefers-reduced-motion`: her animasyonun sade karşılığı var (`motion-reduce:animate-none`, `.kt-unblur-sade`).
|
||||
|
||||
## 9. Ajan için brief şablonu
|
||||
|
||||
Yeni bir UI işi istenince önce şu dört 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 "yok" yaz ve ana sayfa bölüm bloğunu al.
|
||||
Tek kaynak: Kullanılacak kanonik parçalar (SectionEyebrow, Button+ArrowRight, Card+PixelCorner, PagePixelDivider…)
|
||||
Durumlar: boş / yükleniyor / hata / başarılı / girişsiz / kredisiz — hangileri var?
|
||||
```
|
||||
|
||||
"Modern", "temiz", "şık" gibi yön belirtmeyen kelimeler kullanılmaz; yön = bu dosya.
|
||||
İş bitince: `pnpm tasarim:denetim` sıfır hata + 375 px'te tek bakış (taşma, üst üste binme, dokunma hedefi).
|
||||
Reference in New Issue
Block a user