Drawer component for React.
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Vaul is an unstyled drawer component library for React that serves as a Dialog replacement optimized for tablet and mobile devices. It provides a comprehensive set of components that work together to create smooth, accessible drawer interfaces with advanced features like snap points, fade transitions, drag gestures with velocity-based animations, and accessibility support.
npm install vaulstyle.css available for basic stylingimport { Drawer } from "vaul";For TypeScript projects, you can also import individual types:
import {
Drawer,
useDrawerContext,
type DialogProps,
type ContentProps,
type HandleProps,
type WithFadeFromProps,
type WithoutFadeFromProps,
type DrawerDirection,
type DrawerContextValue
} from "vaul";For CommonJS:
const { Drawer } = require("vaul");import { Drawer } from "vaul";
function MyComponent() {
return (
<Drawer.Root>
<Drawer.Trigger>Open Drawer</Drawer.Trigger>
<Drawer.Portal>
<Drawer.Overlay />
<Drawer.Content>
<Drawer.Handle />
<Drawer.Title>Drawer Title</Drawer.Title>
<Drawer.Description>Drawer content goes here.</Drawer.Description>
<Drawer.Close>Close</Drawer.Close>
</Drawer.Content>
</Drawer.Portal>
</Drawer.Root>
);
}Vaul is built around several key components:
Root, Content, Overlay, Trigger, etc.)The fundamental drawer components that form the building blocks of any drawer interface.
// Main root component that provides context and state management
interface Drawer.Root extends React.Component<DialogProps> {}
// Main drawer content container
interface Drawer.Content extends React.ForwardRefExoticComponent<ContentProps> {}
// Backdrop overlay component
interface Drawer.Overlay extends React.ForwardRefExoticComponent<React.ComponentProps<typeof DialogPrimitive.Overlay>> {}
// Button/element that triggers drawer open
interface Drawer.Trigger extends typeof DialogPrimitive.Trigger {}
// Portal component for rendering drawer outside normal DOM tree
interface Drawer.Portal extends React.Component<React.ComponentProps<typeof DialogPrimitive.Portal> & { container?: HTMLElement }> {}Specialized components for drawer interaction and accessibility.
// Draggable handle component for drawer interaction
interface Drawer.Handle extends React.ForwardRefExoticComponent<HandleProps> {}
// Element that closes the drawer when activated
interface Drawer.Close extends typeof DialogPrimitive.Close {}
// Accessible title element for drawer
interface Drawer.Title extends typeof DialogPrimitive.Title {}
// Accessible description element for drawer
interface Drawer.Description extends typeof DialogPrimitive.Description {}
// Special root component for nested drawers
interface Drawer.NestedRoot extends React.Component<DialogProps> {}Type definitions and interfaces for configuring drawer behavior.
interface DialogProps {
open?: boolean;
onOpenChange?: (open: boolean) => void;
defaultOpen?: boolean;
children?: React.ReactNode;
snapPoints?: (number | string)[];
fadeFromIndex?: number;
activeSnapPoint?: number | string | null;
setActiveSnapPoint?: (snapPoint: number | string | null) => void;
closeThreshold?: number;
noBodyStyles?: boolean;
shouldScaleBackground?: boolean;
setBackgroundColorOnScale?: boolean;
scrollLockTimeout?: number;
fixed?: boolean;
handleOnly?: boolean;
dismissible?: boolean;
onDrag?: (event: any, percentageDragged: number) => void;
onRelease?: (event: any, open: boolean) => void;
modal?: boolean;
nested?: boolean;
onClose?: () => void;
direction?: 'top' | 'bottom' | 'left' | 'right';
disablePreventScroll?: boolean;
repositionInputs?: boolean;
snapToSequentialPoint?: boolean;
container?: HTMLElement | null;
onAnimationEnd?: (open: boolean) => void;
preventScrollRestoration?: boolean;
autoFocus?: boolean;
}Advanced context and hooks for building custom drawer components and accessing drawer state.
// Hook to access drawer context from within drawer components
function useDrawerContext(): DrawerContextValue;
// Context value interface containing all drawer state and methods
interface DrawerContextValue {
drawerRef: React.RefObject<HTMLDivElement>;
overlayRef: React.RefObject<HTMLDivElement>;
onPress: (event: React.PointerEvent<HTMLDivElement>) => void;
onRelease: (event: React.PointerEvent<HTMLDivElement> | null) => void;
onDrag: (event: React.PointerEvent<HTMLDivElement>) => void;
dismissible: boolean;
isOpen: boolean;
isDragging: boolean;
modal: boolean;
shouldFade: boolean;
activeSnapPoint?: number | string | null;
setActiveSnapPoint: (snapPoint: number | string | null) => void;
closeDrawer: () => void;
direction: DrawerDirection;
// ... additional properties for complete drawer state
}See Configuration & Types for complete context interface and usage examples.