İçeriğe geç

ECU Tuning Portal — Admin Panel Design System

Detay

Bu dosya admin panel için kanonik stil rehberidir. Tüm component’ler, sayfalar ve yeni eklemeler bu kurallara uyar. Hiçbir kural pazarlık konusu değildir.

Kaynak: Landing site design system (/public/ECU Tuning Portal Design System (1).zip içeriği), app/globals.css, repo dökümanları. Bu admin rehberi landing’den bire bir türetilmiştir — admin ve landing tek bir görsel dilde buluşur.


  1. Corners are CUT, not rounded. border-radius: 0 varsayılan. Köşeler clip-path ile kesilir (14px kart, 8px buton, 5-6px badge). Avatarlar ve blog tabloları istisna.
  2. Chakra Petch + uppercase + tracking. Her başlık, buton, uppercase label Chakra Petch 700, letter-spacing: 0.05em–0.12em. Istisna yok.
  3. Navy not black. Yüzeyler #060a10 → #0a111a → #0e1724. Saf siyah YASAK. Ayrım kontrastla değil, hairline border + colored glow ile sağlanır.

Bu üçü ihlal ediliyorsa kod reject edilir.


--brand-black: #060a10 /* <body>, sayfa scroll container */
--brand-dark: #0a111a /* Varsayılan kart arkaplanı */
--brand-panel: #0e1724 /* Elevated / modal / nav bg */

Not: Tonal fark sadece 3–5 luminosity puanı. Kart ile sayfa arasını yakalatan hairline border + 4px black drop + top-red-line üçlüsüdür.

--brand-red: #e8192c /* CTA, hot highlights, danger */
--brand-red-dark: #c41520 /* :hover */
--brand-red-bright: #ff3a4f /* badge/button wrapper outer */
--brand-teal: #00c8a0 /* ONLINE dots, "us" column, checkmarks */
--brand-teal-bright: #22ffdc /* badge wrapper outer */
--brand-amber: #f5a623 /* Warnings, VIP, star ratings */
--brand-amber-bright:#ffc761 /* badge wrapper outer */
--brand-blue: #4499ff /* Info links, tertiary accent */
--brand-blue-bright: #78b6ff
--brand-purple: #8a5adc /* Optional badge variant */
--brand-purple-bright:#c69aff

Renk kullanım kuralları:

  • Red = CTA + danger + VIP accent. Pazarlama tarafında “onlar” (rakipler) için de kullanılır ama admin panelde red = CTA/danger.
  • Teal = başarı, aktif, pozitif. ASLA primary button için kullanılma.
  • Amber = uyarı, kısmi destek, VIP flag, “coming soon”.
  • Blue = info, tertiary link.
--fg-1: #e6f2ff /* H1, vurgu, beyaz metin */
--fg-2: #c0d8ec /* Body text, varsayılan <p> */
--fg-3: #7fa4c4 /* Secondary, feature description */
--fg-4: #6987a5 /* Muted metadata, // prefix rengi · WCAG AA 4.81:1 on --brand-panel */

Asla rgba(255,255,255,0.X) gibi alfa-beyaz YAZMA. Bu tokenları kullan.

Her foreground token --brand-panel: #0e1724 üzerinde aşağıdaki kontrasta sahiptir. Yeni token eklenecekse minimum 4.5:1 (WCAG AA) sağlanmalı; muted/decorative dahi 3:1 altına düşemez.

TokenHexContrast vs --brand-panelWCAG sınıfıTipik kullanım
--fg-1#e6f2ff15.86:1AAAHeading, ana metin
--fg-2#c0d8ec12.24:1AAABody, varsayılan paragraf
--fg-3#7fa4c46.87:1AA (büyük: AAA)Secondary metin, feature desc
--fg-4#6987a54.81:1AAMuted metadata, sidebar grup label, // prefix

Tarihçe: --fg-4 2026-05-17’de #4e6880 (3.10:1, AA FAIL) değerinden #6987a5’e revize edildi (Trial Hub a11y audit bulgusu A4). Eski değer 10-12px font’larda label okunabilirliğini bozuyordu.

Yeni token eklerken kontrol:

def rel_lum(hex_c):
r,g,b = [int(hex_c[i:i+2],16)/255 for i in (1,3,5)]
f = lambda v: v/12.92 if v<=0.03928 else ((v+0.055)/1.055)**2.4
return 0.2126*f(r) + 0.7152*f(g) + 0.0722*f(b)
def contrast(a,b):
la,lb = sorted([rel_lum(a), rel_lum(b)], reverse=True)
return (la+0.05)/(lb+0.05)
print(contrast('#yeni-hex', '#0e1724')) # >= 4.5 olmalı
--border-white-4: rgba(255, 255, 255, 0.04)
--border-hairline: rgba(255, 255, 255, 0.055) /* Default card border */
--border-subtle: rgba(255, 255, 255, 0.10) /* Modal, glass */
--border-strong: rgba(255, 255, 255, 0.20) /* Ghost button border */

Solid beyaz border YASAK. Yüzeye göre şeffaflık uyum sağlar.

--grid-line: #1a2a3d /* Koyu grid (hero, section header) */
--grid-line-sm: #0f1d2e /* Yoğun grid (tech block) */

Admin panel ana içerik alanında rgba(255,255,255,0.025) grid (40x40px) kullan — landing ile tutarlı.


FontWeightRolKaynak
Inter400 / 500 / 600Body, paragraflarnext/font/google
Chakra Petch700TÜM başlıklar, butonlar, uppercase label’larnext/font/google
JetBrains Mono400 / 500 / 700Data, prices, badges, // PREFIX, metadatanext/font/google
Archivo (opsiyonel)800 / 900Editorial .ghost-num numeralsLanding’de var

app/[locale]/layout.tsx zaten bunları yüklüyor. Admin panel aynı font variables’ı kullanır.

  • Her başlık (h1-h6) → Chakra Petch 700 + letter-spacing: 0.05em + text-transform: uppercase
  • Her buton → Chakra Petch 700 + letter-spacing: 0.12em + uppercase
  • Her tablo header → JetBrains Mono 700 + 0.08em + uppercase
  • Badge → JetBrains Mono 700 + 0.14em + uppercase
  • Body → Inter 400 + sentence case
  • Data/id/date/metric → JetBrains Mono
  • Archivo sadece editorial numeral (.ghost-num) için
  • Negatif tracking (-0.02em) SADECE Archivo display’de
--h1-size: clamp(36px, 4.5vw, 48px)
--h2-size: clamp(28px, 3.4vw, 36px)
--h3-size: clamp(18px, 1.8vw, 22px)
--h4-size: 16px
--body-size: 14px /* Inter 400 */
--small-size: 12px
--micro-size: 11px /* Badge labels */
--stat-size: clamp(32px, 4vw, 48px) /* Chakra Petch 700, stat-value */
--lh-tight: 1 /* stat-value, fiyat */
--lh-heading: 1.1
--lh-body: 1.6 /* paragraflar */

Bu sistemin kimliğidir. Yanlış pixel değerleri brand recognition’ı bozar.

/* Kart — bottom-right 14px kesim + 2px üst kırmızı çizgi */
--clip-card: polygon(0 0, 100% 0, 100% calc(100% - 14px), calc(100% - 14px) 100%, 0 100%);
/* Glass panel (modal, nav backdrop) — 12px */
--clip-glass: polygon(0 0, 100% 0, 100% calc(100% - 12px), calc(100% - 12px) 100%, 0 100%);
/* Buton — top-left + bottom-right 8px çift kesim */
--clip-button: polygon(8px 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%, 0 8px);
/* Badge — 5px paralelkenar */
--clip-badge: polygon(5px 0, 100% 0, calc(100% - 5px) 100%, 0 100%);
/* Badge (alt) — 6px double-corner */
--clip-badge-6: polygon(6px 0, 100% 0, 100% calc(100% - 6px), calc(100% - 6px) 100%, 0 100%, 0 6px);
/* Hex banner */
--clip-hex: polygon(12px 0, calc(100% - 12px) 0, 100% 50%, calc(100% - 12px) 100%, 12px 100%, 0 50%);

Butonlar, badge’ler ve input’lar için wrapper + inner tekniği:

<span class="btn-wrap btn-primary"> <!-- outer (1px padding = "border") -->
<span class="inner">BUTTON TEXT</span> <!-- inner (solid fill) -->
</span>
.btn-wrap {
display: inline-block;
padding: 1px;
clip-path: var(--clip-button);
}
.btn-wrap .inner {
padding: 10px 18px;
clip-path: var(--clip-button);
}
.btn-primary { background: var(--brand-red-bright); box-shadow: var(--shadow-cta); }
.btn-primary .inner { background: var(--brand-red); color: white; }

Outer wrap’in background’u “border rengi” olur, inner’ın background’u fill olur. Her ikisi aynı clip-path’i paylaşır. Bu teknik olmadan “cut corner + border” yapılamaz.


--space-1: 4px --space-6: 24px (card padding standart)
--space-2: 8px --space-8: 32px (large card padding)
--space-3: 12px --space-12: 48px
--space-4: 16px --space-16: 64px (section-header mb)
--space-5: 20px --space-24: 96px (section vertical rhythm)
  • Max-width: 1280px (max-w-7xl)
  • Section padding: py-24 (96px) — landing. Admin içinde py-6 yeterli.
  • Page padding: px-4 mobile → px-6 tablet → px-8 desktop
  • Grid gap: gap-6 (24px) feature/pricing, gap-4 (16px) dense grid
  • Section header margin-bottom: mb-16 (64px)
  • Sidebar width: 248px (collapsed: 58px)
  • Topbar height: 56px
  • Content padding: 24px (px-6 py-6)
  • Table row padding: py-3 px-4 (orta yoğunluk)

ElementRadius
Cards, buttons, badges, panels0 (clip-path halleder)
.launch-total chip2px
Blog inline code tag4px
Modal, blog table, glass panel8px
Avatars50% (tek istisna)

Asla rounded-md, rounded-lg, rounded-xl KULLANMA. Avatar için rounded-full OK.


Soft drop shadow YOK. Sadece:

/* Base */
--shadow-card: 0 4px 20px rgba(0, 0, 0, 0.4)
--shadow-card-inset: inset 0 1px 0 rgba(255, 255, 255, 0.04) /* üst highlight */
/* CTA */
--shadow-cta: 0 10px 40px -10px rgba(232, 25, 44, 0.5)
/* Hover */
--shadow-card-hover: 0 0 25px rgba(232, 25, 44, 0.15), 0 4px 20px rgba(0, 0, 0, 0.4)
/* Text glows */
--glow-red-text: 0 0 10px rgba(232, 25, 44, 0.5)
--glow-red-box: 0 0 20px rgba(232, 25, 44, 0.15)
--glow-teal-text: 0 0 20px rgba(0, 200, 160, 0.3)
--glow-teal-box: 0 0 30px rgba(0, 200, 160, 0.10)

Her kart: box-shadow: var(--shadow-card), var(--shadow-card-inset).

Primary CTA: box-shadow: var(--shadow-cta).

Stat value (büyük rakam): text-shadow: var(--glow-teal-text) (veya red için red-glow).


--dur-card: 220ms ease-out (kart hover translate/shadow)
--dur-button: 300ms ease (buton bg swap + shadow derinleşme)
--dur-color: 200ms (color-only link swap)
--dur-theme: 500ms cubic-bezier (dark/light geçiş)
  • Easing: cubic-bezier(0.4, 0, 0.2, 1) (Tailwind ease-out) varsayılan
  • Card hover: translateY(-4px) + red-glow shadow
  • Button hover: background brand-red → brand-red-dark + glow derinleşme
  • No spring, no bounce, no scale(0.95) press animation.
  • Entrance animation: fadeInUp 0.8s ease-out (scroll trigger)
  • Tüm animasyonlar prefers-reduced-motion: reduce respect eder

Bu primitivler components/admin/design-system/ altında React bileşeni olarak mevcut. Direkt import ederek kullan.

Red top-border 2px + 14px bottom-right chamfer + hairline side border + black drop + inset top highlight.

import { TechCard } from '@/components/admin/design-system';
<TechCard accent="red"> {/* red | teal | amber | blue | neutral */}
<p className="prefix">Toplam</p>
<p className="font-tech text-[28px] t-1 mt-2">51</p>
</TechCard>
import { IndustrialButton } from '@/components/admin/design-system';
<IndustrialButton variant="primary">YENİ MÜŞTERİ</IndustrialButton>
<IndustrialButton variant="ghost">CSV EXPORT</IndustrialButton>
<IndustrialButton variant="teal">✓ DOĞRULA</IndustrialButton>
<IndustrialButton variant="disabled" disabled>YÜKLENİYOR…</IndustrialButton>

Variants: primary (red fill + glow), ghost (hairline + dark), teal (teal border + dark), disabled.

İç içerik HER ZAMAN Chakra Petch uppercase + tracking 0.12em.

import { IndustrialBadge } from '@/components/admin/design-system';
<IndustrialBadge tone="teal" dot>ONLINE</IndustrialBadge>
<IndustrialBadge tone="red">LIVE</IndustrialBadge>
<IndustrialBadge tone="amber">VIP</IndustrialBadge>
<IndustrialBadge tone="blue">v5.4</IndustrialBadge>
<IndustrialBadge tone="neutral">DRAFT</IndustrialBadge>

Tones: red | teal | amber | blue | purple | neutral. Her zaman wrapper+inner tekniği. Her zaman JetBrains Mono uppercase.

import { ChamferedInput } from '@/components/admin/design-system';
<ChamferedInput
label="Work Email"
placeholder="tuner@workshop.com"
required
helper={{ type: 'ok', text: 'VALID · UNIQUE' }}
/>
<ChamferedInput
label="Country"
state="error"
helper={{ type: 'err', text: '!! REQUIRED FIELD' }}
/>

States: rest | focus | error. Label her zaman JetBrains Mono uppercase tracking 0.18em. Helper da aynı.

import { PrefixLabel } from '@/components/admin/design-system';
<PrefixLabel>Customer Management</PrefixLabel>
{/* renders: // CUSTOMER MANAGEMENT */}

// kırmızı, geri kalan fg-4 mono uppercase tracking 0.08em.

import { SectionHeading } from '@/components/admin/design-system';
<SectionHeading
prefix="Customer Management"
title="Müşteriler"
subtitle="51 kayıt · 48 aktif"
actions={<>
<IndustrialButton variant="ghost">CSV EXPORT</IndustrialButton>
<IndustrialButton variant="primary">YENİ MÜŞTERİ</IndustrialButton>
</>}
/>

Sol kenarda 1x28px kırmızı çubuk (box-shadow: 0 0 12px rgba(232,25,44,0.6)) + Chakra Petch uppercase başlık.


<main className="bg-grid min-h-[calc(100vh-3.5rem)]">
<div className="p-6">
<SectionHeading prefix="..." title="..." subtitle="..." actions={...} />
{/* Stats row */}
<div className="grid grid-cols-5 gap-4 mb-6">
<TechCard accent="..."><StatContent ... /></TechCard>
</div>
{/* Filter tabs */}
<FilterTabGroup tabs={...} />
{/* Main table inside TechCard */}
<TechCard padding="none">
<Table ... />
<Pagination ... />
</TechCard>
</div>
</main>

Chamfered group button (clip-btn-sm). Aktif sekme background: var(--brand-red); color: white. Diğerleri t-3 hover:bg-white/[0.04]. Sayaçlar sekmeden sonra JetBrains Mono.

  • Header bg: var(--brand-panel), padding py-2.5 px-4
  • Header text: prefix class (mono uppercase // PREFIX pattern değil, sadece uppercase mono)
  • Row border-bottom: var(--border-hairline)
  • Row hover: bg-white/[0.02]
  • ID column: JetBrains Mono, t-4, 10px
  • Name column: font-semibold t-1, avatar + isim + e-posta (mono, 10px)
  • Date: JetBrains Mono t-4 11px, format YYYY-MM-DD
  • Amount: JetBrains Mono t-red font-semibold
  • Numeric counts: font-tech (Chakra Petch) 14px t-1
  • Badges for status: IndustrialBadge
  • Action column: 3-dot vertical button t-4 hover:t-1

Chamfered buttons (btn-wrap sm). Aktif sayfa btn-primary, diğerleri btn-ghost. ”…” JetBrains Mono t-4.

TechCard içinde centered: Lucide icon w-14 h-14 text-fg-4, başlık font-tech t-1, açıklama t-3.

<form>
<TechCard accent="neutral">
<div className="p-6">
<PrefixLabel>Create Customer</PrefixLabel>
<h2 className="font-tech text-[20px] t-1 mt-2">Yeni Müşteri</h2>
<div className="grid grid-cols-2 gap-4 mt-6">
<ChamferedInput label="Name" required />
<ChamferedInput label="Email" required />
...
</div>
<div className="flex items-center justify-end gap-2 mt-6 pt-4 border-t border-hairline">
<IndustrialButton variant="ghost" type="button">VAZGEÇ</IndustrialButton>
<IndustrialButton variant="primary" type="submit">KAYDET</IndustrialButton>
</div>
</div>
</TechCard>
</form>

  • Grid pattern (admin ana alan): rgba(255,255,255,0.025) 40x40 — landing ile tutarlı
  • Dense grid (teknik blok): #0f1d2e 20x20
  • Spotlight gradient (section header arkası): radial-gradient(circle at 50% -20%, rgba(255,255,255,0.05), transparent 50%)
  • Glass panel (modal, dropdown): bg-[#0e1724]/60 backdrop-blur-md border-subtle
  • Gradient FİLL YASAK — gradient sadece overlay/mask/glow için
  • Cards’ta frosted glass YASAK — blur sadece nav/modal/dropdown

Brand’in signature label’ı: // SECTION_NAME veya // FEATURE.

<span class="prefix">Customer Management</span>
<!-- renders: <red>//</red> <fg-4 mono>CUSTOMER MANAGEMENT</fg-4> -->

CSS:

.prefix {
font-family: 'JetBrains Mono', monospace;
font-size: 11px;
color: var(--fg-4);
letter-spacing: 0.08em;
text-transform: uppercase;
}
.prefix::before { content: "// "; color: var(--brand-red); }

Nerede kullanılır:

  • Sayfa başlığı üstünde
  • TechCard içinde stat label olarak
  • Tablo header’ında (alternatif)
  • Form section ayırıcı olarak

  • Lucide (lucide-react) — tek izinli library
  • Stroke width: 1.75 default, 2 strong, 2.5 Check/X emphasis
  • Size: w-3.5 h-3.5 (14px inline button), w-4 h-4 (16px list), w-5 h-5 (20px headings)
  • Color: inherit default; explicit text-brand-red | text-brand-teal | text-fg-4
  • PNG, decorative SVG, emoji YASAK.
  • Check/Cross pattern:
    • ✓ → <Check> inside bg-brand-teal/15 24px circle
    • ✗ → <X> inside bg-white/4 24px circle
    • ± → <Minus> inside bg-brand-amber/10 24px circle

  • Admin paneli Türkçe (kullanıcı Türk). Pazarlama siteden farklı olarak B2B internal tool.
  • Başlıklar hep UPPERCASE + tracking — pazarlamadaki gibi
  • // PREFIX yeri (sayfa başlığı üstü) İngilizce teknik isimlerle OK: // CUSTOMER MANAGEMENT, // BILLING
  • Buton text’leri UPPERCASE Türkçe: YENİ MÜŞTERİ, KAYDET, VAZGEÇ, SİL
  • Badge text’leri UPPERCASE: AKTİF, PASİF, VIP, BETA, YENİ
  • Sayılar JetBrains Mono, binlik ayraç nokta (TR format): €24.840, 66.000+
  • Tarih formatları: JetBrains Mono YYYY-MM-DD (ISO) veya 12 Nis 2026 (TR). Tablo içinde ISO tercih edilir.
  • Emoji YASAK — Lucide icons.

Admin panel şu an sadece dark. Light mode ilerde eklenirse:

  • Brand colors ve clip-path’ler aynı kalır
  • Surfaces #ffffff → #f5f5f5 → #e5e7eb
  • Foreground invert
  • Glow’lar kalkar (--glow-red-text: none light mode’da)

Admin panel şu an dark class varsayımı ile çalışır.


  • border-radius: 4px | 6px | 8px | 12px | 16px — sadece 0, 2, 4, 8 izinli ve sadece istisna durumlar için
  • rounded-lg, rounded-xl, rounded-2xl Tailwind class’ları
  • font-family: sans-serif default bırakmak (her başlık explicit font-tech, her data explicit font-mono)
  • ❌ Başlıklarda lowercase veya title case
  • ❌ Buton text’te Türkçe sentence case (Yeni Müşteri değil, YENİ MÜŞTERİ)
  • ❌ Solid beyaz border (border-white) — her zaman rgba(255,255,255,0.X)
  • ❌ Soft drop shadow (shadow-md, shadow-lg) — sadece belirtilen glow pattern’leri
  • ❌ Kartlarda backdrop-filter: blur — sadece nav/modal/dropdown
  • ❌ Emoji (✅ ❌ 🎉) — Lucide icon
  • bg-gradient-to-* solid fill için — gradient sadece glow/overlay
  • ❌ Animasyonlarda bounce/spring
  • ❌ Press’te scale(0.95) transform

/app
globals.css — Tailwind + landing tokens (mevcut)
admin-theme.css — YENİ: admin design tokens + primitive classes
[locale]/
admin/(panel)/
layout.tsx — Panel layout wrapper
[sayfa]/page.tsx — Her admin sayfası
/components/admin
AdminSidebar.tsx — REVIZE: design-system-uyumlu
AdminHeader.tsx — REVIZE: MRR chip + status + ⌘K
AdminPanelContent.tsx — REVIZE: grid-bg katmanı
design-system/ — YENİ: shared primitives
index.ts — barrel export
TechCard.tsx
IndustrialButton.tsx
IndustrialBadge.tsx
ChamferedInput.tsx
PrefixLabel.tsx
SectionHeading.tsx
FilterTabs.tsx
Pagination.tsx
StatCard.tsx
TableShell.tsx — opsiyonel: table wrapper
/docs/admin-design-system
STYLE.md — BU DOSYA
examples/ — gerekirse kod örnekleri

Her sayfayı dönüştürürken sor:

  1. rounded-* class’ları temizlendi mi? → TechCard/IndustrialButton/IndustrialBadge kullanıldı mı?
  2. ✅ Başlıklar Chakra Petch uppercase tracking-wide mı?
  3. // PREFIX pattern sayfa başlığı üstünde var mı?
  4. ✅ Tablo header’ları mono uppercase mi?
  5. ✅ Renkler token’lardan mı geliyor (hex değil, var(--brand-red))?
  6. ✅ Status badge’leri IndustrialBadge bileşeniyle mi?
  7. ✅ Primary CTA kırmızı glow’lu mu?
  8. ✅ Avatar dışında rounded-full kullanılmadı mı?
  9. ✅ Drop shadow yerine red/teal glow mu?
  10. ✅ Grid pattern bg admin main’de var mı?

Her sayfa revize edilince mutlaka build + chown + PM2 restart yapılır:

Terminal window
npx next build && chown -R yigit:yigit .next/ && pm2 restart ecutuningportal

Email/SMS gibi detay drawer’lari icin parent key={id} + race-safe fetch + usePayloadReveal hook kanonu ayri dosyada: docs/admin-design-system/DRAWER.md. Yeni detay drawer yazmadan once oraya bak.


Reference mockup (hem agent hem insan için görsel kaynak): https://ecutuningportal.com/admin-mockups/dark-4-portal-bridge.html

Bu mockup’ta gördüğün tüm pattern’ler (sidebar, topbar, stats, filter tabs, tablo, pagination, footer reference) bu STYLE.md’nin HTML karşılığıdır. Şüphe varsa oraya bak.


Bu dosya yaşayan dökümandır:

  • Yeni component eklenirse components/admin/design-system/ altına + buraya section eklenir
  • Yeni pattern ortaya çıkarsa §9’a (Patterns) eklenir
  • Yasaklar (§15) genişleyebilir, daralmaz
  • Brand renkleri / font’lar değişirse app/globals.css + bu dosya aynı anda güncellenir

PR her zaman bu dosyayı güncel tutar.