SKILL.md
唯讀
名稱
shadcn-ui
描述
提供完整的 shadcn/ui 元件庫模式,包含安裝、設定及實作無障礙 React 元件。適用於設定 shadcn/ui、安裝元件、使用 React Hook Form 和 Zod 建立表單、透過 Tailwind CSS 自訂主題,或實作按鈕、對話框、下拉選單、表格及複雜表單佈局等 UI 模式。
shadcn/ui 元件模式
使用 shadcn/ui、Radix UI 和 Tailwind CSS 建立可存取、可自訂的 UI 元件。
概覽
- 元件會複製到你的專案中 — 你擁有並可自訂程式碼
- 基於 Radix UI 基礎元件,確保完整無障礙
- 使用 Tailwind CSS 和 CSS 變數進行主題樣式設定
- CLI 安裝方式:
npx shadcn@latest add <component>
使用時機
當使用者要求涉及以下內容時啟用:
- 「設定 shadcn/ui」、「初始化 shadcn」、「加入 shadcn 元件」
- 「安裝 button/input/form/dialog/card/select/toast/table/chart」
- 「React Hook Form」、「Zod 驗證」、「含驗證的表單」
- 「無障礙元件」、「Radix UI」、「Tailwind 主題」
- 「shadcn button」、「shadcn dialog」、「shadcn sheet」、「shadcn table」
- 「深色模式」、「CSS 變數」、「自訂主題」
- 「使用 Recharts 的圖表」、「長條圖」、「折線圖」、「圓餅圖」
快速參考
可用元件
| 元件 | 安裝指令 | 說明 |
|---|---|---|
button |
npx shadcn@latest add button |
變體:default、destructive、outline、secondary、ghost、link |
input |
npx shadcn@latest add input |
文字輸入欄位 |
form |
npx shadcn@latest add form |
整合 React Hook Form 與驗證 |
card |
npx shadcn@latest add card |
包含標頭、內容、頁尾的容器 |
dialog |
npx shadcn@latest add dialog |
模態覆蓋層 |
sheet |
npx shadcn@latest add sheet |
滑出面板(上/右/下/左) |
select |
npx shadcn@latest add select |
下拉選單 |
toast |
npx shadcn@latest add toast |
通知提示 |
table |
npx shadcn@latest add table |
資料表格 |
menubar |
npx shadcn@latest add menubar |
桌面風格的選單列 |
chart |
npx shadcn@latest add chart |
包含主題的 Recharts 包裝 |
textarea |
npx shadcn@latest add textarea |
多行文字輸入 |
checkbox |
npx shadcn@latest add checkbox |
核取方塊 |
label |
npx shadcn@latest add label |
無障礙表單標籤 |
操作說明
初始化專案
# 新的 Next.js 專案
npx create-next-app@latest my-app --typescript --tailwind --eslint --app
cd my-app
npx shadcn@latest init
# 現有專案
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react
npx shadcn@latest init
# 安裝元件
npx shadcn@latest add button input form card dialog select toast
基本元件用法
// 含變體與尺寸的按鈕
import { Button } from "@/components/ui/button"
<Button variant="default">預設</Button>
<Button variant="destructive" size="sm">刪除</Button>
<Button variant="outline" disabled>載入中...</Button>
含 Zod 驗證的表單
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/components/ui/button"
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
const formSchema = z.object({
email: z.string().email("無效的電子郵件"),
password: z.string().min(8, "密碼至少需要 8 個字元"),
})
export function LoginForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: { email: "", password: "" },
})
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(console.log)} className="space-y-4">
<FormField name="email" control={form.control} render={({ field }) => (
<FormItem>
<FormLabel>電子郵件</FormLabel>
<FormControl><Input type="email" {...field} /></FormControl>
<FormMessage />
</FormItem>
)} />
<FormField name="password" control={form.control} render={({ field }) => (
<FormItem>
<FormLabel>密碼</FormLabel>
<FormControl><Input type="password" {...field} /></FormControl>
<FormMessage />
</FormItem>
)} />
<Button type="submit">登入</Button>
</form>
</Form>
)
}
更多進階多欄位表單、含 API 提交的聯絡表單及登入卡片模式,請參閱 references/forms-and-validation.md。
對話框(模態)
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">開啟</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>編輯個人資料</DialogTitle>
</DialogHeader>
{/* 內容 */}
</DialogContent>
</Dialog>
通知提示
// 1. 在 app/layout.tsx 中加入 <Toaster />
import { Toaster } from "@/components/ui/toaster"
// 2. 在元件中使用
import { useToast } from "@/components/ui/use-toast"
const { toast } = useToast()
toast({ title: "成功", description: "變更已儲存。" })
toast({ variant: "destructive", title: "錯誤", description: "發生錯誤。" })
長條圖
import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"
const chartConfig = {
desktop: { label: "桌上型", color: "var(--chart-1)" },
} satisfies import("@/components/ui/chart").ChartConfig
<ChartContainer config={chartConfig} className="min-h-[200px] w-full">
<BarChart data={data}>
<CartesianGrid vertical={false} />
<XAxis dataKey="month" />
<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
<ChartTooltip content={<ChartTooltipContent />} />
</BarChart>
</ChartContainer>
更多折線圖、區域圖和圓餅圖範例,請參閱 references/charts-components.md。
範例
含驗證的登入表單
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import { z } from "zod"
import { Button } from "@/components/ui/button"
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
const formSchema = z.object({
email: z.string().email("無效的電子郵件"),
password: z.string().min(8, "至少 8 個字元"),
})
export function LoginForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: { email: "", password: "" },
})
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(console.log)} className="space-y-4">
<FormField name="email" control={form.control} render={({ field }) => (
<FormItem>
<FormLabel>電子郵件</FormLabel>
<FormControl><Input type="email" {...field} /></FormControl>
<FormMessage />
</FormItem>
)} />
<FormField name="password" control={form.control} render={({ field }) => (
<FormItem>
<FormLabel>密碼</FormLabel>
<FormControl><Input type="password" {...field} /></FormControl>
<FormMessage />
</FormItem>
)} />
<Button type="submit">登入</Button>
</form>
</Form>
)
}
含操作的資料表格
import { ColumnDef } from "@tanstack/react-table"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import { DataTable } from "@/components/ui/data-table"
const columns: ColumnDef<User>[] = [
{ id: "select", header: ({ table }) => (
<Checkbox checked={table.getIsAllPageRowsSelected()} />
), cell: ({ row }) => (
<Checkbox checked={row.getIsSelected()} />
)},
{ accessorKey: "name", header: "姓名" },
{ accessorKey: "email", header: "電子郵件" },
{ id: "actions", cell: ({ row }) => (
<Button variant="ghost" size="sm">編輯</Button>
)},
]
含表單的對話框
import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">新增使用者</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>新增使用者</DialogTitle>
</DialogHeader>
{/* <LoginForm /> */}
</DialogContent>
</Dialog>
通知提示
import { useToast } from "@/components/ui/use-toast"
import { Button } from "@/components/ui/button"
const { toast } = useToast()
toast({ title: "已儲存", description: "變更已成功儲存。" })
toast({ variant: "destructive", title: "錯誤", description: "儲存失敗。" })
最佳實務
- 無障礙:使用 Radix UI 基礎元件 — 內建 ARIA 屬性
- 客戶端元件:為互動式元件(hooks、事件)加上
"use client" - 型別安全:使用 TypeScript 和 Zod 架構進行表單驗證
- 主題設定:在
globals.css中設定 CSS 變數以維持一致的設計 - 自訂化:直接修改元件檔案 — 你擁有程式碼
- 路徑別名:確保在
tsconfig.json中設定@別名 - 註冊表安全性:僅從信任的註冊表安裝元件;在正式環境使用前審查產生的程式碼
- 深色模式:使用 CSS 變數策略和
next-themes設定 - 表單:務必一起使用
Form、FormField、FormItem、FormLabel、FormMessage - Toaster:在根佈局中加入一次
<Toaster />
限制與警告
- 非 NPM 套件:元件會複製到你的專案中,並非版本化的依賴項
- 註冊表安全性:從
npx shadcn@latest add取得的元件是遠端擷取;安裝前務必確認註冊表來源可信 - 客戶端元件:大多數互動式元件需要
"use client"指令 - Radix 依賴:確保所有
@radix-ui套件已安裝 - 需要 Tailwind:元件依賴 Tailwind CSS 工具類別
- 路徑別名:在
tsconfig.json中設定@別名以用於匯入
參考資料
詳細模式與程式碼範例請參閱以下檔案:
- references/setup-and-configuration.md — 完整安裝、tsconfig、tailwind 設定、CSS 變數
- references/ui-components.md — Button、Input、Card、Dialog、Sheet、Select、Toast、Table、Menubar
- references/forms-and-validation.md — React Hook Form + Zod、進階表單、登入卡片、聯絡表單
- references/charts-components.md — 長條圖、折線圖、區域圖、圓餅圖搭配 ChartContainer 與主題
- references/nextjs-integration.md — App Router、伺服器/客戶端元件、深色模式、中繼資料
- references/customization.md — 自訂變體、CSS 變數、cn() 工具函式、擴充元件






