0
# Core Components
1
2
The fundamental drawer components that form the building blocks of any drawer interface. These components work together to create the basic drawer structure and behavior.
3
4
## Capabilities
5
6
### Drawer.Root
7
8
Main root component that provides context and state management for the entire drawer system. This component must wrap all other drawer components.
9
10
```typescript { .api }
11
/**
12
* Root component that provides drawer context and manages state
13
* @param props - Configuration props for the drawer
14
* @returns Root drawer component
15
*/
16
interface Drawer.Root extends React.Component<DialogProps> {}
17
18
interface DialogProps {
19
/** Controlled open state */
20
open?: boolean;
21
/** Callback fired when open state changes */
22
onOpenChange?: (open: boolean) => void;
23
/** Default open state for uncontrolled usage */
24
defaultOpen?: boolean;
25
/** Child components */
26
children?: React.ReactNode;
27
/** Array for snap point behavior - numbers 0-100 for % or px values */
28
snapPoints?: (number | string)[];
29
/** Index from which overlay fade should be applied */
30
fadeFromIndex?: number;
31
/** Controlled active snap point */
32
activeSnapPoint?: number | string | null;
33
/** Callback to set active snap point */
34
setActiveSnapPoint?: (snapPoint: number | string | null) => void;
35
/** Threshold for closing (default: 0.25) */
36
closeThreshold?: number;
37
/** Prevent body style changes */
38
noBodyStyles?: boolean;
39
/** Enable background scaling effect */
40
shouldScaleBackground?: boolean;
41
/** Change background color when scaling */
42
setBackgroundColorOnScale?: boolean;
43
/** Duration for scroll lock in ms (default: 100) */
44
scrollLockTimeout?: number;
45
/** Fixed positioning behavior */
46
fixed?: boolean;
47
/** Restrict dragging to handle only */
48
handleOnly?: boolean;
49
/** Allow dismissal via gestures (default: true) */
50
dismissible?: boolean;
51
/** Drag event handler */
52
onDrag?: (event: React.PointerEvent<HTMLDivElement>, percentageDragged: number) => void;
53
/** Release event handler */
54
onRelease?: (event: React.PointerEvent<HTMLDivElement>, open: boolean) => void;
55
/** Modal behavior (default: true) */
56
modal?: boolean;
57
/** Nested drawer support */
58
nested?: boolean;
59
/** Close callback */
60
onClose?: () => void;
61
/** Drawer direction (default: 'bottom') */
62
direction?: 'top' | 'bottom' | 'left' | 'right';
63
/** Disable scroll prevention */
64
disablePreventScroll?: boolean;
65
/** Reposition inputs on keyboard */
66
repositionInputs?: boolean;
67
/** Disable velocity-based snapping */
68
snapToSequentialPoint?: boolean;
69
/** Portal container */
70
container?: HTMLElement | null;
71
/** Animation end callback */
72
onAnimationEnd?: (open: boolean) => void;
73
/** Prevent scroll restoration */
74
preventScrollRestoration?: boolean;
75
/** Auto focus behavior */
76
autoFocus?: boolean;
77
}
78
```
79
80
**Usage Examples:**
81
82
```typescript
83
import { Drawer } from "vaul";
84
85
// Basic drawer
86
function BasicDrawer() {
87
return (
88
<Drawer.Root>
89
<Drawer.Trigger>Open</Drawer.Trigger>
90
<Drawer.Portal>
91
<Drawer.Content>Content</Drawer.Content>
92
</Drawer.Portal>
93
</Drawer.Root>
94
);
95
}
96
97
// Controlled drawer with snap points
98
function ControlledDrawer() {
99
const [open, setOpen] = React.useState(false);
100
101
return (
102
<Drawer.Root
103
open={open}
104
onOpenChange={setOpen}
105
snapPoints={[0.2, 0.5, 0.8]}
106
fadeFromIndex={1}
107
>
108
<Drawer.Trigger>Open Drawer</Drawer.Trigger>
109
<Drawer.Portal>
110
<Drawer.Overlay />
111
<Drawer.Content>
112
<p>Drawer with snap points</p>
113
</Drawer.Content>
114
</Drawer.Portal>
115
</Drawer.Root>
116
);
117
}
118
```
119
120
### Drawer.Content
121
122
Main drawer content container that holds the actual drawer content. This component handles pointer events and provides the visual container for drawer contents.
123
124
```typescript { .api }
125
/**
126
* Main drawer content container
127
* @param props - Content component props extending Radix Dialog.Content
128
* @param ref - Forwarded ref to the content element
129
* @returns Content container component
130
*/
131
interface Drawer.Content extends React.ForwardRefExoticComponent<ContentProps> {}
132
133
type ContentProps = React.ComponentProps<typeof DialogPrimitive.Content>;
134
```
135
136
**Usage Examples:**
137
138
```typescript
139
// Basic content
140
<Drawer.Content>
141
<h2>Drawer Title</h2>
142
<p>Drawer content goes here.</p>
143
</Drawer.Content>
144
145
// Content with custom styling
146
<Drawer.Content className="drawer-content">
147
<div className="drawer-header">
148
<Drawer.Title>Settings</Drawer.Title>
149
<Drawer.Close>×</Drawer.Close>
150
</div>
151
<div className="drawer-body">
152
<p>Settings content...</p>
153
</div>
154
</Drawer.Content>
155
```
156
157
### Drawer.Overlay
158
159
Backdrop overlay component that appears behind the drawer content. Clicking the overlay typically closes the drawer (unless configured otherwise).
160
161
```typescript { .api }
162
/**
163
* Backdrop overlay component
164
* @param props - Overlay component props extending Radix Dialog.Overlay
165
* @param ref - Forwarded ref to the overlay element
166
* @returns Overlay backdrop component
167
*/
168
interface Drawer.Overlay extends React.ForwardRefExoticComponent<React.ComponentProps<typeof DialogPrimitive.Overlay>> {}
169
```
170
171
**Usage Examples:**
172
173
```typescript
174
// Basic overlay
175
<Drawer.Overlay />
176
177
// Overlay with custom styling
178
<Drawer.Overlay className="drawer-overlay" />
179
180
// Overlay with click handler
181
<Drawer.Overlay onClick={() => console.log('Overlay clicked')} />
182
```
183
184
### Drawer.Trigger
185
186
Button or element that triggers the drawer to open when activated. Can be any interactive element.
187
188
```typescript { .api }
189
/**
190
* Element that triggers drawer open when activated
191
*/
192
interface Drawer.Trigger extends typeof DialogPrimitive.Trigger {}
193
```
194
195
**Usage Examples:**
196
197
```typescript
198
// Button trigger
199
<Drawer.Trigger>Open Drawer</Drawer.Trigger>
200
201
// Custom trigger with styling
202
<Drawer.Trigger className="custom-trigger">
203
<Icon name="menu" />
204
Menu
205
</Drawer.Trigger>
206
207
// Trigger as different element
208
<Drawer.Trigger asChild>
209
<button className="my-button">Custom Button</button>
210
</Drawer.Trigger>
211
```
212
213
### Drawer.Portal
214
215
Portal component that renders the drawer outside the normal DOM tree. This ensures proper layering and prevents styling conflicts.
216
217
```typescript { .api }
218
/**
219
* Portal component for rendering drawer outside normal DOM tree
220
* @param props - Portal props extending Radix Dialog.Portal with container override
221
* @returns Portal component
222
*/
223
interface Drawer.Portal extends React.Component<PortalProps> {}
224
225
interface PortalProps extends React.ComponentProps<typeof DialogPrimitive.Portal> {
226
/** Override container for portal rendering */
227
container?: HTMLElement;
228
}
229
```
230
231
**Usage Examples:**
232
233
```typescript
234
// Default portal (renders to document.body)
235
<Drawer.Portal>
236
<Drawer.Overlay />
237
<Drawer.Content>Content</Drawer.Content>
238
</Drawer.Portal>
239
240
// Portal to custom container
241
<Drawer.Portal container={customContainer}>
242
<Drawer.Overlay />
243
<Drawer.Content>Content</Drawer.Content>
244
</Drawer.Portal>
245
```