Drawer
A drawer component for React.
About
Drawer is built on top of Vaul by emilkowalski_.
Installation
Install the following dependencies:
npm install vaulCopy and paste the following code into your project.
'use client';
import clsx from 'clsx';
import { ComponentProps, ComponentPropsWithoutRef, ElementRef, HTMLAttributes, forwardRef } from 'react';
import { Drawer as DrawerPrimitive } from 'vaul';
import styles from './styles.module.scss';
const Drawer = ({ shouldScaleBackground = true, ...props }: ComponentProps<typeof DrawerPrimitive.Root>) => (
<DrawerPrimitive.Root shouldScaleBackground={shouldScaleBackground} {...props} />
);
Drawer.displayName = 'Drawer';
const DrawerTrigger = DrawerPrimitive.Trigger;
const DrawerPortal = DrawerPrimitive.Portal;
const DrawerClose = DrawerPrimitive.Close;
const DrawerOverlay = forwardRef<
ElementRef<typeof DrawerPrimitive.Overlay>,
ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Overlay ref={ref} className={clsx(styles.drawer__overlay, className)} {...props} />
));
DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName;
const DrawerContent = forwardRef<
ElementRef<typeof DrawerPrimitive.Content>,
ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>
>(({ className, children, ...props }, ref) => (
<DrawerPortal>
<DrawerOverlay />
<DrawerPrimitive.Content ref={ref} className={clsx(styles.drawer__content, className)} {...props}>
<div className={styles.div} />
{children}
</DrawerPrimitive.Content>
</DrawerPortal>
));
DrawerContent.displayName = 'DrawerContent';
const DrawerHeader = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (
<div className={clsx(styles.drawer__header, className)} {...props} />
);
DrawerHeader.displayName = 'DrawerHeader';
const DrawerFooter = ({ className, ...props }: HTMLAttributes<HTMLDivElement>) => (
<div className={clsx(styles.drawer__footer, className)} {...props} />
);
DrawerFooter.displayName = 'DrawerFooter';
const DrawerTitle = forwardRef<
ElementRef<typeof DrawerPrimitive.Title>,
ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Title ref={ref} className={clsx(styles.drawer__title, className)} {...props} />
));
DrawerTitle.displayName = DrawerPrimitive.Title.displayName;
const DrawerDescription = forwardRef<
ElementRef<typeof DrawerPrimitive.Description>,
ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
>(({ className, ...props }, ref) => (
<DrawerPrimitive.Description ref={ref} className={clsx(styles.drawer__description, className)} {...props} />
));
DrawerDescription.displayName = DrawerPrimitive.Description.displayName;
export {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerOverlay,
DrawerPortal,
DrawerTitle,
DrawerTrigger,
};Update the import paths to match your project setup.
Usage
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/components/ui/drawer';<Drawer>
<DrawerTrigger>Open</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Are you absolutely sure?</DrawerTitle>
<DrawerDescription>This action cannot be undone.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose>
<Button variant='outline'>Cancel</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>Examples
Responsive Dialog
You can combine the Dialog and Drawer components to create a responsive dialog. This renders a Dialog component on desktop and a Drawer on mobile.