React ve Storybook ile UI Komponenti Geliştirme: Kapsamlı Bir Rehber
Modern web uygulamaları, karmaşıklığı yönetmek ve geliştirme süreçlerini hızlandırmak için modüler, yeniden kullanılabilir bileşenlere dayalı mimarileri benimsemektedir. Bu mimarilerin merkezinde, kullanıcı arayüzü (UI) bileşenleri yer alır. React, bu bileşen tabanlı yaklaşımın en popüler temsilcilerinden biridir. Ancak, bileşenleri izole bir şekilde geliştirmek, test etmek ve belgelemek, özellikle büyük projelerde zorlayıcı olabilir. İşte bu noktada Storybook devreye girer. Storybook, UI bileşenlerini bağımsız bir ortamda geliştirmek, görselleştirmek ve belgelemek için güçlü bir araçtır. Bu makalede, React ve Storybook’u bir araya getirerek nasıl sağlam, yeniden kullanılabilir ve iyi belgelenmiş UI bileşenleri oluşturulacağını adım adım inceleyeceğiz.
React ve Komponent Tabanlı Mimari
React, Facebook tarafından geliştirilen açık kaynaklı bir JavaScript kütüphanesidir ve kullanıcı arayüzleri oluşturmak için kullanılır. Deklaratif yapısı ve bileşen tabanlı mimarisi sayesinde, karmaşık UI’ları yönetilebilir, bakımı kolay ve ölçeklenebilir parçalara ayırmayı mümkün kılar.
React’in Temel Prensipleri
* Bileşen Tabanlılık: React’te her şey bir bileşendir. Bir bileşen, kendi mantığına ve görünümüne sahip, bağımsız, yeniden kullanılabilir bir kod bloğudur. Bu bileşenler, daha büyük ve karmaşık UI’lar oluşturmak için birleştirilir. Örneğin, bir Button (Düğme), bir Card (Kart) veya bir Navbar (Gezinme Çubuğu) birer bileşen olabilir.
* Deklaratif Yaklaşım: React, UI’ın nasıl görünmesi gerektiğini “nasıl” değil, “ne” olması gerektiğini tanımlamanıza olanak tanır. Yani, belirli bir veri durumu için UI’ın nasıl görünmesi gerektiğini belirtirsiniz ve React, bu durumu gerçek DOM’a yansıtma işini otomatik olarak halleder. Bu, UI geliştirmeyi daha öngörülebilir ve hata ayıklamayı daha kolay hale getirir.
* Tek Yönlü Veri Akışı (Props): React’te veriler, üst bileşenlerden alt bileşenlere “props” (özellikler) aracılığıyla tek yönlü olarak akar. Bu, veri yönetimini basitleştirir ve uygulamanın durumunu daha kolay takip etmenizi sağlar.
* Durum (State): Bileşenler kendi iç durumlarını (state) yönetebilirler. Durum, bileşenin zaman içinde değişebilen verilerini temsil eder. Durum değiştiğinde, React bileşeni otomatik olarak yeniden render eder.
React’in bu temel prensipleri, UI geliştirme sürecini daha düzenli ve verimli hale getirir. Ancak, bu bileşenleri bir araya getirmeden önce, her birinin kendi başına doğru çalıştığından ve farklı durumları ele alabildiğinden emin olmak önemlidir. İşte bu noktada Storybook’un değeri ortaya çıkar.
Storybook Nedir ve Neden Kullanmalıyız?
Storybook, UI bileşenlerini izole bir ortamda geliştirmek, test etmek ve belgelemek için açık kaynaklı bir araçtır. Bir bileşen kütüphanesi veya tasarım sistemi oluştururken vazgeçilmez bir yardımcıdır.
Storybook’un Sağladığı Avantajlar
* İzole Geliştirme Ortamı: Bileşenleri uygulamanın geri kalanından bağımsız olarak geliştirebilirsiniz. Bu, karmaşık bağımlılıklarla uğraşmadan, sadece o bileşenin kendi işlevselliğine odaklanmanızı sağlar.
* Canlı Dokümantasyon: Her bileşenin farklı durumlarını (örneğin, bir düğmenin “aktif”, “pasif”, “yüklü” halleri) gösteren interaktif bir belge görevi görür. Bu dokümantasyon, geliştiriciler, tasarımcılar ve ürün yöneticileri arasında ortak bir dil oluşturur.
* Görsel Test ve Regresyon Tespiti: Bileşenlerinizi farklı veri ve durumlarla görsel olarak inceleyebilir, beklenmedik UI değişikliklerini (regresyonları) kolayca tespit edebilirsiniz.
* Ekip İçi İşbirliği: Tasarımcılar, geliştiriciler ve QA ekipleri, Storybook üzerinden bileşenleri kolayca gözden geçirebilir ve geri bildirim sağlayabilir. Bu, tasarım ve geliştirme arasındaki boşluğu kapatır.
* Hızlandırılmış Geliştirme: Bileşenleri uygulamanın genel bağlamını kurmaya gerek kalmadan doğrudan Storybook içinde geliştirebilirsiniz. Bu, geliştirme döngüsünü önemli ölçüde hızlandırır.
* Eklenti Ekosistemi (Addons): Storybook, işlevselliğini genişletmek için zengin bir eklenti ekosistemine sahiptir. Bu eklentilerle, bileşen özelliklerini dinamik olarak değiştirebilir, etkileşimleri günlüğe kaydedebilir, erişilebilirlik kontrolleri yapabilir ve daha fazlasını yapabilirsiniz.
React ile Storybook’u birleştirmek, hem geliştirme verimliliğini artırır hem de daha tutarlı, bakımı kolay ve kaliteli UI’lar oluşturmanızı sağlar. Şimdi, bu güçlü ikiliyi kullanarak bir UI bileşeni oluşturma sürecine geçelim.
Proje Ortamının Kurulumu
React ve Storybook ile bir UI bileşeni oluşturmaya başlamadan önce, gerekli proje ortamını kurmamız gerekiyor.
1. React Projesi Oluşturma
Eğer mevcut bir React projeniz yoksa, create-react-app veya Vite gibi araçlarla hızlıca bir tane oluşturabilirsiniz. Bu makale için create-react-app kullanacağız, ancak prensipler diğer kurulumlar için de geçerlidir.
npx create-react-app my-ui-component-library
cd my-ui-component-library
Bu komutlar, my-ui-component-library adında yeni bir React projesi oluşturacak ve proje dizinine geçiş yapacaktır.
2. Storybook Kurulumu
Şimdi sıra Storybook’u projemize entegre etmeye geldi. Proje dizininde aşağıdaki komutu çalıştırın:
nnpx storybook init
Bu komut, projenizin türünü otomatik olarak algılayacak (bu durumda React) ve Storybook’u kuracaktır. Kurulum sırasında, gerekli bağımlılıkları yükleyecek, .storybook klasörünü oluşturacak ve örnek Story dosyalarını ekleyecektir.
Kurulum tamamlandıktan sonra, Storybook’u başlatmak için aşağıdaki komutu kullanabilirsiniz:
npm run storybook
Bu komut, Storybook’u genellikle http://localhost:6006 adresinde başlatacak ve tarayıcınızda açacaktır. Örnek Story’leri göreceksiniz.
3. Klasör Yapısı
Bileşenlerimizi düzenli tutmak için basit bir klasör yapısı oluşturalım. src klasörünün altında components adında yeni bir klasör açalım. Her bileşen için bu klasör içinde ayrı bir alt klasör oluşturmak iyi bir uygulamadır.
my-ui-component-library/
├── src/
│ ├── components/
│ │ ├── Button/
│ │ │ ├── Button.jsx
│ │ │ ├── Button.module.css
│ │ │ └── Button.stories.jsx
│ ├── App.js
│ └── index.js
├── .storybook/
├── package.json
└── ...
Örnek Bir UI Komponenti Oluşturma: Button Komponenti
Şimdi, React ve Storybook’u kullanarak basit ama işlevsel bir Button (Düğme) komponenti oluşturalım. Bu komponentin farklı boyutları, stilleri (birincil, ikincil) ve devre dışı bırakılma durumu gibi çeşitli varyasyonları olacaktır.
Komponentin Tanımlanması
Button komponentimiz şu özellikleri alacak:
* children: Düğme içindeki metin veya JSX içeriği.
* onClick: Düğmeye tıklandığında çalışacak fonksiyon.
* primary: Düğmenin birincil stilini alıp almayacağını belirten boolean. Varsayılan olarak ikincil stili kullanır.
* backgroundColor: Özel bir arka plan rengi atamak için.
* size: Düğmenin boyutu (small, medium, large). Varsayılan olarak medium.
* disabled: Düğmenin devre dışı olup olmadığını belirten boolean.
Komponentin React Kodunu Yazma (Button.jsx)
src/components/Button/Button.jsx dosyasını oluşturalım ve içine aşağıdaki kodu yazalım:
import React from 'react';
import PropTypes from 'prop-types';
import styles from './Button.module.css';
/
* Birincil veya ikincil stile sahip yeniden kullanılabilir bir düğme komponenti.
*/
export const Button = ({
primary,
backgroundColor,
size,
onClick,
children,
disabled,
}) => {
const mode = primary ? styles.primary : styles.secondary;
return (
], mode].join(' ')}
style={backgroundColor && { backgroundColor }}
onClick={onClick}
disabled={disabled}
>
{children}
);
};
Button.propTypes = {
/
* Düğme birincil stil mi kullanacak?
*/
primary: PropTypes.bool,
/
* Özel arka plan rengi
*/
backgroundColor: PropTypes.string,
/
* Düğme boyutu
*/
size: PropTypes.oneOf(['small', 'medium', 'large']),
/
* Tıklama olayı işleyici
*/
onClick: PropTypes.func,
/
* Düğme içeriği
*/
children: PropTypes.node.isRequired,
/
* Düğme devre dışı mı?
*/
disabled: PropTypes.bool,
};
Button.defaultProps = {
backgroundColor: null,
primary: false,
size: 'medium',
onClick: undefined,
disabled: false,
};
Burada propTypes kullanarak bileşenimizin alacağı prop’ların tiplerini tanımladık. Bu, geliştirme sırasında hataları yakalamak için iyi bir uygulamadır. defaultProps ile de varsayılan değerleri belirledik.
Komponentin Stilini Belirleme (Button.module.css)
src/components/Button/Button.module.css dosyasını oluşturalım ve içine aşağıdaki CSS kodunu ekleyelim:
.button {
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 700;
border: 0;
border-radius: 3em;
cursor: pointer;
display: inline-block;
line-height: 1;
padding: 10px 16px; / Varsayılan padding /
}
.button--small {
font-size: 12px;
padding: 8px 14px;
}
.button--medium {
font-size: 14px;
padding: 11px 20px;
}
.button--large {
font-size: 16px;
padding: 12px 24px;
}
.primary {
color: white;
background-color: #1ea7fd;
}
.secondary {
color: #333;
background-color: transparent;
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
}
.button[disabled] {
opacity: 0.6;
cursor: not-allowed;
}
Bu CSS modülleri, stil çakışmalarını önlememizi sağlar. Her sınıf adı, yalnızca bu bileşenin kapsamında benzersizdir.
Storybook ile Komponenti Belgeleme ve Geliştirme
Şimdi, Button komponentimizin farklı durumlarını Storybook’ta nasıl göstereceğimizi ve belgeleyeceğimizi öğrenelim.
Storybook Kurulumu ve İlk Story’nin Oluşturulması (Button.stories.jsx)
src/components/Button/Button.stories.jsx dosyasını oluşturalım ve içine Storybook için gerekli kodu yazalım.
import React from 'react';
import { Button } from './Button';
// Storybook'a bu komponentin nerede görüneceğini ve hangi komponent olduğunu bildirir.
export default {
title: 'Example/Button', // Storybook navigasyonunda yolu
component: Button, // Hangi React komponentini belgeliyoruz
tags: ['autodocs'], // Otomatik dokümantasyon oluşturmayı etkinleştirir
argTypes: { // Props'lar için kontrolleri tanımlar
backgroundColor: { control: 'color' },
onClick: { action: 'clicked' }, // onClick prop'u tetiklendiğinde Storybook Actions panelinde gösterir
children: { control: 'text' },
},
};
// Yeniden kullanılabilir bir şablon (Template) oluşturuyoruz.
// Bu, her story için aynı temel yapıyı kullanmamızı sağlar.
const Template = (args) => ;
// Default (varsayılan) düğme story'si
export const Primary = Template.bind({});
Primary.args = {
primary: true,
children: 'Primary Button',
};
export const Secondary = Template.bind({});
Secondary.args = {
children: 'Secondary Button',
};
export const Large = Template.bind({});
Large.args = {
size: 'large',
children: 'Large Button',
};
export const Small = Template.bind({});
Small.args = {
size: 'small',
children: 'Small Button',
};
export const Disabled = Template.bind({});
Disabled.args = {
disabled: true,
children: 'Disabled Button',
};
export const CustomBackgroundColor = Template.bind({});
CustomBackgroundColor.args = {
backgroundColor: '#FF7F50', // Özel bir renk
children: 'Custom Color',
};
export const WithEmoji = Template.bind({});
WithEmoji.args = {
primary: true,
children: ' ',
};
Bu kodda dikkat etmemiz gerekenler:
* export default objesi: Bu, Storybook’un komponentimiz hakkında bilgi edinmesini sağlar.
* title: Storybook UI’ında komponentimizin nerede görüneceğini belirler. Genellikle Kategori/KomponentAdı formatında kullanılır.
* component: Belgelediğimiz React komponentini işaret eder.
* tags: ['autodocs']: Storybook’un otomatik olarak kapsamlı bir dokümantasyon sayfası oluşturmasını sağlar.
* argTypes: Bu, Storybook’un “Controls” eklentisi için önemlidir. Hangi prop’ların hangi türde kontrol (renk seçici, metin girişi vb.) ile Storybook UI’ında düzenlenebileceğini belirtir. onClick için action: 'clicked' tanımlamak, bu olayın tetiklendiğinde Storybook’un “Actions” panelinde görünmesini sağlar.
* Template: Bu, her bir Story için temel bileşen yapısını tanımlayan bir fonksiyondur. Template.bind({}) kullanarak bu şablonu kopyalarız ve her Story’ye özel args (prop’lar) atarız. Bu, kod tekrarını azaltır.
* export const [StoryName]: Her bir export const ifadesi, Storybook’ta ayrı bir “Story” olarak görünür. args özelliği ile bu Story’nin hangi prop değerleriyle render edileceğini belirleriz.
Şimdi npm run storybook komutunu tekrar çalıştırırsanız, sol taraftaki navigasyon panelinde “Example/Button” altında farklı düğme varyasyonlarını göreceksiniz. Her birine tıkladığınızda, düğme farklı stillerde ve davranışlarda görünecektir. “Controls” panelinden backgroundColor, size, children gibi prop’ları değiştirebilir ve düğmenin nasıl tepki verdiğini anında görebilirsiniz. onClick prop’u için tanımladığımız action sayesinde, düğmeye tıkladığınızda “Actions” panelinde bir clicked olayı loglandığını da fark edeceksiniz.
Storybook Addon’ları ile Gelişmiş Özellikler
Storybook’un gücü, zengin eklenti ekosisteminden gelir. Kurulum sırasında bazı temel eklentiler otomatik olarak eklenir. .storybook/main.js dosyasını kontrol ederek hangi eklentilerin etkin olduğunu görebilirsiniz.
// .storybook/main.js
/ @type { import('@storybook/react-webpack5').StorybookConfig } */
const config = {
stories: ['../src//.mdx', '../src//.stories.@(js|jsx|mjs|ts|tsx)'],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials', // Controls, Actions, Viewport, Backgrounds, Docs gibi temel eklentileri içerir
'@storybook/addon-interactions',
],
framework: {
name: '@storybook/react-webpack5',
options: {},
},
docs: {
autodocs: 'tag',
},
};
export default config;
@storybook/addon-essentials paketi, çoğu ihtiyacınızı karşılayacak temel eklentileri içerir:
* Controls: Bileşen prop’larını Storybook UI’ından interaktif olarak değiştirmenizi sağlar. Bizim argTypes tanımımız bu eklenti sayesinde çalışır.
* Actions: Bileşenler tarafından tetiklenen olayları (örneğin onClick) günlüğe kaydeder ve “Actions” panelinde gösterir.
* Docs: Story’lerinizden otomatik olarak kapsamlı dokümantasyon sayfaları oluşturur. tags: ['autodocs'] bu özelliği etkinleştirir. Bu sayfalarda bileşenin kullanımı, prop tablosu ve canlı örnekler yer alır.
* Viewport: Bileşenin farklı ekran boyutlarında nasıl göründüğünü test etmenizi sağlar.
* Backgrounds: Bileşeni farklı arka plan renklerinde test etmenizi sağlar.
Ek olarak, erişilebilirlik (a11y) testleri için @storybook/addon-a11y gibi eklentileri de ekleyebilirsiniz. Kurulumu basittir:
npm install @storybook/addon-a11y --save-dev
Ardından .storybook/main.js dosyanızdaki addons dizisine ekleyin:
// .storybook/main.js
const config = {
// ...
addons: [
// ... diğer eklentiler
'@storybook/addon-a11y', // Erişilebilirlik eklentisi
],
// ...
};
Bu eklenti sayesinde, Storybook UI’ında “Accessibility” panelini göreceksiniz. Bu panel, bileşenlerinizin erişilebilirlik standartlarına uygunluğunu kontrol etmenize yardımcı olur ve potansiyel sorunları (kontrast, etiketler vb.) raporlar.
Storybook’un Faydaları ve En İyi Uygulamalar
React bileşenlerini Storybook ile geliştirmek, sadece daha iyi bileşenler oluşturmakla kalmaz, aynı zamanda tüm geliştirme sürecini de iyileştirir.
Geliştirme Sürecindeki Faydaları
* Hızlı İterasyon ve Geri Bildirim: Bileşenleri izole bir ortamda geliştirdiğiniz için, her değişikliği anında görebilirsiniz. Bu, tasarımcılar ve geliştiriciler arasında hızlı geri bildirim döngüleri oluşturur.
* Tutarlılık ve Kalite: Her bileşenin tüm olası durumlarını Storybook’ta belgeleyerek ve test ederek, uygulamanız genelinde görsel tutarlılığı ve davranışsal kaliteyi garanti altına alırsınız.
* Ekip İçi Koordinasyon: Storybook, tasarımcıların, geliştiricilerin ve QA mühendislerinin ortak bir referans noktasıdır. Herkes, bileşenlerin nasıl görünmesi ve davranması gerektiği konusunda aynı sayfada olur.
* Eğitim ve Katılım: Yeni ekip üyeleri, Storybook’u kullanarak mevcut bileşen kütüphanesini hızlıca öğrenebilir ve projenin tasarım dilini anlayabilirler.
* Görsel Regresyon Testleri: Storybook, bileşenlerin görsel olarak değişip değişmediğini kontrol etmek için harika bir araçtır. Otomatik görsel regresyon test araçlarıyla (örneğin Chromatic) entegre edilebilir.
* Erişilebilirlik (Accessibility) Odaklı Geliştirme: Erişilebilirlik eklentileri sayesinde, bileşenlerinizi geliştirirken erişilebilirlik standartlarına uygunluğunu sürekli kontrol edebilirsiniz.
En İyi Uygulamalar
* Her Komponent İçin Ayrı Story Dosyası: Her React komponenti için ayrı bir .stories.jsx (veya .stories.tsx) dosyası oluşturun. Bu, Storybook’u düzenli tutar.
* Her Durumu Temsil Eden Story’ler: Komponentinizin her olası durumu (varsayılan, aktif, devre dışı, hata, farklı boyutlar, farklı içerikler vb.) için ayrı bir Story oluşturun. Bu, komponentinizin tüm senaryolarda doğru çalıştığından emin olmanızı sağlar.
* Anlaşılır Story Başlıkları: Story’lerinizin başlıklarını (title prop’u) ve Story adlarını (export const) anlamlı ve açıklayıcı tutun.
* argTypes ve args Kullanımı: argTypes ile Storybook Controls panelinde interaktif kontroller sağlayın. args ile her Story’nin başlangıç prop değerlerini tanımlayın.
* Dokümantasyonu Güncel Tutun: Komponentleriniz değiştikçe Story’lerinizi ve dolayısıyla dokümantasyonunuzu güncel tutun. autodocs etiketi bu süreci büyük ölçüde otomatikleştirir.
* Addon’ları Etkin Kullanın: Controls, Actions, Docs, A11y gibi eklentileri etkin bir şekilde kullanarak bileşenlerinizin testini ve belgelenmesini zenginleştirin.
* CI/CD Entegrasyonu (İsteğe Bağlı): Storybook’u bir statik site olarak yayınlayabilir ve CI/CD süreçlerinize entegre edebilirsiniz. Bu, tüm ekibin her zaman güncel bileşen kütüphanesine erişmesini sağlar. Chromatic gibi hizmetler, Storybook’unuzu barındırabilir ve görsel regresyon testlerini otomatikleştirebilir.
* Komponentleri Atomik Tutun: Mümkün olduğunca küçük ve tek bir sorumluluğa sahip atomik bileşenler oluşturmaya çalışın. Bu, yeniden kullanılabilirliği ve test edilebilirliği artırır.
Sonuç
React ve Storybook, modern UI geliştirme için güçlü bir ikilidir. React’in bileşen tabanlı mimarisiyle UI’larınızı modüler parçalara ayırırken, Storybook bu parçaları izole bir ortamda geliştirmenize, belgelemenize ve test etmenize olanak tanır. Bu makalede gösterildiği gibi, basit bir Button komponenti oluşturarak bu iki aracın nasıl entegre edileceğini öğrendik.
Bu iş akışını benimsemek, geliştirme hızınızı artıracak, UI’larınızın kalitesini ve tutarlılığını yükseltecek ve ekip üyeleri arasında daha iyi bir işbirliği sağlayacaktır. İster küçük bir proje üzerinde çalışıyor olun ister büyük bir tasarım sistemi oluşturuyor olun, React ve Storybook size daha sağlam, bakımı kolay ve ölçeklenebilir kullanıcı arayüzleri inşa etme gücünü verecektir. Kendi bileşenlerinizi oluşturmaya başlayın ve bu güçlü kombinasyonun faydalarını keşfedin!