İLETİŞİME GEÇİN
Token, primitive ve composite bileşen katmanlarıyla erişilebilir, temalanabilir ve sürdürülebilir bir React tasarım sistemi nasıl kurulur?

Bir uygulamada üç farklı mavi tonu, dört farklı buton yüksekliği ve her ekranda biraz farklı davranan modallar görüyorsanız, sorun tasarımcıda ya da geliştiricide değil, ortak bir karar altyapısının olmamasındadır. Tasarım sistemi bu altyapının adıdır: Renk, boşluk ve tipografi kararlarını bir kez alıp her yerde aynı şekilde uygulamayı sağlayan token'lar, bileşenler ve kurallar bütünü. Bu yazıda React ile böyle bir sistemi sıfırdan kurarken izlenebilecek katmanlı yapıyı ve yol boyunca verilmesi gereken kararları ele alıyoruz.
Sürdürülebilir bir tasarım sistemi genellikle üç katmandan oluşur ve her katman yalnız bir altındakine dayanır:
Bu ayrım, ekiplerin paralel çalışmasını da kolaylaştırır: Marka rengi değiştiğinde yalnız token katmanı güncellenir; bir tablonun davranışı değiştiğinde ise token'lara dokunmak gerekmez.
Token'ları iki seviyede tanımlamak, tema desteğini ve bakımı belirgin biçimde kolaylaştırır. İlk seviyede paletin kendisi (primitive token), ikinci seviyede bu değerlerin hangi amaçla kullanıldığını anlatan anlamsal isimler (semantic token) yer alır. Bileşenler yalnız anlamsal token'ları kullanır.
:root {
/* Palet */
--blue-600: #2563eb;
--blue-700: #1d4ed8;
--gray-50: #f9fafb;
--gray-900: #111827;
/* Anlamsal token'lar */
--color-bg-surface: var(--gray-50);
--color-text-primary: var(--gray-900);
--color-action-primary: var(--blue-600);
--color-action-primary-hover: var(--blue-700);
--space-2: 0.5rem;
--space-4: 1rem;
--radius-md: 0.5rem;
}
[data-theme="dark"] {
--color-bg-surface: var(--gray-900);
--color-text-primary: var(--gray-50);
}
Koyu tema bu yapıda yalnız anlamsal token'ların yeniden eşlenmesinden ibarettir; hiçbir bileşen koduna dokunulmaz. Token'ların tek kaynaktan (örneğin bir JSON dosyasından) üretilmesi istenirse Style Dictionary gibi araçlar aynı tanımdan CSS değişkenleri, TypeScript sabitleri ve mobil platform çıktıları üretebilir. W3C bünyesindeki Design Tokens Community Group'un token formatı da araçlar arası ortak bir dil olarak giderek yaygınlaşıyor.
İsimlendirmede kural basit: Değeri değil amacı anlatın. --blue-600 bir palet adıdır; --color-action-primary ise bir karardır. Marka rengi yeşile döndüğünde ikincisinin adı hâlâ doğru kalır.
Bir butonu yazmak kolaydır; klavyeyle gezinilebilen, ekran okuyucularla doğru çalışan, odak yönetimi yapan bir açılır menü ya da combobox yazmak ise haftalar alabilir. Bu yüzden karmaşık etkileşimli bileşenlerde headless kütüphaneler iyi bir başlangıç noktasıdır. Radix UI ve React Aria, davranışı ve erişilebilirliği sağlayıp görünümü tamamen size bırakır. Siz yalnız kendi token'larınızla stil verirsiniz.
Basit primitive'lerde ise kendi bileşeninizi yazmak çoğu zaman yeterlidir. Varyantları prop'larla, stilleri token'larla yönetmek tutarlılığı korur:
import type { ComponentProps } from "react";
import styles from "./Button.module.css";
type ButtonProps = ComponentProps<"button"> & {
variant?: "primary" | "secondary" | "ghost";
size?: "sm" | "md";
};
export function Button({
variant = "primary",
size = "md",
className,
...props
}: ButtonProps) {
return (
<button
{...props}
data-variant={variant}
data-size={size}
className={[styles.button, className].filter(Boolean).join(" ")}
/>
);
}
React 19 ile fonksiyon bileşenleri ref'i normal bir prop olarak alabildiği için bu bileşen forwardRef sarmalayıcısına ihtiyaç duymaz; ComponentProps<"button"> tipi ref'i de kapsar. Projeniz React 18'deyse forwardRef kullanmaya devam etmeniz gerekir.
Primitive'lerin API'sinde dikkat edilecek birkaç nokta:
disabled, type, aria-* gibi özellikleri engellemeyin; bileşen, sardığı elemanın yerine geçebilmeli.className desteği esneklik sağlar ama sık kullanılıyorsa eksik bir varyantın işaretidir.Dialog veya Card gibi yapılarda tek bir bileşene onlarca prop eklemek yerine compound component deseni daha esnektir. Kullanıcı parçaları kendisi dizer; bileşen yalnız düzeni ve davranışı sağlar:
<Dialog.Root>
<Dialog.Trigger asChild>
<Button variant="secondary">Siparişi iptal et</Button>
</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title>Emin misiniz?</Dialog.Title>
<Dialog.Description>Bu işlem geri alınamaz.</Dialog.Description>
</Dialog.Content>
</Dialog.Root>
Radix'in Dialog bileşeni tam olarak bu yapıyı sunar; tasarım sisteminiz bunun üzerine kendi stilini ve varsayılanlarını ekleyen ince bir katman olabilir.
Erişilebilirlik tasarım sistemine sonradan eklendiğinde, her bileşeni ve onu kullanan her ekranı yeniden elden geçirmek gerekir. Sistemin içine baştan yerleştirildiğinde ise bütün ürün bunu kendiliğinden devralır. Temel kontrol listesi:
:focus-visible ile görünür bir odak halkası olsun.aria-label) olsun.prefers-reduced-motion tercihine saygı göstersin.Bir bileşen kütüphanesi ancak bulunabildiği ve güvenilebildiği ölçüde kullanılır. Storybook, her bileşenin tüm varyantlarını izole biçimde gösteren canlı bir katalog sunar; erişilebilirlik eklentisi (axe tabanlı) bu ekranlarda otomatik kontroller de çalıştırır. Görsel regresyon testleri (Chromatic ya da Playwright ekran görüntüsü karşılaştırmaları gibi), bir token değişikliğinin hangi bileşenleri etkilediğini piksel düzeyinde gösterir.
Sistemi ayrı bir paket olarak yayınlıyorsanız anlamsal sürümleme (semver) kullanın ve kırıcı değişiklikleri bir sürüm önceden kullanımdan kaldırma uyarısıyla duyurun. Changesets gibi araçlar, sürüm notlarını PR'larla birlikte yazmayı kolaylaştırır.
Her şeyi bir anda kurmaya çalışmayın. Mevcut uygulamada en sık kullanılan renkleri ve boşlukları toplayıp token'lara dönüştürmek, ardından en çok tekrar eden üç dört bileşeni (genellikle Button, Input, Select ve Dialog) sisteme taşımak iyi bir ilk adımdır. TeksERP gibi çok sayıda form ve tablo ekranı olan kurumsal uygulamalarda, bu ilk adım bile ekranlar arasındaki tutarsızlıkları görünür kılar ve yeni ekranların aynı kalıpla yazılmasını sağlar. Sonrasında sistem, ürünün gerçek ihtiyaçlarıyla birlikte büyümelidir; kimsenin kullanmadığı bileşenler için önceden yatırım yapmaya gerek yoktur.
Yorumlar yakında etkinleştirilecek.

LCP, INP ve CLS neyi ölçer, eşikleri nedir ve üretimde nasıl iyileştirilir? Saha ve laboratuvar ölçümünden performans bütçesine pratik bir rehber.

Server Components, paralel veri yükleme, Suspense ile streaming, önbellek kararları ve Server Actions: App Router ile performans odaklı bir Next.js mimarisi nasıl kurulur?

Mobil uygulama projenize başlamadan önce verilecek en kritik kararlardan biri: native mi, cross-platform mı? İki yaklaşımı dürüstçe karşılaştırıyor, doğru seçimi nasıl yapacağınızı anlatıyoruz.