در فضای مدرن فرانتاند، شکاف بین طراحی و توسعه اغلب توسط سیستمهای طراحی پر میشود. با این حال، ساخت چنین سیستمی از صفر میتواند ترسناک باشد. ترکیب قدرتمند Tailwind CSS و Headless UI وارد میشود. این جفت به توسعهدهندگان اجازه میدهد کامپوننتهای قابل دسترس، قابل استفاده مجدد و همسان را بدون محدود شدن به سبکهای سلیقهای ایجاد کنند. این پست بررسی میکند که چگونه میتوان یک سیستم طراحی قوی را معماری کرد که گردش کار نمونهسازی شما را تسریع میکند و در عین حال کیفیت بالای کد را حفظ میکند.
چرا ترکیب Tailwind و Headless UI؟
Tailwind CSS در سبکدهی اولویتدار به ابزار (utility-first) عالی عمل میکند و کنترل دقیقی بر هر جنبه از رابط کاربری شما به شما میدهد. با این حال، این کتابخانه به صورت پیشفرض مدیریت حالتهای پیچیده یا دسترسپذیری (a11y) را برای ویجتهای پیچیده مانند لیستهای بازشو، مودالها یا تبها انجام نمیدهد. کامپوننتهای Headless UI، مانند آنهایی که توسط کتابخانه React Headless ارائه میشوند، این مشکل را حل میکنند. آنها منطق جاوااسکریپت، ناوبری با کیبورد و ویژگیهای aria را فراهم میکنند، در حالی که سبکدهی بصری را کاملاً به شما و کلاسهای Tailwind واگذار میکنند.
این جدایی دغدغهها (separation of concerns) به این معنی است که کتابخانه کامپوننت شما سبک، قابل دسترس و کاملاً قابل سفارشیسازی باقی میماند که این امر قداستمکان (holy grail) یک سیستم طراحی مقیاسپذیر است.
مرحله ۱: راهاندازی و پیکربندی پروژه
قبل از نوشتن کد، مطمئن شوید که محیط شما به درستی پیکربندی شده است. وابستگیهای ضروری را نصب کنید. برای این مثال، فرض بر این است که از یک محیط React با Tailwind CSS استفاده میکنید.
npm install @headlessui/react @headlessui/vue
# یا اگر از npm/yarn/pnpm به صورت مناسب استفاده میکنید
سپس، فایل tailwind.config.js خود را برای گسترش تم پیکربندی کنید. یک سیستم طراحی خوب با یک پالت رنگی و مقیاس فاصلهدهی (spacing) همسان آغاز میشود.
// tailwind.config.js
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
500: '#3b82f6',
700: '#1d4ed8',
},
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
},
},
plugins: [],
}
مرحله ۲: ایجاد عناصر اولیه (Primitives) قابل استفاده مجدد
برای ساخت واقعی یک سیستم طراحی، نباید کامپوننتهای Headless UI را به طور مکرر در فایلهای نمایش (view files) استفاده کنید. در عوض، آنها را درون کامپوننتهای اولیه خودتان بپیچید (wrap کنید). این کار تضمین میکند که هر دکمه، ورودی یا مودالی در برنامه شما از دستورالعملهای برند شما پیروی میکند.
برای مثال، بیایید یک CustomButton قابل استفاده مجدد ایجاد کنیم که سبکهای استاندارد دکمه Tailwind را در بر میگیرد. اگرچه Headless UI بر تعاملات پیچیده تمرکز دارد، عناصر ساده از مدیریت متمرکز سبکها بهره میبرند.
// components/CustomButton.jsx
import React from 'react';
const CustomButton = ({ children, variant = 'primary', className, ...props }) => {
const baseStyles = "px-4 py-2 rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2";
const variants = {
primary: "bg-primary-500 text-white hover:bg-primary-700 focus:ring-primary-500",
secondary: "bg-gray-200 text-gray-800 hover:bg-gray-300 focus:ring-gray-500",
};
return (
);
};
export default CustomButton;
مرحله ۳: یکپارچهسازی کامپوننتهای پیچیده Headless
حال، بیایید به یک کامپوننت پیچیدهتر نگاه کنیم: یک Combobox. Headless UI این کار را با مدیریت منطق لیست بازشو بسیار آسان میکند، در حالی که ما کلاسهای Tailwind خود را اعمال میکنیم.
import { Combobox } from '@headlessui/react';
import { CheckIcon, ChevronUpDownIcon } from '@heroicons/react/20/solid';
const people = [
{ id: 1, name: 'Wade Cooper' },
{ id: 2, name: 'Arlene Mccoy' },
];
export default function UserCombobox() {
const [selected, setSelected] = React.useState(people[0]);
const [query, setQuery] = React.useState('');
const filteredPeople = query === ''
? people
: people.filter((person) =>
person.name.toLowerCase().replace(/\s+,/, '').includes(query.toLowerCase())
);
return (
setQuery(event.target.value)}
/>
{filteredPeople.length === 0 && query !== '' ? (
Nothing found.
) : (
filteredPeople.map((person) => (
`relative cursor-default select-none py-2 pl-10 pr-4 ${active ? 'bg-blue-600 text-white' : 'text-gray-900'}`
}
value={person}
>
{({ selected, active }) => (
<>
{person.name}
{selected ? (
) : null}
>
)}
))
)}
);
}
بهترین شیوهها برای نگهداری
- کامپوننتها را خالص نگه دارید: اجازه دهید Headless UI مدیریت حالت را بر عهده داشته باشد و از Tailwind برای ارائه (presentation) استفاده کنید. از ترکیب منطق حالت با کلاسهای سبکدهی خودداری کنید.
- واریانتها را مستند کنید: یک Storybook یا سایت مستندسازی مشابه برای عناصر اولیه خود ایجاد کنید تا تمام واریانتهای موجود را نشان دهد.
- دسترسپذیری را اجبار کنید: از آنجا که Headless UI ویژگیهای aria را مدیریت میکند، مطمئن شوید که هرگز آنها را حذف نمیکنید. کامپوننتهای خود را به طور منظم با خوانندههای صفحه (screen readers) آزمایش کنید.
نتیجهگیری
ساخت یک سیستم طراحی با Tailwind CSS و Headless UI یکی از کارآمدترین روشها برای ایجاد تعادل بین سرعت و کیفیت است. با جداسازی منطق از سبک، شما پایهای انعطافپذیر ایجاد میکنید که به طراحان و توسعهدهندگان اجازه میدهد همگام با هم حرکت کنند. با مقیاسپذیر شدن پروژه شما، این رویکرد از تورم سبک (style bloat) جلوگیری میکند و تضمین میکند که رابط کاربری شما قابل دسترس و همسان باقی بماند. کوچک شروع کنید، عناصر اولیه خود را بسازید و سرعت نمونهسازی خود را به پرواز درآورید.