Modern web applications often need a panel that will slide into view instead of navigating to a different page. These panels are commonly called drawers. The drawers are perfect for mobile menus, settings panels, shopping carts, and quick forms.
While you can build a drawer from scratch, handling the animations, gestures, state management, and accessibility can quickly become complicated. That is where the Vaul package comes in. Vaul is a lightweight React library that makes creating beautiful and accessible drawer components easy, especially for mobile-first interfaces. In this guide, we will learn how to install Vaul and create your first drawer in a React application.
What is Vaul?
Vaul is a React component library that is specifically designed for creating drawer interfaces. It provides smooth drawer animations and mobile-friendly interactions. We can also handle the drawer overlay and positioning easily with Vaul.
Set up a React project
If you don't have a React project, create one using Vite
npm create vite@latest
npm install
npm run dev
Install Vaul
Install the Vaul package using npm
npm install vaul
Creating the first drawer
Let's now build a simple drawer with Vaul. When the button is clicked, a drawer appears from the bottom of the screen.
import { Drawer } from "vaul";
export default function App() {
return (
<Drawer.Root>
<Drawer.Trigger asChild>
<button>Open Drawer</button>
</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Overlay className="overlay" />
<Drawer.Content className="drawer">
<Drawer.Title>
Welcome
</Drawer.Title>
<Drawer.Description>
This is your first Vaul drawer.
</Drawer.Description>
</Drawer.Content>
</Drawer.Portal>
</Drawer.Root>
);
} - Drawer.Root - This is the main wrapper of Vaul, and it manages the drawer state
- Drawer.Trigger - This handles the triggering of the drawer
- Drawer.Overlay - This creates the dark overlay background behind the drawer
- Drawer.Content - This contains all the contents that will display in the drawer
Add basic styling
Vaul is unstyled, so we need to add our own styles to the drawer.
.overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.4);
}
.drawer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
padding: 24px;
border-radius: 16px 16px 0 0;
min-height: 250px;
}With tailwind css styling
<Drawer.Overlay className="fixed inset-0 bg-black/40" />
<Drawer.Content className="fixed bottom-0 left-0 right-0 rounded-t-3xl bg-white p-6">
<Drawer.Title className="text-xl font-semibold">
Settings
</Drawer.Title>
<Drawer.Description className="text-gray-500">
Manage your preferences.
</Drawer.Description>
</Drawer.Content>
Controlling drawer state
We can also handle the drawer state programmatically like this
import { useState } from "react";
import { Drawer } from "vaul";
export default function App() {
const [open, setOpen] = useState(false);
return (
<Drawer.Root
open={open}
onOpenChange={setOpen}
>
<Drawer.Trigger asChild>
<button>Open Drawer</button>
</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Overlay />
<Drawer.Content>
<Drawer.Title>
Controlled Drawer
</Drawer.Title>
<button
onClick={() => setOpen(false)}
>
Close
</button>
</Drawer.Content>
</Drawer.Portal>
</Drawer.Root>
);
}Setting drawer directions
By default, the drawer opens from the bottom; however, vaul also supports other directions.
<Drawer.Root direction="right">
direction="bottom"
direction="top"
direction="left"
direction="right"
Vaul makes it easy to build modern, accessible, and mobile-friendly drawer components in React. Instead of spending time on handling complete animation, drawer states, and gestures, you can focus on building a great user experience. With support of custom styling, snap points, multiple directions, and smooth interactions, Vaul is the best solution for this.
To read more about How to Use the Activity Component in React 19.2, refer to our blog How to Use the Activity Component in React 19.2.