Tiếp nối chuỗi thực hành Tailwind CSS nâng cao, bài viết này sẽ hướng dẫn bạn cách viết các component tái sử dụng bằng cách kết hợp tư duy “utility-first” của Tailwind với cấu trúc module hóa. Đây là bước quan trọng để xây dựng hệ thống giao diện linh hoạt, dễ mở rộng và tiết kiệm thời gian khi làm việc nhóm hoặc phát triển dự án lớn.
🎯 Mục tiêu
- Xây dựng các component như:
Button
,Card
,Alert
,Input
,Modal
… - Gom nhóm class Tailwind với
@apply
để dễ tái sử dụng - Tùy biến component qua biến, props, slot (React, Vue…)
- Tổ chức thư mục UI có cấu trúc rõ ràng
💡 Vì sao cần viết component tái sử dụng?
Lợi ích | Giải thích |
---|---|
🔁 Dễ dùng lại | Viết 1 lần – dùng nhiều nơi |
🧼 Giao diện đồng nhất | Tránh lặp code class Tailwind khắp nơi |
🔧 Dễ nâng cấp | Cập nhật 1 nơi, toàn bộ UI thay đổi theo |
🤝 Làm việc nhóm hiệu quả | Mỗi dev chỉ cần gọi <Button variant="primary" /> |
🧱 1. Cách tái sử dụng với @apply
(HTML/CSS thuần)
✨ Ví dụ: Tạo button tái sử dụng
/* styles/components.css */
@layer components {
.btn {
@apply inline-flex items-center px-4 py-2 rounded text-sm font-medium transition;
}
.btn-primary {
@apply bg-blue-600 text-white hover:bg-blue-700;
}
.btn-outline {
@apply border border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white;
}
.btn-danger {
@apply bg-red-600 text-white hover:bg-red-700;
}
}
<button class="btn btn-primary">Lưu</button>
<button class="btn btn-outline">Hủy</button>
<button class="btn btn-danger">Xóa</button>
👉 Có thể tạo thêm: .input
, .card
, .alert-success
, .badge
,…
⚛️ 2. Component tái sử dụng trong React (JSX)
// components/Button.jsx
export default function Button({ variant = 'primary', children }) {
const base = 'inline-flex items-center px-4 py-2 rounded text-sm font-medium transition';
const variants = {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
outline: 'border border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white',
danger: 'bg-red-600 text-white hover:bg-red-700'
};
return <button className={`${base} ${variants[variant]}`}>{children}</button>;
}
Sử dụng:
<Button>Lưu</Button>
<Button variant="outline">Hủy</Button>
<Button variant="danger">Xóa</Button>
🔷 3. Component tái sử dụng trong Vue 3
<!-- components/BaseButton.vue -->
<template>
<button :class="computedClass"><slot /></button>
</template>
<script setup>
const props = defineProps({
variant: { type: String, default: 'primary' }
});
const computedClass = computed(() => {
const base = 'inline-flex items-center px-4 py-2 rounded text-sm font-medium transition';
const variants = {
primary: 'bg-blue-600 text-white hover:bg-blue-700',
outline: 'border border-blue-600 text-blue-600 hover:bg-blue-600 hover:text-white',
danger: 'bg-red-600 text-white hover:bg-red-700'
};
return `${base} ${variants[props.variant]}`;
});
</script>
Sử dụng:
<BaseButton>Lưu</BaseButton>
<BaseButton variant="outline">Hủy</BaseButton>
<BaseButton variant="danger">Xóa</BaseButton>
🗂️ 4. Tổ chức thư mục component hiệu quả
src/
├── components/
│ ├── ui/
│ │ ├── Button.jsx
│ │ ├── Input.jsx
│ │ ├── Card.jsx
│ │ ├── Alert.vue
│ │ └── Modal.vue
│ └── layout/
│ └── Header.vue
│ └── Sidebar.jsx
👉 Bạn có thể gom thành thư viện UI riêng nếu dự án lớn.
🎨 Gợi ý viết thêm component UI tái sử dụng:
Component | Ý tưởng giao diện |
---|---|
🔘 Button | Nhiều biến thể: primary, outline, ghost, icon |
📦 Card | Layout sản phẩm, thông tin người dùng |
🔔 Alert | Các trạng thái: success, error, info |
💬 Badge | Trạng thái: online, pending, warning |
📩 Modal | Có slot nội dung + nút đóng |
🧾 InputField | Label + icon + validation |
✅ Kết luận
Viết component tái sử dụng với Tailwind giúp bạn:
- Tiết kiệm thời gian khi thiết kế giao diện
- Tăng độ nhất quán và dễ bảo trì trong toàn bộ dự án
- Tối ưu làm việc nhóm, chia sẻ UI nhanh chóng
- Dễ tích hợp trong mọi framework hiện đại