สำหรับนักพัฒนาเว็บ การแสวงหา UI toolkit ที่สมบูรณ์แบบเป็นความพยายามอย่างต่อเนื่อง เป็นเวลาหลายปีที่นักพัฒนา React อาศัยไลบรารีคอมโพเนนต์แบบดั้งเดิม เช่น Material-UI (MUI), Ant Design และ Chakra UI ไลบรารีเหล่านี้มีคอมโพเนนต์สำเร็จรูปมากมาย ซึ่งช่วยเร่งการพัฒนา อย่างไรก็ตาม มักจะมีข้อแลกเปลี่ยนคือ การขาดการควบคุม การปรับสไตล์ที่รู้สึกเหมือนเป็นการต่อสู้ และขนาดของ bundle ที่ใหญ่เกินไป
ขอแนะนำ Shadcn UI ซึ่งเป็นแนวทางที่พลิกโฉมวงการและได้รับความนิยมอย่างมากในชุมชน React ไม่ใช่ไลบรารีคอมโพเนนต์ในแบบที่คุณคุ้นเคย แต่เป็นสิ่งที่ดียิ่งกว่า เป็นชุดของคอมโพเนนต์ที่ออกแบบมาอย่างสวยงาม เข้าถึงได้ และนำกลับมาใช้ซ้ำได้อย่างไม่สิ้นสุด ซึ่งคุณไม่ได้ติดตั้งจาก npm เป็น dependency แต่คุณคัดลอกโค้ดโดยตรงลงในโปรเจกต์ของคุณ
บทช่วยสอนฉบับสมบูรณ์ความยาว 4000 คำนี้จะเป็นคู่มือที่ชัดเจนของคุณ โดยจะพาคุณจากผู้เริ่มต้นไปสู่ผู้ใช้งาน Shadcn UI ได้อย่างมั่นใจ เราจะสำรวจปรัชญาพื้นฐานของมัน เดินผ่านการตั้งค่าอย่างละเอียด สร้าง UI ที่ซับซ้อน เชี่ยวชาญการปรับแต่งธีมขั้นสูงและการจัดการฟอร์ม และพูดคุยเกี่ยวกับแนวทางปฏิบัติที่ดีที่สุดสำหรับแอปพลิเคชันขนาดใหญ่ เตรียมพร้อมที่จะคิดใหม่เกี่ยวกับสิ่งที่คุณคาดหวังจาก UI toolkit
ต้องการแพลตฟอร์มแบบ All-in-One ที่ผสานรวมสำหรับทีมพัฒนาของคุณเพื่อทำงานร่วมกันด้วย ประสิทธิภาพสูงสุด ใช่ไหม?
Apidog ตอบสนองทุกความต้องการของคุณ และ มาแทนที่ Postman ในราคาที่เข้าถึงได้ง่ายกว่ามาก!
ปรัชญาของ Shadcn UI - วิธีการสร้างแบบใหม่
ก่อนที่จะเขียนโค้ดแม้แต่บรรทัดเดียว สิ่งสำคัญที่สุดคือการทำความเข้าใจว่า ทำไม Shadcn UI จึงมีอยู่และแก้ปัญหาอะไร การเข้าใจปรัชญาหลักนี้คือกุญแจสำคัญในการปลดล็อกศักยภาพสูงสุดของมัน
สิ่งที่ Shadcn UI ไม่ใช่
- ไม่ใช่แพ็คเกจ npm แบบดั้งเดิม คุณจะไม่พบ
shadcn-ui
ในรายการ dependencies ของpackage.json
ของคุณ นี่คือความแตกต่างที่สำคัญที่สุด - ไม่ใช่ไลบรารีแบบ Monolithic ไม่ได้บังคับให้คุณติดตั้งคอมโพเนนต์หลายร้อยรายการเมื่อคุณต้องการเพียงแค่ปุ่มและช่องป้อนข้อมูล
- ไม่จำกัด คุณจะไม่ถูกจำกัดอยู่ในสไตล์การออกแบบเฉพาะเจาะจง หรือถูกจำกัดโดยความสามารถในการปรับแต่งธีมที่ผู้ดูแลไลบรารีจัดหาให้
สิ่งที่ Shadcn UI คือ
- ชุดโค้ดที่นำกลับมาใช้ซ้ำได้: ลองคิดว่ามันเป็นชุดสูตรอาหารที่คัดสรรมาอย่างดี คุณเลือกสูตรที่คุณต้องการ (เช่น คอมโพเนนต์
Card
) และคำแนะนำ (โค้ด) จะถูกมอบให้คุณเพื่อนำไปปรุงในครัวของคุณเอง (โปรเจกต์ของคุณ) - ความมุ่งมั่นในการเป็นเจ้าของโค้ด: เมื่อคุณเพิ่มคอมโพเนนต์ Shadcn โค้ดต้นฉบับของมัน ซึ่งเป็นไฟล์
.tsx
จะถูกวางไว้โดยตรงใน codebase ของคุณ โดยทั่วไปจะอยู่ในcomponents/ui/
ตอนนี้มันคือคอมโพเนนต์ ของคุณ คุณสามารถเปลี่ยนโครงสร้าง สไตล์ หรือ logic ของมันได้ทุกอย่าง สิ่งนี้ช่วยขจัดประสบการณ์ที่น่าหงุดหงิดในการต่อสู้กับ CSS overrides ที่ใช้!important
หรือ prop API ที่ซับซ้อนเพื่อให้ได้การปรับแต่งภาพง่ายๆ - สร้างขึ้นบนรากฐานที่แข็งแกร่งและทันสมัย: Shadcn UI ไม่ได้สร้างสิ่งใหม่ทั้งหมด แต่ยืนอยู่บนไหล่ของยักษ์ใหญ่:
- Tailwind CSS: เฟรมเวิร์ก CSS แบบ utility-first ที่มี building blocks ระดับต่ำสำหรับการสร้างดีไซน์ใดๆ ได้โดยตรงใน markup ของคุณ คอมโพเนนต์ของ Shadcn ถูกจัดสไตล์ด้วย Tailwind เท่านั้น ทำให้ง่ายต่อการปรับแต่งอย่างเหลือเชื่อหากคุณคุ้นเคยกับเฟรมเวิร์กนี้
- Radix UI: ไลบรารีของ UI primitives ระดับต่ำที่ไม่มีสไตล์ แต่เข้าถึงได้ Radix จัดการด้านที่ซับซ้อนและมักถูกมองข้ามของคอมโพเนนต์ UI ทั้งหมด เช่น การนำทางด้วยคีย์บอร์ด การจัดการโฟกัส และแอตทริบิวต์ ARIA เพื่อการเข้าถึง (a11y) Shadcn นำ primitives ที่ทรงพลังและ headless เหล่านี้มาเพิ่มสไตล์ที่สวยงามด้วย Tailwind CSS
ข้อได้เปรียบหลักของโมเดลนี้คือการรวมกันของ ความเร็วและการควบคุม คุณจะได้ความเร็วเริ่มต้นจากการใช้คอมโพเนนต์สำเร็จรูป โดยไม่เสียความยืดหยุ่นและความสามารถในการบำรุงรักษาในระยะยาวที่มาจากการเป็นเจ้าของโค้ดของคุณเอง
การเตรียมการ - การตั้งค่าโปรเจกต์และการติดตั้ง
มาเปลี่ยนจากทฤษฎีสู่การปฏิบัติ เราจะตั้งค่าโปรเจกต์ใหม่ตั้งแต่เริ่มต้น สำหรับคู่มือนี้ เราจะใช้ Next.js เป็นหลัก เนื่องจาก Server Components และการกำหนดเส้นทางตามไฟล์ของมันเข้ากันได้ดีกับแนวคิดของ Shadcn UI เราจะกล่าวถึงการตั้งค่าสำหรับ Vite สั้นๆ ด้วย
ขั้นตอนที่ 1: ข้อกำหนดเบื้องต้นของสภาพแวดล้อม
ตรวจสอบให้แน่ใจว่าสภาพแวดล้อมการพัฒนาของคุณพร้อมแล้ว คุณจะต้องมี:
- Node.js: แนะนำเวอร์ชัน Long-Term Support (LTS) ล่าสุด คุณสามารถดาวน์โหลดได้จาก เว็บไซต์ทางการของ Node.js
- ตัวจัดการแพ็คเกจ: บทช่วยสอนนี้จะใช้
npm
ซึ่งมาพร้อมกับ Node.js คุณสามารถใช้yarn
หรือpnpm
ได้เช่นกัน
ขั้นตอนที่ 2: การสร้างแอปพลิเคชัน Next.js ใหม่
เปิด Terminal ของคุณและรันคำสั่งต่อไปนี้เพื่อเริ่มต้นโปรเจกต์ Next.js ใหม่Bash
npx create-next-app@latest my-pro-shadcn-app --typescript --tailwind --eslint
คำสั่งนี้จะสร้างแอปพลิเคชันใหม่ในไดเร็กทอรีชื่อ my-pro-shadcn-app
เราได้รวม flags ที่สำคัญบางอย่างไว้:
--typescript
: Shadcn UI เขียนด้วย TypeScript และทำงานได้ดีที่สุดในสภาพแวดล้อม TypeScript--tailwind
: Tailwind CSS เป็น dependency ที่จำเป็นสำหรับการจัดสไตล์ของ Shadcn UI--eslint
: เป็นแนวทางปฏิบัติที่ดีเสมอสำหรับการรักษาคุณภาพโค้ด
ตัวติดตั้งจะถามคำถามสองสามข้อ นี่คือตัวเลือกที่แนะนำสำหรับการตั้งค่า Next.js 14+ ที่ทันสมัย:
✔ 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
การใช้ App Router เป็นแนวทางปฏิบัติมาตรฐาน และไดเร็กทอรี src/
ช่วยในการจัดระเบียบโค้ด เมื่อเสร็จแล้ว ให้เข้าไปในโปรเจกต์ใหม่ของคุณ:Bash
cd my-pro-shadcn-app
ขั้นตอนที่ 3: คำสั่ง init
- ทำให้ Shadcn UI มีชีวิตชีวา
นี่คือขั้นตอนที่สำคัญที่สุด Shadcn UI มีเครื่องมือ CLI สำหรับกำหนดค่าโปรเจกต์ของคุณ รันคำสั่งต่อไปนี้จากไดเร็กทอรี root ของโปรเจกต์ของคุณ:Bash
npx shadcn-ui@latest init
สิ่งนี้จะเรียกใช้แบบสอบถามแบบโต้ตอบเพื่อตั้งค่าโปรเจกต์ของคุณ มาทำความเข้าใจแต่ละคำถามและความสำคัญของมัน:
- Would you like to use TypeScript (recommended)?
Yes
เราอยู่ในโปรเจกต์ TypeScript - Which style would you like to use?
Default
vs.New York
นี่คือสองสไตล์ภาพที่กำหนดไว้ล่วงหน้าDefault
จะมีพื้นที่มากกว่าเล็กน้อย ในขณะที่New York
จะกระชับกว่า คุณสามารถดูตัวอย่างได้บนเว็บไซต์ Shadcn UI มาเลือกDefault
- Which color would you like to use as a base color? นี่เป็นการตั้งค่าชุดสีหลักสำหรับ UI ของคุณ ค่าเริ่มต้นคือ
Slate
มายึดตามSlate
ไว้ก่อน เราจะเรียนรู้วิธีเปลี่ยนในภายหลัง - Where is your
global.css
file? CLI ตรวจพบได้อย่างถูกต้องที่src/app/globals.css
ไฟล์นี้คือที่ที่ตัวแปร CSS หลักสำหรับการปรับแต่งธีมจะถูกแทรก - Do you want to use CSS variables for theming?
Yes
นี่คือหัวใจหลักของระบบการปรับแต่งธีมของ Shadcn ซึ่งช่วยให้สามารถเปลี่ยนแปลงแบบไดนามิกได้ (เช่น โหมดมืด/สว่าง) และปรับแต่งได้ง่าย - Where is your
tailwind.config.ts
located? CLI ตรวจพบsrc/tailwind.config.ts
ไฟล์นี้จะถูกแก้ไขเพื่อรวมการตั้งค่าธีมของ Shadcn - Configure import alias for components:
@/components
นี่คือแนวทางปฏิบัติที่ดี หมายความว่าไม่ว่าไฟล์จะซ้อนกันลึกแค่ไหน คุณก็สามารถ import คอมโพเนนต์ด้วย path ที่สะอาดได้เสมอ เช่นimport { Button } from "@/components/ui/button";
- Configure import alias for utils:
@/lib/utils
เช่นเดียวกับข้างต้น สำหรับฟังก์ชันยูทิลิตี้ - Are you using React Server Components?
Yes
เราเลือก App Router ซึ่งใช้ Server Components เป็นค่าเริ่มต้น - Write configuration to
components.json
?Yes
สิ่งนี้จะสร้างไฟล์ที่สำคัญซึ่งจดจำตัวเลือกทั้งหมดของคุณ คุณจึงไม่ต้องตอบคำถามเหล่านี้ทุกครั้งที่รันnpx shadcn-ui@latest add ...
หลังจากที่คุณยืนยัน CLI จะทำงานอย่างมหัศจรรย์:
- ติดตั้ง Dependencies: เพิ่มแพ็คเกจที่จำเป็น เช่น
tailwindcss-animate
และclass-variance-authority
- สร้าง
components.json
: จัดเก็บตัวเลือกการกำหนดค่าของคุณ - อัปเดต
tailwind.config.ts
: แทรก Shadcn UI plugin และการกำหนดค่าธีม - อัปเดต
globals.css
: เพิ่มบล็อกใหญ่ของตัวแปร CSS ที่กำหนดชุดสีทั้งหมดของคุณ, border radii, และอื่นๆ - สร้าง
lib/utils.ts
: ไฟล์นี้ export ฟังก์ชันตัวช่วยcn
ซึ่งเป็นยูทิลิตี้ที่ชาญฉลาดสำหรับการรวมคลาส Tailwind CSS แบบมีเงื่อนไข
โปรเจกต์ของคุณได้รับการกำหนดค่าอย่างสมบูรณ์แล้ว
(ทางเลือก: การตั้งค่า Vite)
หากคุณใช้ Vite กับ React กระบวนการจะคล้ายกันมาก หลังจากตั้งค่าโปรเจกต์ Vite + React + TS แล้ว คุณจะต้องติดตั้ง Tailwind CSS ด้วยตนเอง จากนั้นรัน npx shadcn-ui@latest init CLI ฉลาดพอที่จะตรวจจับการตั้งค่า Vite และจะถามคำถามที่แตกต่างกันเล็กน้อยเกี่ยวกับตำแหน่งไฟล์ (เช่น index.css แทน globals.css)
การสร้าง UI - จากคอมโพเนนต์ง่ายๆ ไปจนถึงเลย์เอาต์ที่ซับซ้อน
เมื่อตั้งค่าเสร็จแล้ว มาเริ่มสร้างกันเลย เวิร์กโฟลว์หลักคือ: ระบุความต้องการ, เพิ่มคอมโพเนนต์, ใช้มัน
ขั้นตอนที่ 4: การเพิ่มและใช้คอมโพเนนต์แรกของคุณ
มาทำความสะอาด boilerplate เริ่มต้นของ Next.js และสร้างอินเทอร์เฟซง่ายๆ
1. เพิ่มปุ่ม:Bash
npx shadcn-ui@latest add button
สังเกตสิ่งที่เกิดขึ้น: ไฟล์ใหม่ src/components/ui/button.tsx
ถูกสร้างขึ้น นี่คือปุ่มของคุณ คุณเป็นเจ้าของมัน
2. เพิ่ม Card:Bashnpx shadcn-ui@latest add card
คำสั่งนี้น่าสนใจกว่า สร้าง src/components/ui/card.tsx
หากคุณตรวจสอบไฟล์นี้ คุณจะเห็นว่ามัน export คอมโพเนนต์หลายรายการ: Card
, CardHeader
, CardTitle
, CardDescription
, CardContent
, และ CardFooter
นี่เป็นรูปแบบทั่วไปสำหรับ compound components
3. สร้าง UI:
ตอนนี้ เปิด src/app/page.tsx
และแทนที่เนื้อหาด้วยโค้ดต่อไปนี้:TypeScript
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input"; // เราจะเพิ่มอันนี้ต่อไป
import { Label } from "@/components/ui/label"; // และอันนี้
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>
{/* เราจะแทนที่ด้วยคอมโพเนนต์ Select ในภายหลัง */}
<Input id="framework" placeholder="e.g. Next.js" />
</div>
</CardContent>
<CardFooter>
<Button className="w-full">Deploy</Button>
</CardFooter>
</Card>
</main>
);
}
โค้ดของเรายังไม่สามารถรันได้เนื่องจากเราขาดคอมโพเนนต์ Input
และ Label
มาเพิ่มกัน:Bash
npx shadcn-ui@latest add input
npx shadcn-ui@latest add label
ตอนนี้ รัน development server ของคุณ:Bash
npm run dev
ไปที่ http://localhost:3000
คุณจะเห็นฟอร์มที่ดูสะอาดตาและเป็นมืออาชีพภายใน card สังเกตว่าเราใช้ utility classes เช่น w-full
, max-w-md
, และ grid
โดยตรงใน JSX ของเราเพื่อควบคุมเลย์เอาต์ นี่คือพลังของการรวม Shadcn และ Tailwind CSS
ขั้นตอนที่ 5: การแนะนำคอมโพเนนต์ที่ซับซ้อนมากขึ้น
Input แบบ static ก็ดี แต่แอปพลิเคชันจริงต้องการองค์ประกอบแบบโต้ตอบ มาปรับปรุงฟอร์มของเรากัน
1. เพิ่มคอมโพเนนต์ Select
: ช่อง input "Framework" ควรเป็น dropdown มาเพิ่มคอมโพเนนต์ Select
อันนี้ซับซ้อนกว่าและมี dependencies กับคอมโพเนนต์อื่น:Bash
npx shadcn-ui@latest add select
CLI ฉลาด มันจะเห็นว่า Select
ต้องการคอมโพเนนต์ Popover
เพื่อทำงาน และจะขออนุญาตคุณในการติดตั้งมันและ dependencies ของมันด้วย นี่เป็นคุณสมบัติที่ยอดเยี่ยมที่ช่วยให้คุณไม่ต้องติดตาม dependencies ด้วยตนเอง
2. รวมคอมโพเนนต์ Select
: แทนที่ Input
สำหรับ "Framework" ใน src/app/page.tsx
ด้วยคอมโพเนนต์ Select
ใหม่:TypeScript
// เพิ่ม imports เหล่านี้ที่ด้านบน
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
// ... ภายใน 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>
รีเฟรชเบราว์เซอร์ของคุณ ตอนนี้คุณมี dropdown select ที่ใช้งานได้เต็มรูปแบบและเข้าถึงได้ พร้อมแอนิเมชันและการนำทางด้วยคีย์บอร์ดที่ถูกต้อง ทั้งหมดนี้ต้องขอบคุณ Radix UI ที่ทำงานอยู่เบื้องหลัง
3. การเพิ่ม User Feedback ด้วย Toast
: จะเกิดอะไรขึ้นเมื่อผู้ใช้คลิก "Deploy"? เราควรให้ feedback แก่พวกเขา คอมโพเนนต์ Toast
เหมาะสำหรับสิ่งนี้
ขั้นแรก เพิ่มมัน:Bash
npx shadcn-ui@latest add toast
ถัดไป ในการใช้ toasts คุณต้องเพิ่มคอมโพเนนต์ <Toaster />
ไปยัง root layout ของคุณเพื่อให้สามารถแสดงผลได้ทุกที่ในแอป เปิด src/app/layout.tsx
และแก้ไขมัน:TypeScript
import { Toaster } from "@/components/ui/toaster" // Import the Toaster
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Toaster /> {/* เพิ่มที่นี่ ก่อนปิด body */}
</body>
</html>
)
}
ตอนนี้ เราต้องการวิธี เรียก toast เราจะใช้ hook useToast
มาอัปเดต src/app/page.tsx
เพื่อให้เป็น client component และจัดการการคลิกปุ่ม:TypeScript
'use client'; // <-- เพิ่มที่ด้านบนสุดของไฟล์
// ... imports อื่นๆ
import { useToast } from "@/components/ui/use-toast";
export default function Home() {
const { toast } = useToast(); // รับฟังก์ชัน toast จาก 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 และ CardContent ... */}
<CardFooter>
<Button className="w-full" onClick={handleDeploy}> {/* เพิ่ม onClick handler */}
Deploy
</Button>
</CardFooter>
</Card>
</main>
);
}
ตอนนี้ เมื่อคุณคลิกปุ่ม "Deploy" การแจ้งเตือนที่ดูดีจะปรากฏขึ้นที่มุมหน้าจอของคุณ
การสร้างฟอร์มระดับมืออาชีพพร้อมการตรวจสอบข้อมูล (Validation)
แอปพลิเคชันจริงส่วนใหญ่ต้องการการจัดการฟอร์มที่แข็งแกร่ง รวมถึงการตรวจสอบข้อมูลฝั่ง client วิธีการอย่างเป็นทางการในการจัดการสิ่งนี้ด้วย Shadcn UI คือการรวมมันเข้ากับ react-hook-form
สำหรับการจัดการสถานะ และ zod
สำหรับการตรวจสอบ schema มาสร้างกัน
ขั้นตอนที่ 6: การติดตั้ง Dependencies สำหรับฟอร์ม
ขั้นแรก มาติดตั้งไลบรารีที่จำเป็น:Bash
npm install react-hook-form zod @hookform/resolvers
react-hook-form
: ไลบรารีฟอร์มที่มีประสิทธิภาพ ยืดหยุ่น และขยายได้zod
: ไลบรารีสำหรับการประกาศและตรวจสอบ schema แบบ TypeScript-first@hookform/resolvers
: ไลบรารีเชื่อมต่อเพื่อให้react-hook-form
สามารถใช้zod
สำหรับการตรวจสอบข้อมูล
ขั้นตอนที่ 7: การเพิ่มคอมโพเนนต์ Form
ของ Shadcn
Shadcn UI มีคอมโพเนนต์ Form
พิเศษที่ทำหน้าที่เป็น wrapper เพื่อเชื่อมต่อ react-hook-form
กับคอมโพเนนต์ UI ของคุณได้อย่างราบรื่น:Bash
npx shadcn-ui@latest add form
สิ่งนี้จะเพิ่ม src/components/ui/form.tsx
ไฟล์นี้มีชุดของคอมโพเนนต์ที่รับรู้ context (Form
, FormField
, FormItem
, FormLabel
, FormControl
, FormDescription
, FormMessage
) ซึ่งช่วยลด boilerplate ได้อย่างมาก
ขั้นตอนที่ 8: การสร้าง Validation Schema
ในไฟล์ src/app/page.tsx
ของคุณ มากำหนดรูปแบบและกฎของข้อมูลฟอร์มของเราโดยใช้ zod
:TypeScript
// เพิ่ม imports เหล่านี้ที่ด้านบน
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";
ตอนนี้ มาสร้าง schema เหนือคอมโพเนนต์ Home
ของเราเล็กน้อย:TypeScript
const formSchema = z.object({
projectName: z.string().min(2, {
message: "Project name must be at least 2 characters.",
}).max(50, {
message: "Project name must not exceed 50 characters.",
}),
framework: z.string({
required_error: "Please select a framework to display.",
}),
});
schema นี้กำหนดสองฟิลด์: projectName
ต้องเป็น string ที่มีความยาวระหว่าง 2 ถึง 50 ตัวอักษร และ framework
เป็น string ที่ต้องระบุ
ขั้นตอนที่ 9: การเชื่อมต่อฟอร์ม
ตอนนี้ มาปรับโครงสร้างคอมโพเนนต์ Home
ของเราเพื่อใช้เครื่องมือใหม่ทั้งหมดเหล่านี้:TypeScript
export default function Home() {
const { toast } = useToast();
// 1. กำหนดฟอร์มของคุณ
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
projectName: "",
},
});
// 2. กำหนด submit handler
function onSubmit(values: z.infer<typeof formSchema>) {
// ทำอะไรบางอย่างกับค่าฟอร์ม
// ✅ สิ่งนี้จะ type-safe และถูกตรวจสอบแล้ว
console.log(values);
toast({
title: "You submitted the following values:",
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. สร้าง JSX ด้วยคอมโพเนนต์ Form ของ 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 /> {/* แสดงข้อผิดพลาดในการตรวจสอบข้อมูล */}
</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>
);
}
นี่เป็นโค้ดส่วนใหญ่ แต่เป็นรูปแบบที่ทรงพลังและปรับขนาดได้สูง คอมโพเนนต์ FormField
จัดการการเชื่อมต่อสถานะทั้งหมด และ FormMessage
จะแสดงข้อผิดพลาดในการตรวจสอบข้อมูลที่ถูกต้องจาก schema zod
ของคุณโดยอัตโนมัติเมื่อผู้ใช้โต้ตอบกับฟิลด์ ลองส่งฟอร์มโดยเว้นชื่อโปรเจกต์ว่างไว้เพื่อดูการตรวจสอบข้อมูลทำงาน
การเชี่ยวชาญการปรับแต่งธีมและการปรับแต่ง
พลังที่แท้จริงของ Shadcn UI จะถูกปลดปล่อยเมื่อคุณเริ่มปรับให้เป็นของคุณเอง
ขั้นตอนที่ 10: การปรับแต่งธีมขั้นสูงด้วยตัวแปร CSS
ธีมทั้งหมดของคุณถูกกำหนดโดยตัวแปร CSS ในไฟล์ src/app/globals.css
เปิดไฟล์นี้และมองหาบล็อก :root
และ .dark
:CSS
/* ตัวอย่างจาก 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%;
/* ... และอื่นๆ อีกมากมาย */
--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%;
/* ... */
}
- การเปลี่ยนสี: ค่าต่างๆ ถูกแสดงในรูปแบบ HSL (Hue, Saturation, Lightness) โดยไม่มี wrapper
hsl()
นี่คือการเลือกที่ตั้งใจเพื่อให้จัดการได้ง่ายขึ้น หากต้องการเปลี่ยนสีแบรนด์หลักของคุณ คุณเพียงแค่ต้องค้นหาค่า HSL สำหรับสีของคุณและอัปเดตตัวแปร--primary
และ--primary-foreground
หน้า Shadcn UI Themes มีตัวสร้างที่ยอดเยี่ยมที่ให้คุณเลือกสีและคัดลอก-วางบล็อกธีมทั้งหมดได้ - การเปลี่ยนรัศมีขอบ: ต้องการมุมที่คมขึ้นหรือไม่? เปลี่ยน
--radius: 0.5rem;
เป็น--radius: 0.2rem;
หรือแม้แต่0rem
ทุกคอมโพเนนต์ที่มีมุมโค้งมนจะใช้ตัวแปรนี้ ดังนั้นการเปลี่ยนแปลงของคุณจะมีผลทั่วโลก
การใช้งาน Dark Mode:
Shadcn ได้รับการกำหนดค่าล่วงหน้าสำหรับ dark mode ต้องขอบคุณบล็อกคลาส .dark และกลยุทธ์ darkMode: "class" ของ Tailwind ใน tailwind.config.ts สิ่งที่คุณต้องมีคือวิธีสลับคลาส dark บนองค์ประกอบ <html> ไลบรารียอดนิยมสำหรับสิ่งนี้คือ next-themes
- ติดตั้ง:
npm install next-themes
- สร้างคอมโพเนนต์
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>
}
- ครอบ
RootLayout
ของคุณด้วย provider นี้ (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>
)
}
- สุดท้าย สร้างปุ่มสลับ (เช่น
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>
)
}
ตอนนี้คุณสามารถวาง <ModeToggle />
นี้ได้ทุกที่ในแอปของคุณเพื่อรับปุ่มสลับ dark mode ที่รับรู้ระบบและผู้ใช้สามารถ override ได้
ขั้นตอนที่ 11: การปรับแต่งโค้ดต้นฉบับของคอมโพเนนต์
นี่คือสุดยอดพลังพิเศษ สมมติว่าคุณต้องการ variant ใหม่สำหรับปุ่มของคุณที่พื้นหลังเป็นสีเขียว
เปิด src/components/ui/button.tsx ค้นหาการกำหนด buttonVariants ใช้ cva (Class Variance Authority) เพียงแค่เพิ่ม variant ใหม่:TypeScript
const buttonVariants = cva(
// ... base styles
{
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", // variant ใหม่ของเรา
},
// ... size variants
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
แค่นั้นเอง ตอนนี้คุณสามารถใช้มันในโค้ดของคุณได้: <Button variant="success">Success</Button>
คุณไม่จำเป็นต้องเขียน CSS overrides ที่ซับซ้อน คุณเพียงแค่แก้ไขโค้ดต้นฉบับของคอมโพเนนต์เอง เวิร์กโฟลว์นี้เรียบง่าย คาดเดาได้ และทรงพลังอย่างเหลือเชื่อ
ส่วนที่ 6: แนวทางปฏิบัติที่ดีที่สุดและเส้นทางข้างหน้า
เมื่อแอปพลิเคชันของคุณเติบโตขึ้น นี่คือแนวทางปฏิบัติที่ดีที่สุดบางประการที่ควรจำไว้
- การจัดระเบียบไฟล์: แม้ว่า CLI จะวางทุกอย่างไว้ใน
components/ui
แต่โฟลเดอร์นี้ควรถูกพิจารณาว่าเป็นชุด UI "พื้นฐาน" ของคุณ สำหรับคอมโพเนนต์ที่ซับซ้อนมากขึ้นที่คุณสร้างขึ้นเอง (เช่นUserProfileCard
ที่ใช้Card
,Avatar
, และButton
ของ Shadcn) ให้สร้างไว้ในไดเร็กทอรีอื่น เช่นcomponents/shared
หรือcomponents/features
สิ่งนี้ช่วยให้แยกความแตกต่างระหว่าง UI พื้นฐานและคอมโพเนนต์เฉพาะแอปพลิเคชันได้อย่างชัดเจน - การอัปเดตคอมโพเนนต์: คุณจะได้รับการอัปเดตได้อย่างไรหากคอมโพเนนต์ Shadcn UI ต้นฉบับได้รับการปรับปรุง? CLI มีคำตอบให้ คุณสามารถรัน
npx shadcn-ui@latest add button
อีกครั้ง CLI จะตรวจพบว่าคุณมีไฟล์button.tsx
อยู่แล้วและแสดงการเปรียบเทียบdiff
ทำให้คุณสามารถเลือกที่จะเขียนทับไฟล์ของคุณหรือยอมรับการเปลี่ยนแปลงด้วยตนเอง มันเหมือนกับ mini version control สำหรับคอมโพเนนต์ของคุณ - ใช้ประโยชน์จากการเข้าถึง (Accessibility): จำไว้ว่าคอมโพเนนต์ Shadcn สามารถเข้าถึงได้ทันทีเนื่องจากสร้างขึ้นบน Radix primitives เมื่อคุณปรับแต่งมัน โปรดระวังอย่าทำให้การเข้าถึงนี้เสียไป ตัวอย่างเช่น หากคุณเปลี่ยนสีของปุ่ม ตรวจสอบให้แน่ใจว่าข้อความยังคงมีความคมชัดเพียงพอ เมื่อคุณสร้างคอมโพเนนต์ใหม่ พยายามทำตามรูปแบบที่ Shadcn/Radix กำหนดไว้เพื่อรักษาการนำทางด้วยคีย์บอร์ดและการรองรับ screen reader
สรุป: คุณคือผู้เขียนไลบรารี
ตอนนี้คุณได้เดินทางจากปรัชญาหลักของ Shadcn UI ไปสู่การนำรูปแบบขั้นสูงในโลกแห่งความเป็นจริงไปใช้ คุณได้เห็นแล้วว่านวัตกรรมที่แท้จริงของมันไม่ใช่แค่คอมโพเนนต์เท่านั้น แต่เป็นการเปลี่ยนแปลงกระบวนทัศน์ที่มันนำเสนอ มันเปลี่ยนนักพัฒนาจากการเป็นเพียง ผู้บริโภค ไลบรารีไปสู่การเป็น ผู้ดูแล และ เจ้าของ UI toolkit ของตนเอง
ด้วยการมอบโค้ดต้นฉบับให้คุณ การสร้างบนรากฐานที่แข็งแกร่งของ Tailwind CSS และ Radix UI และการมอบประสบการณ์ CLI ที่ราบรื่น Shadcn UI จึงสร้างสมดุลที่สมบูรณ์แบบระหว่างความเร็วในการพัฒนาเริ่มต้นและความสามารถในการบำรุงรักษาในระยะยาวและอิสระในการสร้างสรรค์ คุณไม่ถูกจำกัดด้วยระบบการออกแบบของคนอื่นอีกต่อไป คอมโพเนนต์ในโปรเจกต์ของคุณคือของคุณเอง—ที่จะแก้ไข ขยาย และทำให้สมบูรณ์แบบ
อนาคตของ UI แอปพลิเคชันของคุณไม่ได้อยู่ในมือของ dependency บุคคลที่สามอีกต่อไป มันอยู่ที่นั่นในโฟลเดอร์ components
ของคุณ ขอให้มีความสุขกับการสร้างสรรค์
ต้องการแพลตฟอร์มแบบ All-in-One ที่ผสานรวมสำหรับทีมพัฒนาของคุณเพื่อทำงานร่วมกันด้วย ประสิทธิภาพสูงสุด ใช่ไหม?
Apidog ตอบสนองทุกความต้องการของคุณ และ มาแทนที่ Postman ในราคาที่เข้าถึงได้ง่ายกว่ามาก!