Overview
The UI component library consists of accessible, customizable primitives built on Radix UI and styled with Tailwind CSS. All components support the asChild pattern for polymorphic rendering and include full TypeScript support.
A versatile button component with multiple variants and sizes.
Props
Button style variant: default | destructive | outline | secondary | ghost | link
Button size: default | sm | lg | icon
Render as a child component (useful for links)
Usage Examples
Basic Button
Button Variants
Button as Link
Icon Button
import { Button } from "@/components/ui/button" ;
export function Example () {
return < Button > Click me </ Button > ;
}
Implementation
src/components/ui/button.tsx
const buttonVariants = cva (
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]" ,
{
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90" ,
destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90" ,
outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground" ,
secondary: "bg-secondary text-secondary-foreground shadow-xs 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 has-[>svg]:px-3" ,
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5" ,
lg: "h-10 rounded-md px-6 has-[>svg]:px-4" ,
icon: "size-9"
}
},
defaultVariants: {
variant: "default" ,
size: "default"
}
}
);
Card
A flexible card component with compound components for header, content, and footer.
Components
Card: Root container
CardHeader: Header section with title and description
CardTitle: Card title
CardDescription: Card description
CardAction: Action area in header (positioned in top-right)
CardContent: Main content area
CardFooter: Footer section
Usage Examples
Basic Card
Card with Action
Project Card (Real Example)
import {
Card ,
CardHeader ,
CardTitle ,
CardDescription ,
CardContent ,
CardFooter
} from "@/components/ui/card" ;
import { Button } from "@/components/ui/button" ;
export function Example () {
return (
< Card >
< CardHeader >
< CardTitle > Project Title </ CardTitle >
< CardDescription > A brief description of the project </ CardDescription >
</ CardHeader >
< CardContent >
< p > Main content goes here... </ p >
</ CardContent >
< CardFooter >
< Button > View Details </ Button >
</ CardFooter >
</ Card >
);
}
Badge
Compact labels for tags, status indicators, and metadata.
Props
Badge style: default | secondary | destructive | outline
Render as a child component
Usage Examples
Basic Badges
Technology Tags
import { Badge } from "@/components/ui/badge" ;
export function Example () {
return (
< div className = "flex gap-2" >
< Badge > Default </ Badge >
< Badge variant = "secondary" > Secondary </ Badge >
< Badge variant = "destructive" > Error </ Badge >
< Badge variant = "outline" > Outline </ Badge >
</ div >
);
}
Dialog
Accessible modal dialog component with overlay.
Components
Dialog: Root component
DialogTrigger: Button to open dialog
DialogContent: Dialog content container
DialogHeader: Header section
DialogTitle: Dialog title
DialogDescription: Dialog description
DialogFooter: Footer section
DialogClose: Close button
Props
Show the close button in the top-right corner
Usage Examples
import {
Dialog ,
DialogTrigger ,
DialogContent ,
DialogHeader ,
DialogTitle ,
DialogDescription ,
DialogFooter
} from "@/components/ui/dialog" ;
import { Button } from "@/components/ui/button" ;
export function Example () {
return (
< Dialog >
< DialogTrigger asChild >
< Button > Open Dialog </ Button >
</ DialogTrigger >
< DialogContent >
< DialogHeader >
< DialogTitle > Are you sure? </ DialogTitle >
< DialogDescription >
This action cannot be undone. This will permanently delete your account.
</ DialogDescription >
</ DialogHeader >
< DialogFooter >
< Button variant = "outline" > Cancel </ Button >
< Button variant = "destructive" > Delete Account </ Button >
</ DialogFooter >
</ DialogContent >
</ Dialog >
);
}
Integrated form components with React Hook Form validation.
Components
Form: Root form provider (wraps React Hook Form’s FormProvider)
FormField: Field wrapper with Controller
FormItem: Field container
FormLabel: Field label
FormControl: Input control wrapper
FormDescription: Help text
FormMessage: Error message
Usage Examples
import { useForm } from "react-hook-form" ;
import { zodResolver } from "@hookform/resolvers/zod" ;
import * as z from "zod" ;
import {
Form ,
FormControl ,
FormDescription ,
FormField ,
FormItem ,
FormLabel ,
FormMessage
} from "@/components/ui/form" ;
import { Input } from "@/components/ui/input" ;
import { Button } from "@/components/ui/button" ;
const formSchema = z . object ({
email: z . string (). email ( "Invalid email address" ),
name: z . string (). min ( 2 , "Name must be at least 2 characters" )
});
export function ContactForm () {
const form = useForm < z . infer < typeof formSchema >>({
resolver: zodResolver ( formSchema ),
defaultValues: {
email: "" ,
name: ""
}
});
function onSubmit ( values : z . infer < typeof formSchema >) {
console . log ( values );
}
return (
< Form { ... form } >
< form onSubmit = { form . handleSubmit ( onSubmit ) } className = "space-y-4" >
< FormField
control = { form . control }
name = "name"
render = { ({ field }) => (
< FormItem >
< FormLabel > Name </ FormLabel >
< FormControl >
< Input placeholder = "John Doe" { ... field } />
</ FormControl >
< FormDescription >
Your full name as it appears on official documents.
</ FormDescription >
< FormMessage />
</ FormItem >
) }
/>
< FormField
control = { form . control }
name = "email"
render = { ({ field }) => (
< FormItem >
< FormLabel > Email </ FormLabel >
< FormControl >
< Input type = "email" placeholder = "[email protected] " { ... field } />
</ FormControl >
< FormMessage />
</ FormItem >
) }
/>
< Button type = "submit" > Submit </ Button >
</ form >
</ Form >
);
}
Text input field with consistent styling.
Usage Examples
import { Input } from "@/components/ui/input" ;
import { Label } from "@/components/ui/label" ;
export function Example () {
return (
< div className = "grid gap-2" >
< Label htmlFor = "email" > Email </ Label >
< Input id = "email" type = "email" placeholder = "[email protected] " />
</ div >
);
}
Label
Accessible form label component.
Usage
import { Label } from "@/components/ui/label" ;
import { Input } from "@/components/ui/input" ;
export function Example () {
return (
< div className = "grid gap-2" >
< Label htmlFor = "username" > Username </ Label >
< Input id = "username" placeholder = "@username" />
</ div >
);
}
Select
Dropdown select component with custom styling.
Components
Select: Root component
SelectTrigger: Button to open dropdown
SelectValue: Selected value display
SelectContent: Dropdown content
SelectItem: Individual option
SelectGroup: Group options
SelectLabel: Group label
SelectSeparator: Visual separator
Props
Trigger size: default | sm
Show chevron icon in trigger
Usage Examples
Basic Select
Grouped Select
import {
Select ,
SelectContent ,
SelectItem ,
SelectTrigger ,
SelectValue
} from "@/components/ui/select" ;
export function Example () {
return (
< Select >
< SelectTrigger >
< SelectValue placeholder = "Select a theme" />
</ SelectTrigger >
< SelectContent >
< SelectItem value = "light" > Light </ SelectItem >
< SelectItem value = "dark" > Dark </ SelectItem >
< SelectItem value = "system" > System </ SelectItem >
</ SelectContent >
</ Select >
);
}
Sheet
Slide-out panel component (mobile drawer/sidebar).
Components
Sheet: Root component
SheetTrigger: Button to open sheet
SheetContent: Sheet content container
SheetHeader: Header section
SheetTitle: Sheet title
SheetDescription: Sheet description
SheetFooter: Footer section
SheetClose: Close button
Props
Sheet position: top | right | bottom | left
Usage Examples
import {
Sheet ,
SheetContent ,
SheetDescription ,
SheetHeader ,
SheetTitle ,
SheetTrigger
} from "@/components/ui/sheet" ;
import { Button } from "@/components/ui/button" ;
export function Example () {
return (
< Sheet >
< SheetTrigger asChild >
< Button variant = "outline" > Open Menu </ Button >
</ SheetTrigger >
< SheetContent side = "right" >
< SheetHeader >
< SheetTitle > Menu </ SheetTitle >
< SheetDescription >
Navigate through the application
</ SheetDescription >
</ SheetHeader >
< div className = "py-4" >
{ /* Navigation items */ }
</ div >
</ SheetContent >
</ Sheet >
);
}
Textarea
Multi-line text input component.
Usage
import { Textarea } from "@/components/ui/textarea" ;
import { Label } from "@/components/ui/label" ;
export function Example () {
return (
< div className = "grid gap-2" >
< Label htmlFor = "message" > Message </ Label >
< Textarea id = "message" placeholder = "Type your message here..." />
</ div >
);
}
Context menu and dropdown component.
Components
DropdownMenu: Root component
DropdownMenuTrigger: Button to open menu
DropdownMenuContent: Menu content container
DropdownMenuItem: Individual menu item
DropdownMenuCheckboxItem: Checkbox item
DropdownMenuRadioGroup: Radio group
DropdownMenuRadioItem: Radio item
DropdownMenuLabel: Section label
DropdownMenuSeparator: Visual separator
DropdownMenuShortcut: Keyboard shortcut display
DropdownMenuSub: Submenu container
DropdownMenuSubTrigger: Submenu trigger
DropdownMenuSubContent: Submenu content
Usage Examples
Basic Dropdown
Advanced Dropdown
import {
DropdownMenu ,
DropdownMenuContent ,
DropdownMenuItem ,
DropdownMenuLabel ,
DropdownMenuSeparator ,
DropdownMenuTrigger
} from "@/components/ui/dropdown-menu" ;
import { Button } from "@/components/ui/button" ;
export function Example () {
return (
< DropdownMenu >
< DropdownMenuTrigger asChild >
< Button variant = "outline" > Open Menu </ Button >
</ DropdownMenuTrigger >
< DropdownMenuContent >
< DropdownMenuLabel > My Account </ DropdownMenuLabel >
< DropdownMenuSeparator />
< DropdownMenuItem > Profile </ DropdownMenuItem >
< DropdownMenuItem > Settings </ DropdownMenuItem >
< DropdownMenuItem > Logout </ DropdownMenuItem >
</ DropdownMenuContent >
</ DropdownMenu >
);
}
Styling and Theming
All components respect the global theme configuration defined in your Tailwind config:
@layer base {
:root {
--background : 0 0 % 100 % ;
--foreground : 222.2 84 % 4.9 % ;
--primary : 222.2 47.4 % 11.2 % ;
--primary-foreground : 210 40 % 98 % ;
/* ... more CSS variables */
}
}
Custom Styling
All components accept a className prop for custom styling:
< Button className = "bg-gradient-to-r from-purple-500 to-pink-500" >
Custom Gradient Button
</ Button >
Use the cn() utility when combining multiple class names to avoid style conflicts: import { cn } from "@/utils/cn" ;
< Button className = { cn ( "custom-class" , condition && "conditional-class" ) } >
Button
</ Button >
Accessibility Features
All components include built-in accessibility features:
Keyboard Navigation : Full keyboard support for all interactive components
ARIA Attributes : Proper ARIA labels, roles, and states
Focus Management : Visible focus indicators and focus trapping in modals
Screen Reader Support : Descriptive labels and announcements
All Radix UI primitives are tested against the WAI-ARIA authoring practices.
Next Steps
Animated Background Learn about the canvas-based animated grid component
GitHub Stats Explore the GitHub statistics integration