- Accordion
- Alert
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendarnew
- Card
- Carousel
- Checkbox
- Chip
- Collapse
- Dialog
- Drawer
- Footer
- Gallery
- Icon Button
- Image
- Input
- List
- Mapnew
- Menu
- Navbar
- Pagination
- Popover
- Progress
- Radio
- Rating
- Select
- Sidebar
- Skeletonnew
- Slider
- Software Purchase Card
- Sonner / Toastnew
- Speed Dial
- Spinner
- Stepper
- Switch
- Table
- Tabs
- Textarea
- Timeline
- Tooltip
- Typography
- Video
import { X } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
export function DrawerDemo() {
return (
<Drawer direction="right">
<DrawerTrigger asChild>
<Button>Open Drawer</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Creative Tim UI</DrawerTitle>
<DrawerDescription className="mt-2">
A collection of open-source UI Components, Blocks & AI Agents by
Creative Tim on top of shadcn/ui. Integrate them in v0, Lovable,
Claude, or your application.
</DrawerDescription>
</DrawerHeader>
<DrawerClose asChild>
<Button
variant="ghost"
size="icon"
className="absolute top-4 right-4 h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
</Button>
</DrawerClose>
<DrawerFooter className="px-4">
<Button>Get Started</Button>
<Button variant="secondary">Documentation</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
)
}
Installation
pnpm dlx @creative-tim/ui@latest add drawer
Usage
import DrawerDemo from "@/components/drawer-demo"<DrawerDemo />Examples
Drawer Placement
A drawer component with placement options for all four sides (top, right, bottom, left), allowing you to choose the most appropriate direction for your use case.
import { X } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
export function DrawerPlacement() {
return (
<div className="flex gap-4">
<Drawer direction="top">
<DrawerTrigger asChild>
<Button className="w-auto">Open Drawer Top</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader className="px-4 text-left">
<DrawerTitle className="text-left">Creative Tim UI</DrawerTitle>
<DrawerDescription className="mt-2 text-left">
A collection of open-source UI Components, Blocks & AI Agents by
Creative Tim on top of shadcn/ui. Integrate them in v0, Lovable,
Claude, or your application.
</DrawerDescription>
</DrawerHeader>
<DrawerClose asChild>
<Button
variant="ghost"
size="icon"
className="absolute top-4 right-4 h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
</Button>
</DrawerClose>
<DrawerFooter className="flex-row gap-2 px-4">
<Button className="w-auto">Get Started</Button>
<Button variant="secondary" className="w-auto">
Documentation
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
<Drawer direction="right">
<DrawerTrigger asChild>
<Button>Open Drawer Right</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Creative Tim UI</DrawerTitle>
</DrawerHeader>
<DrawerClose asChild>
<Button
variant="ghost"
size="icon"
className="absolute top-4 right-4 h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
</Button>
</DrawerClose>
<DrawerDescription className="mt-2 mb-6 px-4">
A collection of open-source UI Components, Blocks & AI Agents by
Creative Tim on top of shadcn/ui. Integrate them in v0, Lovable,
Claude, or your application.
</DrawerDescription>
<DrawerFooter className="px-4">
<Button>Get Started</Button>
<Button variant="secondary">Documentation</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
<Drawer direction="bottom">
<DrawerTrigger asChild>
<Button className="w-auto">Open Drawer Bottom</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader className="px-4 text-left">
<DrawerTitle className="text-left">Creative Tim UI</DrawerTitle>
<DrawerDescription className="mt-2 text-left">
A collection of open-source UI Components, Blocks & AI Agents by
Creative Tim on top of shadcn/ui. Integrate them in v0, Lovable,
Claude, or your application.
</DrawerDescription>
</DrawerHeader>
<DrawerClose asChild>
<Button
variant="ghost"
size="icon"
className="absolute top-4 right-4 h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
</Button>
</DrawerClose>
<DrawerFooter className="flex-row gap-2 px-4">
<Button className="w-auto">Get Started</Button>
<Button variant="secondary" className="w-auto">
Documentation
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
<Drawer direction="left">
<DrawerTrigger asChild>
<Button>Open Drawer Left</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Creative Tim UI</DrawerTitle>
</DrawerHeader>
<DrawerClose asChild>
<Button
variant="ghost"
size="icon"
className="absolute top-4 right-4 h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
</Button>
</DrawerClose>
<DrawerDescription className="mt-2 mb-6 px-4">
A collection of open-source UI Components, Blocks & AI Agents by
Creative Tim on top of shadcn/ui. Integrate them in v0, Lovable,
Claude, or your application.
</DrawerDescription>
<DrawerFooter className="px-4">
<Button>Get Started</Button>
<Button variant="secondary">Documentation</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
</div>
)
}
Drawer with Form
A drawer that contains a contact form with email, subject, and message fields, perfect for quick user interactions without navigating away from the current page.
import { X } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
import { Input } from "@/components/ui/input"
import { Textarea } from "@/components/ui/textarea"
export function DrawerWithForm() {
return (
<Drawer direction="right">
<DrawerTrigger asChild>
<Button>Open Drawer</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Contact Us</DrawerTitle>
</DrawerHeader>
<DrawerClose asChild>
<Button
variant="ghost"
size="icon"
className="absolute top-4 right-4 h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
</Button>
</DrawerClose>
<DrawerDescription className="mt-4 mb-6 px-4">
Write the message and then click button.
</DrawerDescription>
<div className="mt-6 space-y-4 px-4">
<Input id="email" type="email" placeholder="Email" />
<Input placeholder="Subject" />
<Textarea placeholder="Message" />
<Button className="w-full">Send message</Button>
</div>
</DrawerContent>
</Drawer>
)
}
Drawer with Navigation
A comprehensive navigation drawer featuring a search bar, menu items with badges, collapsible sections, and a promotional card, ideal for mobile navigation or sidebar menus.
"use client"
import * as React from "react"
import {
Archive,
ChevronRight,
FileText,
Folder,
LayoutDashboard,
LogOut,
Mail,
MoreHorizontal,
Pin,
Search,
Send,
Trash2,
UserX,
X,
} from "lucide-react"
import { cn } from "@/lib/utils"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
import { Collapse, CollapseContent } from "@/components/ui/collapse"
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
import { Input } from "@/components/ui/input"
import {
List,
ListItem,
ListItemEnd,
ListItemStart,
} from "@/components/ui/list"
import { Separator } from "@/components/ui/separator"
const Links = [
{
icon: Mail,
title: "Inbox",
href: "#",
badge: 14,
},
{
icon: Send,
title: "Sent",
href: "#",
},
{
icon: FileText,
title: "Drafts",
href: "#",
},
{
icon: Pin,
title: "Pins",
href: "#",
},
{
icon: Archive,
title: "Archive",
href: "#",
},
{
icon: Trash2,
title: "Trash",
href: "#",
},
]
export function DrawerWithNavigation() {
const [isOpen, setIsOpen] = React.useState(false)
return (
<Drawer direction="left">
<DrawerTrigger asChild>
<Button>Open Drawer</Button>
</DrawerTrigger>
<DrawerContent className="p-0">
<DrawerClose asChild>
<Button
variant="ghost"
size="icon"
className="absolute top-2 right-2 z-10 h-8 w-8 rounded-full"
>
<X className="h-5 w-5" />
</Button>
</DrawerClose>
<Card className="border-none shadow-none">
<CardHeader className="m-0 flex h-max items-center gap-2 px-3 pt-4 pb-3">
<Avatar className="h-6 w-6">
<AvatarImage
src="https://www.creative-tim.com/ui/apple-touch-icon-square.jpg"
alt="brand"
/>
<AvatarFallback>CT</AvatarFallback>
</Avatar>
<DrawerTitle>Creative Tim UI</DrawerTitle>
</CardHeader>
<CardContent className="p-3">
<div className="relative">
<Search className="text-muted-foreground absolute top-1/2 left-3 h-4 w-4 -translate-y-1/2" />
<Input
type="search"
placeholder="Search here..."
className="pl-9"
/>
</div>
<List className="mt-3">
{Links.map(({ icon: Icon, title, href, badge }) => (
<ListItem key={title} asChild>
<a href={href} className="flex items-center">
<ListItemStart>
<Icon className="h-[18px] w-[18px]" />
</ListItemStart>
{title}
{badge && (
<ListItemEnd>
<Badge variant="secondary" className="text-xs">
{badge}
</Badge>
</ListItemEnd>
)}
</a>
</ListItem>
))}
<Separator className="my-3" />
<ListItem
onClick={() => setIsOpen((cur) => !cur)}
className="cursor-pointer"
>
<ListItemStart>
<MoreHorizontal className="h-[18px] w-[18px]" />
</ListItemStart>
More
<ListItemEnd>
<ChevronRight
className={cn(
"h-4 w-4 transition-transform",
isOpen && "rotate-90"
)}
/>
</ListItemEnd>
</ListItem>
<Collapse open={isOpen}>
<CollapseContent>
<List>
<ListItem asChild>
<a href="#" className="flex items-center">
<ListItemStart>
<Folder className="h-[18px] w-[18px]" />
</ListItemStart>
Spam
</a>
</ListItem>
<ListItem asChild>
<a href="#" className="flex items-center">
<ListItemStart>
<UserX className="h-[18px] w-[18px]" />
</ListItemStart>
Blocked
</a>
</ListItem>
<ListItem asChild>
<a href="#" className="flex items-center">
<ListItemStart>
<Folder className="h-[18px] w-[18px]" />
</ListItemStart>
Important
</a>
</ListItem>
</List>
</CollapseContent>
</Collapse>
<Separator className="my-3" />
<ListItem
className="text-destructive hover:bg-destructive/10 hover:text-destructive focus:bg-destructive/10 focus:text-destructive cursor-pointer"
asChild
>
<a href="#" className="flex items-center">
<ListItemStart>
<LogOut className="h-[18px] w-[18px]" />
</ListItemStart>
Logout
</a>
</ListItem>
</List>
</CardContent>
<CardFooter className="p-3">
<Card className="bg-primary shadow-none">
<CardHeader className="m-3">
<LayoutDashboard className="text-primary-foreground h-10 w-10" />
</CardHeader>
<CardContent>
<h6 className="mb-1 text-white">Upgrade to PRO</h6>
<p className="text-sm text-white/80">
Upgrade to Creative Tim UI PRO and get even more components,
plugins, advanced features and premium.
</p>
</CardContent>
<CardFooter>
<Button
size="sm"
asChild
className="border-white bg-white text-black hover:border-white hover:bg-white hover:text-black"
>
<a href="#">Upgrade Now</a>
</Button>
</CardFooter>
</Card>
</CardFooter>
</Card>
</DrawerContent>
</Drawer>
)
}
Props
The drawer component is built using vaul and accepts the following props:
Drawer (Root Component)
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controls whether the drawer is open (controlled) |
defaultOpen | boolean | false | The default open state (uncontrolled) |
onOpenChange | (open: boolean) => void | - | Event handler called when the open state changes |
direction | "top" | "right" | "bottom" | "left" | "bottom" | The direction from which the drawer slides in |
dismissible | boolean | true | Whether the drawer can be dismissed by clicking the overlay |
modal | boolean | true | Whether the drawer should be modal (blocks interaction with background) |
DrawerContent
| Prop | Type | Default | Description |
|---|---|---|---|
direction | "top" | "right" | "bottom" | "left" | "bottom" | The side from which the drawer slides in |
className | string | - | Additional CSS classes for custom styling |
DrawerTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merge props with child element |
className | string | - | Additional CSS classes to apply to the trigger button |
children | ReactNode | - | The content to display in the trigger |
DrawerClose
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Merge props with child element |
className | string | - | Additional CSS classes to apply to the close button |
children | ReactNode | - | The content to display in the close button |
Best Practices
- Use drawers for secondary actions or content that doesn't require full-screen attention
- Choose the appropriate direction based on your layout and user flow
- Keep drawer content focused and avoid overwhelming users with too much information
- Provide clear close buttons or allow dismissal via overlay click
- Consider mobile-first design when implementing drawer navigation
- Use drawers for forms, filters, settings, or navigation menus
- Ensure drawer content is scrollable if it exceeds viewport height
The drawer component provides a smooth, accessible way to display additional content without navigating away from the current page. It's ideal for mobile navigation, quick actions, forms, and contextual information.