เมนู
ในหน้านี้

Component Design System

สร้าง reusable UI components ด้วย Tailwind CSS และ class-variance-authority

ผมใช้ shadcn/ui เป็นรากฐานสำหรับ component library ต่างจาก component libraries ทั่วไป shadcn/ui ให้ source code มา — หมายความว่าควบคุม styling และ behavior ได้เต็มที่ Components สร้างด้วย Radix UI primitives (สำหรับ accessibility), style ด้วย Tailwind CSS และใช้ class-variance-authority (CVA) สำหรับจัดการ variants รูปแบบนี้ช่วยให้สร้าง components ที่สม่ำเสมอพร้อม variants (size, color, state) ในขณะที่ API ยังง่ายและ type-safe

ผมใช้ shadcn/ui + Radix UI + CVA สำหรับ accessible และ customizable components คุณสามารถได้ผลลัพธ์คล้ายกันด้วย Material UI, Chakra UI, Ant Design หรือสร้างเองด้วย Headless UI รูปแบบ variant ที่แสดง (ใช้ CVA) สามารถ implement ด้วย Tailwind classes ปกติ, CSS Modules หรือ styled-components ก็ได้

วิธีการทำงาน

components/
├── ui/
│   ├── button.tsx      # Button component with variants
│   ├── input.tsx       # Input component
│   ├── card.tsx        # Card components (Card, CardHeader, etc.)
│   ├── dialog.tsx      # Dialog/Modal component
│   └── separator.tsx   # Separator component
└── common/
    ├── Container.tsx   # Layout container
    ├── Logo.tsx        # Logo component
    └── ThemeToggle.tsx # Theme switcher

lib/
└── cn.ts               # Utility for merging class names

styles/
└── globals.css         # Global styles & CSS variables

Design Tokens

CSS variables for consistent colors and theming.

Composable

Build complex UIs from small reusable components.

CVA Variants

Type-safe component variants with class-variance-authority.

Radix Primitives

Accessible, unstyled components from Radix UI.

คุณสมบัติหลัก

  • Variant-based component API
  • Composable และ reusable patterns
  • Accessible components (Radix UI)
  • Type-safe props ด้วย TypeScript
  • Consistent design tokens

ตัวอย่างการใช้งาน

ปุ่ม

<Button>Default</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Destructive</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>

Input Fields

<Input placeholder="Default input" />
<Input placeholder="Disabled input" disabled />
<div className="flex gap-2">
  <Input placeholder="Search..." className="flex-1" />
  <Button>Search</Button>
</div>

การ์ด

Simple Card

A basic card component with header and content.

Highlighted Card

A card with primary border highlight.

<Card>
  <CardHeader>
    <CardTitle>Simple Card</CardTitle>
  </CardHeader>
  <CardContent>
    <p>A basic card component with header and content.</p>
  </CardContent>
</Card>

<Card className="border-primary">
  <CardHeader>
    <CardTitle className="text-primary">Highlighted Card</CardTitle>
  </CardHeader>
  <CardContent>
    <p>A card with primary border highlight.</p>
  </CardContent>
</Card>