feat(ui): complete phase 4 Poyraz UI foundation

This commit is contained in:
poyrazavsever
2026-07-16 23:20:30 +03:00
parent 5d863280bf
commit 561af11b70
58 changed files with 2555 additions and 7806 deletions
@@ -0,0 +1,145 @@
# Faz 4 — Poyraz UI v3 foundation
Tarih: 2026-07-16
Bu faz, freelancer ve portal sayfalarının dikey dönüşümünden önce ortak UI sözleşmesini kurar. Sayfa bazlı bilgi mimarisi ve görsel revizyonlar Faz 56'da kullanıcı yönlendirmesiyle yapılacaktır.
## Uygulanan temel
- `poyraz-ui` `3.0.2` sürümüne yükseltildi; hem pnpm hem npm lockfile'ları eşitlendi.
- Tailwind v4 girişine `poyraz-ui/preset.css` eklendi.
- Atom, molecule ve organism importları yalnızca ilgili package subpath'inden yapılıyor.
- Freelancer ve portal shell'i aynı Poyraz Sidebar organism bileşimini kullanıyor.
- Masaüstü daraltma, mobil overlay ve mobil aç/kapat state'i `SidebarProvider` tarafından yönetiliyor.
- Hesap menüsü custom event yönetimi yerine Poyraz `DropdownMenu`; icon-only shell aksiyonları Poyraz `Tooltip` kullanıyor.
- Root feedback katmanı Poyraz `Toaster`; auth bildirimleri Poyraz `Alert` ve `toast` kullanıyor.
- Auth alanları ve loading ekranları local kopyalar yerine Poyraz atomlarını kullanıyor.
- Instance adı ve açık/koyu logo shell ile auth yüzeylerine taşındı.
## Import ve ownership kuralı
```ts
import { Button, Input, Typography } from "poyraz-ui/atoms";
import { Alert, Dialog, Form, Select, toast } from "poyraz-ui/molecules";
import { DataTable, Sidebar } from "poyraz-ui/organisms";
```
`poyraz-ui` package root importu kullanılmaz. Genel amaçlı UI primitive'i `components/ui` altında yeniden yazılmaz. Neta'ya özgü durum veya davranış, Poyraz bileşenlerinden `components/system` altında compose edilir.
İzin verilen local davranış yardımcıları:
- `OfflineIndicator`: browser bağlantı durumu davranışı.
- `PendingLink`: Next.js navigasyon pending davranışı.
- `PendingSubmitButton`: server action pending davranışı; görsel primitive olarak Poyraz `Button` kullanır.
Bu sınır `pnpm phase4:ui-boundary` ile otomatik doğrulanır.
## Typography ve page header
Poyraz `Typography` bütün yeni sayfalarda metin semantiğinin kaynağıdır:
| Rol | Poyraz variant | HTML semantiği |
| --- | --- | --- |
| Sayfa başlığı | `h1` | `h1` |
| Bölüm başlığı | `h2` / `h3` | sıradaki doğru heading seviyesi |
| Kart başlığı | `h4` / `large` | bağlama göre `h2``h3` |
| Gövde | `body` / `p` | `p` |
| Yardımcı açıklama | `muted` | `p` |
| Metadata | `caption` / `small` | `span` veya `p` |
Yeni liste ve detay sayfaları `components/system/page-header.tsx` bileşimini kullanır. Header sırası: isteğe bağlı eyebrow, tek `h1`, kısa açıklama, secondary aksiyonlar ve en sağda bir primary aksiyon. Bir görünümde birincil aksiyon sayısı bir olmalıdır. Secondary aksiyonlar `secondary`, `outline` veya `ghost`; riskli aksiyonlar yalnızca `destructive` variant kullanır.
## Form standardı
İki form yolu vardır:
1. Basit Server Action formları native `<form>` ile; görünür Poyraz `Label`, Poyraz `Input`/`Textarea`/`Select`, alan yanında açıklama ve inline hata kullanır.
2. Client-side etkileşimli veya çok alanlı formlar `react-hook-form` ile Poyraz `Form`, `FormField`, `FormItem`, `FormLabel`, `FormControl`, `FormDescription` ve `FormMessage` bileşimini kullanır. Zod doğrulaması gerektiğinde mevcut resolver katmanı kullanılır.
Kurallar:
- Placeholder label yerine geçmez.
- Server ve client aynı Zod/domain sözleşmesine göre doğrular; client doğrulaması güvenlik sınırı değildir.
- Alan hatası `FormMessage` veya alanın hemen altındaki inline metinle gösterilir. Toast tek başına form hatası değildir.
- Submit durumu Poyraz `Button` üzerindeki `loading`, `disabled` ve `aria-busy` proplarıyla gösterilir.
- Başarılı, formun dışında etkisi olan işlem toast ile; kullanıcının karar vermesi gereken veya kalıcı bilgi inline `Alert` ile gösterilir.
## Status-to-Badge standardı
Merkezi eşleme `components/system/status-badge.tsx` içindedir.
| Anlam | Örnek status'ler | Badge variant |
| --- | --- | --- |
| Başarılı/çalışır | `active`, `accepted`, `completed`, `done`, `paid` | `success` |
| Süreçte/bilgi | `in_progress`, `sent` | `info` |
| Bekliyor/dikkat | `pending`, `paused` | `warning` |
| Plan/taslak | `planning`, `planned`, `todo`, `draft` | `secondary` |
| Hata/risk | `overdue`, `rejected`, `revoked`, `expired` | `destructive` |
| Pasif terminal | `cancelled`, `archived` | `outline` |
Renk tek başına anlam taşımaz; badge her zaman Türkçe durum metni içerir.
## Feedback state standardı
`components/system/feedback-state.tsx` yeni sayfaların ortak state bileşimidir.
- Loading: layout'a yakın Poyraz `Skeleton`; kapsayıcıda `aria-busy` ve screen-reader label.
- Empty: nötr Poyraz `Card`, kısa neden ve mümkünse bir sonraki primary aksiyon.
- Error: Poyraz destructive `Alert`, kullanıcıya uygun açıklama ve retry aksiyonu.
- Forbidden: Poyraz warning `Alert`; var olmayan kaynağı açığa çıkarmayacak metin ve güvenli geri dönüş.
- Toast: kısa ömürlü, sayfalar arası kalıcı olmayan işlem sonucu.
- Inline Alert: kullanıcının okumadan devam etmemesi gereken, forma veya sayfaya bağlı durum.
## Overlay, confirmation, table ve KPI
- Geri döndürülemez işlem `components/system/destructive-confirmation.tsx` üzerinden açık `DialogTitle`, `DialogDescription`, vazgeç ve destructive onay aksiyonu ile kurulur.
- Kısa desktop formu `Dialog`, bağlamsal yan panel `Sheet`; küçük ekranda uzun/çok adımlı akış `Drawer` olur. Ekranı kaplayan özel div overlay yazılmaz.
- Veri listeleri seçim, arama, pagination, loading veya error gerektiriyorsa Poyraz organism `DataTable` kullanır. Basit iki sütunlu statik bilgiler native semantic table kalabilir.
- Dashboard metrikleri Poyraz `StatsCard` ile kurulur: kısa label, formatlanmış value, isteğe bağlı trend ve tek anlamlı icon. Renk yalnızca trend/durum bilgisini destekler.
## Branding token bridge
Branding servisi eski `--primary` benzeri uygulama tokenları yerine Poyraz v3 sözleşmesini server-side üretir:
- `--poyraz-primary` ve foreground/hover/active/scale rolleri
- `--poyraz-accent` ve foreground/hover rolleri
- `--poyraz-ring` ve `--poyraz-focus-ring`
- `--poyraz-radius-xs``--poyraz-radius-xl`
Değerler root `<html style>` içine SSR edilir; bu nedenle ilk render'da varsayılan renkten instance rengine geçiş parlaması oluşmaz. `system` renk modu ilk paint öncesi media query ile `.dark` sınıfına çevrilir ve işletim sistemi değişikliği dinlenir. Poyraz preset kalan surface, status, elevation, density ve motion rollerinin tek kaynağıdır.
Recharts içindeki eski `hsl(var(--...))` ifadeleri geçerli Poyraz CSS renk tokenlarına taşındı.
## Local primitive ve dependency sonucu
Kaldırılan local generic primitive'ler: Button, Card, Checkbox, Dialog, DropdownMenu, Field/Form, Input/Label, Select, Separator, Skeleton, Textarea ve Toast/Toaster. Kullanılmayan eski toast hook'u ve `next-themes` provider'ı da kaldırıldı.
Poyraz'ın kendi dependency ağacında yönettiği `@base-ui/react`, doğrudan Radix paketleri, `radix-ui`, `class-variance-authority`, `shadcn`, ayrıca kullanılmayan `@iconify/react` ve `next-themes` doğrudan Neta dependency listesinden çıkarıldı. Poyraz molecule entrypoint'i dinamik Mermaid importunu build sırasında çözdüğü için package'ın optional peer'i `mermaid` açık dependency olarak eklendi. Sonuçta doğrudan dependency sayısı net 14, pnpm kurulum ağacı yaklaşık 112 paket azaldı.
## Erişilebilirlik foundation kuralları
- Heading hiyerarşisi semantik component proplarıyla korunur.
- Icon-only aksiyonlar görünür label yoksa `aria-label`; bağlam açıklaması gerekiyorsa Tooltip kullanır.
- Dialog/Sheet/Drawer title ve description olmadan yayınlanmaz.
- Focus ring utility ile kapatılmaz; Poyraz focus tokenı branding primary rengine bağlıdır.
- Loading ve disabled görsel class taklidiyle değil component proplarıyla kurulur.
- Global reduced-motion kuralı ve component seviyesinde `motion-reduce` korunur.
- Durumlar renk yanında metin ve gerektiğinde icon ile anlatılır.
Bu faz foundation sözleşmesini doğrular. Legacy feature sayfalarının tamamına uygulanması ilgili Faz 56 dikey dilimlerinin kalite kapısıdır.
## Doğrulama
```bash
pnpm phase4:ui-boundary
pnpm typecheck
./node_modules/.bin/eslint app/layout.tsx components/layout components/system components/auth components/error-toaster.tsx components/ui/offline-indicator.tsx components/ui/pending-link.tsx components/ui/pending-submit-button.tsx app/login/page.tsx app/register/page.tsx 'app/invite/[token]/page.tsx' server/branding/service.ts scripts/phase4-ui-boundary.mjs
pnpm phase3:storage-smoke
pnpm phase1:auth-smoke
pnpm build
git diff --check
```
Boundary testi v3 major sürümünü, preset importunu, Sidebar bileşimini, package subpath importlarını, izin verilen local UI dosyalarını ve kaldırılan duplicate UI bağımlılıklarını doğrular.
Foundation hedefli ESLint kontrolü temizdir. Repo genelindeki `pnpm lint`, henüz Faz 57'de taşınacak legacy feature/API dosyalarındaki mevcut `no-explicit-any`, `set-state-in-effect` ve benzeri borçlar nedeniyle bu fazda global kalite kapısı olarak kapatılmadı; master plandaki genel lint maddesi bu nedenle işaretlenmedi.