Shadcn/UI là gì? Hướng dẫn cho người mới bắt đầu

Audrey Lopez

Audrey Lopez

14 tháng 6 2025

Shadcn/UI là gì? Hướng dẫn cho người mới bắt đầu

Đối với các nhà phát triển web, việc tìm kiếm bộ công cụ UI hoàn hảo là một nỗ lực không ngừng. Trong nhiều năm, các nhà phát triển React đã dựa vào các thư viện thành phần truyền thống như Material-UI (MUI), Ant Design và Chakra UI. Các thư viện này cung cấp vô số thành phần được xây dựng sẵn, hứa hẹn tăng tốc độ phát triển. Tuy nhiên, chúng thường đi kèm với một sự đánh đổi: thiếu kiểm soát, ghi đè kiểu dáng (style overrides) cảm giác như một cuộc chiến, và kích thước gói (bundle sizes) bị phình to.

Hãy chào đón Shadcn UI, một cách tiếp cận thay đổi mô hình đã gây bão trong cộng đồng React. Nó không phải là một thư viện thành phần theo cách bạn đã quen thuộc; nó là thứ gì đó tốt hơn. Đó là một bộ sưu tập các thành phần được thiết kế đẹp mắt, dễ tiếp cận (accessible) và có thể tái sử dụng vô tận mà bạn không cài đặt từ npm như một dependency—bạn sao chép chúng trực tiếp vào dự án của mình.

Hướng dẫn toàn diện, dài 4000 từ này sẽ là cẩm nang xác định của bạn, đưa bạn từ người mới bắt đầu hoàn toàn trở thành người sử dụng Shadcn UI tự tin. Chúng ta sẽ khám phá triết lý nền tảng của nó, đi sâu vào thiết lập chi tiết, xây dựng các giao diện phức tạp, nắm vững chủ đề nâng cao và xử lý biểu mẫu, và thảo luận về các thực hành tốt nhất cho các ứng dụng quy mô lớn. Hãy chuẩn bị để suy nghĩ lại về những gì bạn mong đợi từ một bộ công cụ UI.

💡
Bạn muốn một công cụ Kiểm thử API tuyệt vời có thể tạo Tài liệu API đẹp mắt?

Bạn muốn một nền tảng tích hợp, Tất cả trong một để Nhóm Phát triển của bạn làm việc cùng nhau với năng suất tối đa?

Apidog đáp ứng mọi yêu cầu của bạn và thay thế Postman với mức giá phải chăng hơn nhiều!
button

Triết lý Shadcn UI - Một Cách Xây Dựng Mới

Trước khi viết dòng mã đầu tiên, điều quan trọng nhất là phải hiểu tại sao Shadcn UI tồn tại và nó giải quyết những vấn đề gì. Nắm bắt triết lý cốt lõi này là chìa khóa để mở khóa toàn bộ tiềm năng của nó.

Shadcn UI Không Phải Là Gì

Shadcn UI Là Gì

Ưu điểm chính của mô hình này là sự kết hợp giữa tốc độ và kiểm soát. Bạn có được tốc độ ban đầu khi sử dụng các thành phần được xây dựng sẵn mà không phải hy sinh tính linh hoạt và khả năng bảo trì lâu dài đến từ việc sở hữu mã của riêng bạn.


Thiết Lập Sân Khấu - Thiết Lập Dự Án và Cài Đặt

Hãy chuyển từ lý thuyết sang thực hành. Chúng ta sẽ thiết lập một dự án mới từ đầu. Đối với hướng dẫn này, chúng ta sẽ chủ yếu sử dụng Next.js, vì các thành phần máy chủ (server components) và định tuyến dựa trên tệp của nó phù hợp hoàn hảo với triết lý Shadcn UI. Chúng ta cũng sẽ nói ngắn gọn về thiết lập cho Vite.

Bước 1: Các Yêu Cầu Tiên Quyết Về Môi Trường

Đảm bảo môi trường phát triển của bạn đã sẵn sàng. Bạn sẽ cần:

Bước 2: Tạo Một Ứng Dụng Next.js Mới

Mở terminal của bạn và thực thi lệnh sau để khởi tạo một dự án Next.js mới.Bash

npx create-next-app@latest my-pro-shadcn-app --typescript --tailwind --eslint

Lệnh này tạo cấu trúc một ứng dụng mới trong thư mục có tên my-pro-shadcn-app. Chúng ta đã bao gồm một số cờ quan trọng:

Trình cài đặt sẽ hỏi bạn một vài câu hỏi. Đây là các lựa chọn được khuyến nghị cho thiết lập Next.js 14+ hiện đại:

✔ Would you like to use `src/` directory? … No / **Yes**
✔ Would you like to use App Router? (recommended) … No / **Yes**
✔ Would you like to customize the default import alias? … **No** / Yes

Sử dụng App Router là thực hành tiêu chuẩn, và thư mục src/ giúp tổ chức mã. Sau khi hoàn thành, điều hướng vào dự án mới của bạn:Bash

cd my-pro-shadcn-app

Bước 3: Lệnh init - Đưa Shadcn UI Vào Hoạt Động

Đây là bước quan trọng nhất. Shadcn UI cung cấp một công cụ CLI để cấu hình dự án của bạn. Chạy lệnh sau từ thư mục gốc của dự án của bạn:Bash

npx shadcn-ui@latest init

Điều này sẽ kích hoạt một bảng câu hỏi tương tác để thiết lập dự án của bạn. Hãy phân tích từng câu hỏi và ý nghĩa của nó:

Sau khi bạn xác nhận, CLI sẽ thực hiện công việc của nó:

  1. Cài đặt Dependencies: Nó thêm các gói cần thiết như tailwindcss-animateclass-variance-authority.
  2. Tạo components.json: Lưu trữ các lựa chọn cấu hình của bạn.
  3. Cập nhật tailwind.config.ts: Chèn plugin Shadcn UI và cấu hình tạo chủ đề.
  4. Cập nhật globals.css: Thêm một khối lớn các biến CSS định nghĩa toàn bộ bảng màu, bán kính bo tròn (border radii), và nhiều hơn nữa.
  5. Tạo lib/utils.ts: Tệp này xuất một hàm trợ giúp cn, một tiện ích thông minh để hợp nhất có điều kiện các lớp Tailwind CSS.

Dự án của bạn giờ đây đã được cấu hình đầy đủ.

(Thay thế: Thiết lập Vite)

Nếu bạn đang sử dụng Vite với React, quy trình tương tự. Sau khi thiết lập dự án Vite + React + TS, bạn sẽ cài đặt Tailwind CSS theo cách thủ công và sau đó chạy npx shadcn-ui@latest init. CLI đủ thông minh để phát hiện thiết lập Vite và sẽ hỏi các câu hỏi hơi khác về vị trí tệp (ví dụ: index.css thay vì globals.css).


Xây Dựng UI - Từ Các Thành Phần Đơn Giản Đến Các Bố Cục Phức Tạp

Với việc thiết lập đã hoàn thành, hãy bắt đầu xây dựng. Quy trình làm việc cốt lõi là: xác định nhu cầu, thêm thành phần, sử dụng nó.

Bước 4: Thêm và Sử Dụng Các Thành Phần Đầu Tiên Của Bạn

Hãy dọn dẹp mã boilerplate mặc định của Next.js và xây dựng một giao diện đơn giản.

1. Thêm một Nút (Button):Bash

npx shadcn-ui@latest add button

Quan sát điều gì xảy ra: một tệp mới, src/components/ui/button.tsx, được tạo. Đây là nút của bạn. Bạn sở hữu nó.

2. Thêm một Thẻ (Card):Bashnpx shadcn-ui@latest add card

Lệnh này thú vị hơn. Nó tạo ra src/components/ui/card.tsx. Nếu bạn kiểm tra tệp này, bạn sẽ thấy nó xuất nhiều thành phần: Card, CardHeader, CardTitle, CardDescription, CardContent, và CardFooter. Đây là một mẫu phổ biến cho các thành phần phức hợp (compound components).

3. Xây Dựng UI:

Bây giờ, mở src/app/page.tsx và thay thế nội dung của nó bằng đoạn mã sau:TypeScript

import { Button } from "@/components/ui/button";
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input"; // Chúng ta sẽ thêm cái này tiếp theo
import { Label } from "@/components/ui/label";   // Và cái này

export default function Home() {
  return (
    <main className="flex min-h-screen items-center justify-center bg-background p-8">
      <Card className="w-full max-w-md">
        <CardHeader>
          <CardTitle className="text-2xl">Create Project</CardTitle>
          <CardDescription>
            Deploy your new project in one-click.
          </CardDescription>
        </CardHeader>
        <CardContent className="grid gap-4">
          <div className="grid gap-2">
            <Label htmlFor="name">Name</Label>
            <Input id="name" placeholder="Name of your project" />
          </div>
          <div className="grid gap-2">
            <Label htmlFor="framework">Framework</Label>
            {/* Chúng ta sẽ thay thế cái này bằng thành phần Select sau */}
            <Input id="framework" placeholder="e.g. Next.js" />
          </div>
        </CardContent>
        <CardFooter>
          <Button className="w-full">Deploy</Button>
        </CardFooter>
      </Card>
    </main>
  );
}

Mã của chúng ta sẽ chưa chạy vì chúng ta thiếu các thành phần InputLabel. Hãy thêm chúng:Bash

npx shadcn-ui@latest add input
npx shadcn-ui@latest add label

Bây giờ, chạy máy chủ phát triển của bạn:Bash

npm run dev

Điều hướng đến http://localhost:3000. Bạn sẽ thấy một biểu mẫu gọn gàng, chuyên nghiệp bên trong một thẻ. Lưu ý cách chúng ta sử dụng các lớp tiện ích như w-full, max-w-md, và grid trực tiếp trong JSX để kiểm soát bố cục. Đây là sức mạnh của việc kết hợp Shadcn và Tailwind CSS.

Bước 5: Giới Thiệu Các Thành Phần Phức Tạp Hơn

Các trường nhập liệu tĩnh là tốt, nhưng các ứng dụng thực tế cần các yếu tố tương tác. Hãy cải thiện biểu mẫu của chúng ta.

1. Thêm thành phần Select: Trường nhập "Framework" nên là một dropdown. Hãy thêm thành phần Select. Thành phần này phức tạp hơn và có dependencies vào các thành phần khác.Bash

npx shadcn-ui@latest add select

CLI đủ thông minh. Nó sẽ thấy rằng Select yêu cầu thành phần Popover để hoạt động và sẽ xin phép bạn cài đặt nó cùng với các dependencies của nó. Đây là một tính năng tuyệt vời giúp bạn không phải theo dõi dependencies thủ công.

2. Tích Hợp Thành Phần Select: Thay thế trường Input cho "Framework" trong src/app/page.tsx bằng thành phần Select mới.TypeScript

// Thêm các import này ở đầu
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";

// ... bên trong CardContent
<div className="grid gap-2">
  <Label htmlFor="framework">Framework</Label>
  <Select>
    <SelectTrigger id="framework">
      <SelectValue placeholder="Select a framework" />
    </SelectTrigger>
    <SelectContent>
      <SelectItem value="nextjs">Next.js</SelectItem>
      <SelectItem value="sveltekit">SvelteKit</SelectItem>
      <SelectItem value="astro">Astro</SelectItem>
      <SelectItem value="nuxt">Nuxt.js</SelectItem>
    </SelectContent>
  </Select>
</div>

Làm mới trình duyệt của bạn. Bây giờ bạn có một dropdown chọn hoàn toàn chức năng và dễ tiếp cận, đầy đủ các hiệu ứng động và điều hướng bàn phím phù hợp, tất cả nhờ Radix UI hoạt động ngầm.

3. Thêm Phản Hồi Người Dùng với Toast: Điều gì xảy ra khi người dùng nhấp vào "Deploy"? Chúng ta nên cung cấp cho họ một số phản hồi. Thành phần Toast là hoàn hảo cho việc này.

Đầu tiên, thêm nó:Bash

npx shadcn-ui@latest add toast

Tiếp theo, để sử dụng toasts, bạn cần thêm thành phần <Toaster /> vào layout gốc của bạn để nó có thể hiển thị ở bất kỳ đâu trong ứng dụng. Mở src/app/layout.tsx và sửa đổi nó:TypeScript

import { Toaster } from "@/components/ui/toaster" // Import Toaster

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Toaster /> {/* Thêm nó ở đây, ngay trước khi đóng body */}
      </body>
    </html>
  )
}

Bây giờ, chúng ta cần một cách để kích hoạt toast. Chúng ta sẽ sử dụng hook useToast. Hãy cập nhật src/app/page.tsx để biến nó thành một client component và xử lý sự kiện nhấp nút.TypeScript

'use client'; // <-- Thêm dòng này ở đầu tệp

// ... các import khác
import { useToast } from "@/components/ui/use-toast";

export default function Home() {
  const { toast } = useToast(); // Lấy hàm toast từ hook

  function handleDeploy() {
    toast({
      title: "Deployment Scheduled!",
      description: "Your project 'Name of your project' is being deployed.",
      duration: 5000,
    });
  }

  return (
    <main className="flex min-h-screen items-center justify-center bg-background p-8">
      <Card className="w-full max-w-md">
        {/* ... CardHeader và CardContent ... */}
        <CardFooter>
          <Button className="w-full" onClick={handleDeploy}> {/* Thêm onClick handler */}
            Deploy
          </Button>
        </CardFooter>
      </Card>
    </main>
  );
}

Bây giờ, khi bạn nhấp vào nút "Deploy", một thông báo đẹp mắt sẽ xuất hiện ở góc màn hình của bạn.


Xây Dựng Một Biểu Mẫu Chuyên Nghiệp Với Xác Thực

Hầu hết các ứng dụng thực tế yêu cầu xử lý biểu mẫu mạnh mẽ, bao gồm xác thực phía client. Cách chính thức để xử lý điều này với Shadcn UI là kết hợp nó với react-hook-form để quản lý trạng thái và zod để xác thực schema. Hãy xây dựng nó.

Bước 6: Cài Đặt Các Dependencies Cho Biểu Mẫu

Đầu tiên, hãy cài đặt các thư viện cần thiết:Bash

npm install react-hook-form zod @hookform/resolvers

Bước 7: Thêm Thành Phần Form Của Shadcn

Shadcn UI cung cấp một thành phần Form đặc biệt hoạt động như một trình bao bọc để kết nối liền mạch react-hook-form với các thành phần UI của bạn.Bash

npx shadcn-ui@latest add form

Điều này sẽ thêm src/components/ui/form.tsx. Tệp này cung cấp một tập hợp các thành phần nhận biết ngữ cảnh (Form, FormField, FormItem, FormLabel, FormControl, FormDescription, FormMessage) giúp giảm đáng kể mã boilerplate.

Bước 8: Tạo Schema Xác Thực

Trong tệp src/app/page.tsx của bạn, hãy định nghĩa hình dạng và quy tắc của dữ liệu biểu mẫu bằng cách sử dụng zod.TypeScript

// Thêm các import này ở đầu
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import {
  Form,
  FormControl,
  FormDescription,
  FormField,
  FormItem,
  FormLabel,
  FormMessage,
} from "@/components/ui/form";

Bây giờ, hãy tạo schema ngay phía trên thành phần Home của chúng ta:TypeScript

const formSchema = z.object({
  projectName: z.string().min(2, {
    message: "Tên dự án phải có ít nhất 2 ký tự.",
  }).max(50, {
    message: "Tên dự án không được vượt quá 50 ký tự.",
  }),
  framework: z.string({
    required_error: "Vui lòng chọn một framework để hiển thị.",
  }),
});

Schema này định nghĩa hai trường: projectName phải là một chuỗi từ 2 đến 50 ký tự, và framework là một chuỗi bắt buộc.

Bước 9: Kết Nối Biểu Mẫu

Bây giờ, hãy tái cấu trúc thành phần Home của chúng ta để sử dụng tất cả các công cụ mới này.TypeScript

export default function Home() {
  const { toast } = useToast();

  // 1. Định nghĩa biểu mẫu của bạn.
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
    defaultValues: {
      projectName: "",
    },
  });

  // 2. Định nghĩa một trình xử lý gửi biểu mẫu (submit handler).
  function onSubmit(values: z.infer<typeof formSchema>) {
    // Làm gì đó với các giá trị biểu mẫu.
    // ✅ Điều này sẽ an toàn về kiểu và đã được xác thực.
    console.log(values);
    toast({
      title: "Bạn đã gửi các giá trị sau:",
      description: (
        <pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
          <code className="text-white">{JSON.stringify(values, null, 2)}</code>
        </pre>
      ),
    });
  }

  // 3. Xây dựng JSX với các thành phần Form của Shadcn
  return (
    <main className="flex min-h-screen items-center justify-center bg-background p-8">
      <Card className="w-full max-w-md">
        <CardHeader>
          <CardTitle className="text-2xl">Create Project</CardTitle>
          <CardDescription>
            Deploy your new project in one-click.
          </CardDescription>
        </CardHeader>
        <CardContent>
          <Form {...form}>
            <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
              <FormField
                control={form.control}
                name="projectName"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Name</FormLabel>
                    <FormControl>
                      <Input placeholder="Name of your project" {...field} />
                    </FormControl>
                    <FormDescription>
                      This is your public display name.
                    </FormDescription>
                    <FormMessage /> {/* Hiển thị lỗi xác thực */}
                  </FormItem>
                )}
              />
              <FormField
                control={form.control}
                name="framework"
                render={({ field }) => (
                  <FormItem>
                    <FormLabel>Framework</FormLabel>
                    <Select onValueChange={field.onChange} defaultValue={field.value}>
                      <FormControl>
                        <SelectTrigger>
                          <SelectValue placeholder="Select a framework" />
                        </SelectTrigger>
                      </FormControl>
                      <SelectContent>
                        <SelectItem value="nextjs">Next.js</SelectItem>
                        <SelectItem value="sveltekit">SvelteKit</SelectItem>
                        <SelectItem value="astro">Astro</SelectItem>
                        <SelectItem value="nuxt">Nuxt.js</SelectItem>
                      </SelectContent>
                    </Select>
                    <FormDescription>
                      The framework you want to deploy.
                    </FormDescription>
                    <FormMessage />
                  </FormItem>
                )}
              />
              <Button type="submit" className="w-full">Deploy</Button>
            </form>
          </Form>
        </CardContent>
      </Card>
    </main>
  );
}

Đây là một đoạn mã khá dài, nhưng nó là một mẫu cực kỳ mạnh mẽ và có khả năng mở rộng. Thành phần FormField xử lý tất cả các kết nối trạng thái, và FormMessage tự động hiển thị lỗi xác thực chính xác từ schema zod của bạn khi người dùng tương tác với trường. Hãy thử gửi biểu mẫu với tên dự án trống để xem xác thực hoạt động.


Nắm Vững Việc Tạo Chủ Đề và Tùy Chỉnh

Sức mạnh thực sự của Shadcn UI được giải phóng khi bạn bắt đầu biến nó thành của riêng mình.

Bước 10: Tạo Chủ Đề Nâng Cao với Các Biến CSS

Toàn bộ chủ đề của bạn được định nghĩa bởi các biến CSS trong src/app/globals.css. Mở tệp này và tìm các khối :root.dark.CSS

/* Ví dụ từ globals.css */
:root {
  --background: 0 0% 100%;
  --foreground: 222.2 84% 4.9%;
  --primary: 222.2 47.4% 11.2%;
  --primary-foreground: 210 40% 98%;
  /* ... và nhiều hơn nữa */
  --radius: 0.5rem;
}

.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  --primary: 210 40% 98%;
  --primary-foreground: 222.2 47.4% 11.2%;
  /* ... */
}

Triển khai Chế Độ Tối:

Shadcn được cấu hình sẵn cho chế độ tối nhờ khối lớp .dark và chiến lược darkMode: "class" của Tailwind trong tailwind.config.ts. Tất cả những gì bạn cần là một cách để bật/tắt lớp dark trên phần tử <html>. Một thư viện phổ biến cho việc này là next-themes.

  1. Cài đặt nó: npm install next-themes
  2. Tạo một thành phần ThemeProvider (src/components/theme-provider.tsx): TypeScript
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"

export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
  return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
  1. Bao bọc RootLayout của bạn trong provider này (src/app/layout.tsx): TypeScript
import { ThemeProvider } from "@/components/theme-provider"

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider
          attribute="class"
          defaultTheme="system"
          enableSystem
          disableTransitionOnChange
        >
          {children}
          <Toaster />
        </ThemeProvider>
      </body>
    </html>
  )
}
  1. Cuối cùng, tạo một nút chuyển đổi (ví dụ: src/components/mode-toggle.tsx): TypeScript
"use client"
import * as React from "react"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"
import { Button } from "@/components/ui/button"

export function ModeToggle() {
  const { theme, setTheme } = useTheme()

  return (
    <Button
      variant="outline"
      size="icon"
      onClick={() => setTheme(theme === "light" ? "dark" : "light")}
    >
      <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
      <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
      <span className="sr-only">Toggle theme</span>
    </Button>
  )
}

Bây giờ bạn có thể đặt <ModeToggle /> này ở bất kỳ đâu trong ứng dụng của mình để có một nút chuyển đổi chế độ tối nhận biết hệ thống và có thể ghi đè bởi người dùng.

Bước 11: Tùy Chỉnh Mã Nguồn Thành Phần

Đây là siêu năng lực tối thượng. Giả sử bạn muốn một biến thể thành công (success variant) mới cho nút của mình có nền màu xanh lá cây.

Mở src/components/ui/button.tsx. Tìm định nghĩa buttonVariants. Nó sử dụng cva (Class Variance Authority). Đơn giản chỉ cần thêm một biến thể mới:TypeScript

const buttonVariants = cva(
  // ... kiểu dáng cơ bản
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
        outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
        secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
        ghost: "hover:bg-accent hover:text-accent-foreground",
        link: "text-primary underline-offset-4 hover:underline",
        success: "bg-green-600 text-white hover:bg-green-600/90", // Biến thể mới của chúng ta
      },
      // ... biến thể kích thước
    },
    defaultVariants: {
      variant: "default",
      size: "default",
    },
  }
)

Chỉ vậy thôi. Bây giờ bạn có thể sử dụng nó trong mã của mình: <Button variant="success">Success</Button>. Bạn không cần phải viết các ghi đè CSS phức tạp. Bạn chỉ cần chỉnh sửa mã nguồn của chính thành phần đó. Quy trình làm việc này đơn giản, dễ đoán và cực kỳ mạnh mẽ.


Phần 6: Các Thực Hành Tốt Nhất và Con Đường Phía Trước

Khi ứng dụng của bạn phát triển, đây là một số thực hành tốt nhất cần ghi nhớ.

Kết Luận: Bạn Là Tác Giả Thư Viện

Bây giờ bạn đã đi từ triết lý cốt lõi của Shadcn UI đến việc triển khai các mẫu nâng cao, thực tế. Bạn đã thấy rằng sự đổi mới thực sự của nó không chỉ nằm ở bản thân các thành phần, mà còn ở sự thay đổi mô hình mà nó đại diện. Nó chuyển các nhà phát triển từ việc chỉ là người tiêu dùng của một thư viện sang trở thành người quản lýngười sở hữu bộ công cụ UI của riêng họ.

Bằng cách cung cấp cho bạn mã nguồn thô, xây dựng trên nền tảng vững chắc của Tailwind CSS và Radix UI, và cung cấp trải nghiệm CLI liền mạch, Shadcn UI đạt được sự cân bằng hoàn hảo giữa tốc độ phát triển ban đầu và khả năng bảo trì lâu dài cùng sự tự do sáng tạo. Bạn không còn bị ràng buộc bởi hệ thống thiết kế của người khác. Các thành phần trong dự án của bạn là của riêng bạn—để sửa đổi, mở rộng và hoàn thiện.

Tương lai của UI ứng dụng của bạn không còn nằm trong tay một dependency bên thứ ba; nó nằm ngay trong thư mục components của bạn. Chúc bạn xây dựng vui vẻ.

💡
Bạn muốn một công cụ Kiểm thử API tuyệt vời có thể tạo Tài liệu API đẹp mắt?

Bạn muốn một nền tảng tích hợp, Tất cả trong một để Nhóm Phát triển của bạn làm việc cùng nhau với năng suất tối đa?

Apidog đáp ứng mọi yêu cầu của bạn và thay thế Postman với mức giá phải chăng hơn nhiều!
button

Thực hành thiết kế API trong Apidog

Khám phá cách dễ dàng hơn để xây dựng và sử dụng API