♻️ Viết Component Tái Sử Dụng với Tailwind CSS

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 íchGiải thích
🔁 Dễ dùng lạiViết 1 lần – dùng nhiều nơi
🧼 Giao diện đồng nhấtTránh lặp code class Tailwind khắp nơi
🔧 Dễ nâng cấpCậ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
🔘 ButtonNhiều biến thể: primary, outline, ghost, icon
📦 CardLayout sản phẩm, thông tin người dùng
🔔 AlertCác trạng thái: success, error, info
💬 BadgeTrạng thái: online, pending, warning
📩 ModalCó slot nội dung + nút đóng
🧾 InputFieldLabel + 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