Merhaba arkadaşlar, bugün başımı çok ağrıtan bir konudan bahsedeceğim. Büyük bir projede, aynı temel buton, kart veya alert component'ini farklı renklerde, boyutlarda ve durumlarda (hover, disabled) kullanmak zorunda kaldığımda, class listeleri içinde boğuluyordum. Her varyasyon için ayrı bir prop yazıp, içinde koskoca bir `className` string'i birleştirmek... İşte bu hatayı ilk gördüğümde kafayı yemiştim. Sonra Tailwind CSS'in `@variant` direktifinin gücünü keşfettim.
Karşılaştığım Sorun ve Klasik Yöntem
Diyelim ki bir buton component'imiz var ve bunun `primary`, `secondary`, `danger` gibi varyasyonları olacak. Eskiden şöyle yapardım:
Bu yöntem çalışıyor evet, ama her yeni bir varyasyon eklemek istediğimde bu nesneyi güncellemem, ayrıca `disabled`, `outline`, `small` gibi ekstra varyasyonlar geldiğinde kombinasyonlar katlanarak artıyor ve kod okunması zor bir hal alıyordu.
Kurtarıcı: Tailwind'de @variant Kullanımı
İşte tam burada Tailwind'in `tailwind.config.js` dosyası içinde veya bir CSS dosyasında tanımlayabileceğimiz `@variant` direktifi devreye giriyor. Bu sayede, utility class'larımıza kendi özel varyasyon isimlerimizi ekleyebiliyoruz. En temiz çözüm, bunu bir eklenti (`plugin`) olarak konfigürasyon dosyasında tanımlamak.
Bu tanımlamadan sonra, artık CSS'imizde veya doğrudan class isimlerinde şöyle kullanabiliriz:
React/Vue Component'inde Temiz Uygulama
Peki bu tanımlamaları yaptıktan sonra component'imiz nasıl sadeleşiyor bir bakalım. Artık prop'tan gelen değeri doğrudan class'a ekleyebiliriz.
Gördüğünüz gibi, component içindeki karmaşık mantık ve class haritaları tamamen kayboldu. Tüm stil mantığı, Tailwind konfigürasyonu ve global CSS katmanına taşındı. Bu, hem bakımı kolaylaştırıyor hem de tutarlılığı artırıyor.
Sonuç ve Düşüncelerim
`@variant` kullanımı, özellikle design system oluşturduğunuz büyük projelerde hayat kurtarıcı. Stil değişikliklerini merkezi bir yerden yönetebilmek, dark mode, disabled state gibi durumları da aynı mantıkla ekleyebilmek inanılmaz esneklik sağlıyor.
Siz de Tailwind'de benzer bir stil yönetimi sorunu yaşadınız mı? Component varyasyonlarınızı yönetmek için farklı bir yöntem (mesela clsx veya class-variance-authority kütüphaneleri) kullanıyor musunuz? Bu yöntem hakkında düşünceleriniz neler? Aşağıdaki yorumlarda deneyimlerinizi paylaşın, tartışalım!
Diyelim ki bir buton component'imiz var ve bunun `primary`, `secondary`, `danger` gibi varyasyonları olacak. Eskiden şöyle yapardım:
JavaScript:
const Button = ({ variant = 'primary', children }) => {
const baseClasses = "px-4 py-2 rounded font-semibold transition";
const variantClasses = {
primary: "bg-blue-600 text-white hover:bg-blue-700",
secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300",
danger: "bg-red-600 text-white hover:bg-red-700",
};
const className = `${baseClasses} ${variantClasses[variant]}`;
return <button className={className}>{children}</button>;
};
Bu yöntem çalışıyor evet, ama her yeni bir varyasyon eklemek istediğimde bu nesneyi güncellemem, ayrıca `disabled`, `outline`, `small` gibi ekstra varyasyonlar geldiğinde kombinasyonlar katlanarak artıyor ve kod okunması zor bir hal alıyordu.
İşte tam burada Tailwind'in `tailwind.config.js` dosyası içinde veya bir CSS dosyasında tanımlayabileceğimiz `@variant` direktifi devreye giriyor. Bu sayede, utility class'larımıza kendi özel varyasyon isimlerimizi ekleyebiliyoruz. En temiz çözüm, bunu bir eklenti (`plugin`) olarak konfigürasyon dosyasında tanımlamak.
JavaScript:
// tailwind.config.js
const plugin = require('tailwindcss/plugin');
module.exports = {
// ... diğer konfigürasyonlar
plugins: [
plugin(function({ addVariant }) {
// 'btn-primary' varyasyonunu tanımla
addVariant('btn-primary', ['&.btn-primary', '.btn-primary &']);
// 'btn-secondary' varyasyonunu tanımla
addVariant('btn-secondary', ['&.btn-secondary', '.btn-secondary &']);
// 'btn-danger' varyasyonunu tanımla
addVariant('btn-danger', ['&.btn-danger', '.btn-danger &']);
// Boyut için varyasyon
addVariant('btn-small', '&.btn-small');
}),
],
};
Bu tanımlamadan sonra, artık CSS'imizde veya doğrudan class isimlerinde şöyle kullanabiliriz:
CSS:
/ Örnek bir kullanım (global CSS'de) /
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
@apply px-4 py-2 rounded font-semibold transition-colors duration-200;
}
/ Varyasyonlar, tanımladığımız özel varyantlarla /
.btn-primary {
@apply btn-primary:bg-blue-600 btn-primary:text-white btn-primary:hover:bg-blue-700;
}
.btn-danger {
@apply btn-danger:bg-red-600 btn-danger:text-white btn-danger:hover:bg-red-700;
}
.btn-small {
@apply btn-small:px-3 btn-small:py-1 btn-small:text-sm;
}
}
Peki bu tanımlamaları yaptıktan sonra component'imiz nasıl sadeleşiyor bir bakalım. Artık prop'tan gelen değeri doğrudan class'a ekleyebiliriz.
JavaScript:
// React Component Örneği
const Button = ({ variant = 'primary', size, children, ...props }) => {
// Varyasyon ve boyut class'larını birleştir
const variantClass = `btn-${variant}`;
const sizeClass = size ? `btn-${size}` : '';
// Temiz ve anlaşılır class birleştirme
const className = `btn ${variantClass} ${sizeClass}`.trim();
return <button className={className} {...props}>{children}</button>;
};
// Kullanımı:
// <Button variant="primary">Kaydet</Button>
// <Button variant="danger" size="small">Sil</Button>
// <Button variant="secondary" disabled>Devre Dışı</Button>
Gördüğünüz gibi, component içindeki karmaşık mantık ve class haritaları tamamen kayboldu. Tüm stil mantığı, Tailwind konfigürasyonu ve global CSS katmanına taşındı. Bu, hem bakımı kolaylaştırıyor hem de tutarlılığı artırıyor.
`@variant` kullanımı, özellikle design system oluşturduğunuz büyük projelerde hayat kurtarıcı. Stil değişikliklerini merkezi bir yerden yönetebilmek, dark mode, disabled state gibi durumları da aynı mantıkla ekleyebilmek inanılmaz esneklik sağlıyor.
Siz de Tailwind'de benzer bir stil yönetimi sorunu yaşadınız mı? Component varyasyonlarınızı yönetmek için farklı bir yöntem (mesela clsx veya class-variance-authority kütüphaneleri) kullanıyor musunuz? Bu yöntem hakkında düşünceleriniz neler? Aşağıdaki yorumlarda deneyimlerinizi paylaşın, tartışalım!