Tích hợp TailwindCSS và Shadcn/UI vào Docusaurus
Docusaurus - một công cụ tạo trang web tĩnh mã nguồn mở dựa trên React, nổi tiếng với khả năng tạo tài liệu, blog, trang web marketing và ứng dụng web một trang một cách nhanh chóng và dễ dàng. Điểm mạnh của Docusaurus nằm ở giao diện tích hợp sẵn, tài liệu chi tiết, hướng dẫn sử dụng, và cộng đồng người dùng lớn sẵn sàng hỗ trợ.
Kết hợp với TailwindCSS là một framework CSS tiện dụng, tập trung vào việc cung cấp các utility classes (lớp tiện ích) để bạn dễ dàng xây dựng giao diện mà không cần viết quá nhiều CSS tùy chỉnh. Khác với các framework truyền thống như Bootstrap, Tailwind không cung cấp các thành phần sẵn có, thay vào đó, bạn sẽ tự do "xây dựng mọi thứ" dựa trên các utility classes như bg-blue-500
, text-center
, hoặc flex
.
Shadcn/UI là một thư viện giao diện hiện đại được xây dựng dựa trên TailwindCSS. Thay vì chỉ cung cấp các lớp tiện ích, Shadcn/UI mang đến các thành phần (components) sẵn có như Button, Input, Dropdown, Modal,... với thiết kế đẹp mắt, có thể dễ dàng tùy chỉnh và mở rộng.
Sự kết hợp này giúp bạn tạo ra các trang web và ứng dụng web không chỉ đẹp mắt, hiện đại mà còn dễ sử dụng, mang đến trải nghiệm tuyệt vời cho người dùng.
Hãy cùng tham khảo bài viết dưới đây để tích hợp TailwindCSS và Shadcn/UI vào Docusaurus.
Thiết lập ban đầu
Vì Shadcn/UI được không được xây dựng cho Docusaurus nên chúng ta sẽ cần thực hiện một số điều chỉnh để nó hoạt động với Docusaurus. Đầu tiên, hãy tạo một dự án Docusaurus mới nếu bạn chưa có:
npx create-docusaurus@latest my-website classic
cd my-website
Cài đặt các phụ thuộc cần thiết:
npm install tailwindcss tailwindcss-animate postcss autoprefixer class-variance-authority tailwind-merge lucide-react
Cấu hình Tailwind CSS
Tạo file tailwind.config.js
ở thư mục gốc của dự án:
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}', './docs/**/*.{js,jsx,ts,tsx}', './blog/**/*.{js,jsx,ts,tsx}'],
darkMode: ['class', '[data-theme="dark"]'], // Support Docusaurus dark mode
theme: {
extend: {
colors: {
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))',
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))',
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))',
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))',
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))',
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))',
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))',
},
},
borderRadius: {
lg: `var(--radius)`,
md: `calc(var(--radius) - 2px)`,
sm: 'calc(var(--radius) - 4px)',
},
},
},
plugins: [require('tailwindcss-animate')],
};
Tạo file postcss.config.js
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Thiết lập CSS
Tạo file src/css/custom.css
hoặc chỉnh sửa nếu tồn tại, đây là nơi bạn tạo theme của Shadcn/UI.
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--card: 0 0% 100%;
--card-foreground: 222.2 84% 4.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
html[data-theme='dark'] {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--card: 222.2 84% 4.9%;
--card-foreground: 210 40% 98%;
--popover: 222.2 84% 4.9%;
--popover-foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
--secondary: 217.2 32.6% 17.5%;
--secondary-foreground: 210 40% 98%;
--muted: 217.2 32.6% 17.5%;
--muted-foreground: 215 20.2% 65.1%;
--accent: 217.2 32.6% 17.5%;
--accent-foreground: 210 40% 98%;
--destructive: 0 62.8% 30.6%;
--destructive-foreground: 210 40% 98%;
--border: 217.2 32.6% 17.5%;
--input: 217.2 32.6% 17.5%;
--ring: 212.7 26.8% 83.9%;
}
}
Tạo thư mục Utils
Tạo src/lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
Tạo Shadcn/UI Components
❗️ Lưu ý: do Shadcn/ui không xây dựng dành cho Docusaurus nên bạn không thể tải các component bằng CLI, thay vào đó là bạn sao chép các component một cách thủ công.
Các bước thêm bao gồm:
- Tạo một thư mục chứa component:
src/components/ui
- Copy các component trên Shadcn/ui.
- Điều chỉnh đường dẫn import cho phù hợp và tải các packages nếu component yêu cầu.
Ví dụ: Button component (src/components/ui/button.tsx
)
import * as React from 'react'
import { Slot } from '@radix-ui/react-slot'
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '../../lib/utils'
const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
outline:
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline'
},
size: {
default: 'h-9 px-4 py-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
icon: 'h-9 w-9'
}
},
defaultVariants: {
variant: 'default',
size: 'default'
}
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : 'button'
return (
<Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
)
}
)
Button.displayName = 'Button'
export { Button, buttonVariants }
Tạo plugin Tailwind CSS
Tạo file cấu hình Tailwind trong src/plugins/tailwind-config.js
module.exports = function tailwindPlugin(context, options) {
return {
name: 'tailwind-plugin',
configurePostCss(postcssOptions) {
postcssOptions.plugins = [require('postcss-import'), require('tailwindcss'), require('autoprefixer')];
return postcssOptions;
},
};
};
Cập nhật cấu hình Docusaurus
Điều chỉnh file docusaurus.config.js
, thêm plugin Tailwind bạn vừa tạo.
plugins: [['./src/plugins/tailwind-config.js', {}]];
Sử dụng Shadcn/UI Components
Bây giờ bạn có thể sử dụng các components của Shadcn/ui trong dự án Docusaurus của mình.
import React from 'react';
import { Button } from '../components/ui/button';
export default function Home() {
return (
<div className="p-4">
<Button>Click me</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Settings</Button>
</div>
);
}
Demo
Bạn có thể thao khảo repo docusaurus-tailwind-shadcn-template mà mình đã tạo. Trong dự án này đã tích hợp TailwindCSS & Shadcn/UI vào Docusaurus. Bên cạnh đó, mình đã custom lại giao diện, tạo 1 plugin giúp đem blog hiện thị ở ngoài homepage.
👉 Xem thông tin chi tiết repo ở README.md
📌 Repository: https://github.com/namnguyenthanhwork/docusaurus-tailwind-shadcn-template
🚀 Demo: https://docusaurus-tailwind-shadcn-template.vercel.app/
Hãy ủng hộ 1 ⭐️ nếu bạn yêu thích nó. Cảm ơn nhé ❤️
Chia sẻ: