Drawer

A panel that slides in from the edge of the screen, typically containing navigation or supplementary content.


Automatic Installation

This method is still working on progress, please use manual installation for now.

Manual Installation

Install dependencies

npm install radix-ui

Copy the code

components/drawer/drawer.tsx
import * as Lucide from 'lucide-react'
import { Dialog as DrawerPrimitive } from 'radix-ui'
import * as React from 'react'
import { Button } from '#/components/button'
import { type DrawerStyles, drawerStyles } from './drawer.css'
 
const Drawer = (props: React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Root>) => {
  return <DrawerPrimitive.Root {...props} />
}
 
const DrawerTrigger = React.forwardRef<
  React.ComponentRef<typeof DrawerPrimitive.Trigger>,
  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Trigger>
>(({ className, ...props }, forwardedRef) => {
  const styles = drawerStyles()
  return (
    <DrawerPrimitive.Trigger
      ref={forwardedRef}
      className={styles.trigger({ className })}
      {...props}
    />
  )
})
 
const DrawerClose = React.forwardRef<
  React.ComponentRef<typeof DrawerPrimitive.Close>,
  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Close>
>(({ className, ...props }, forwardedRef) => {
  const styles = drawerStyles()
  return (
    <DrawerPrimitive.Close ref={forwardedRef} className={styles.close({ className })} {...props} />
  )
})
 
const DrawerPortal = DrawerPrimitive.Portal
 
const DrawerOverlay = React.forwardRef<
  React.ComponentRef<typeof DrawerPrimitive.Overlay>,
  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Overlay>
>(({ className, ...props }, forwardedRef) => {
  const styles = drawerStyles()
  return (
    <DrawerPrimitive.Overlay
      ref={forwardedRef}
      className={styles.overlay({ className })}
      {...props}
    />
  )
})
 
interface DrawerContentProps
  extends React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Content>,
    DrawerStyles {}
 
const DrawerContent = React.forwardRef<
  React.ComponentRef<typeof DrawerPrimitive.Content>,
  DrawerContentProps
>(({ side = 'right', className, children, ...props }, forwardedRef) => {
  const styles = drawerStyles({ side })
  return (
    <DrawerPortal>
      <DrawerOverlay>
        <DrawerPrimitive.Content
          ref={forwardedRef}
          className={styles.content({ className })}
          {...props}
        >
          {children}
          <DrawerPrimitive.Close asChild>
            <Button variant="ghost" className={styles.closeButton()} size="sm">
              <Lucide.X className={styles.closeIcon()} aria-hidden="true" strokeWidth={2} />
            </Button>
          </DrawerPrimitive.Close>
        </DrawerPrimitive.Content>
      </DrawerOverlay>
    </DrawerPortal>
  )
})
 
const DrawerHeader = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(
  ({ className, ...props }, forwardedRef) => {
    const styles = drawerStyles()
    return <div ref={forwardedRef} className={styles.header({ className })} {...props} />
  }
)
 
const DrawerTitle = React.forwardRef<
  React.ComponentRef<typeof DrawerPrimitive.Title>,
  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Title>
>(({ className, ...props }, forwardedRef) => {
  const styles = drawerStyles()
  return (
    <DrawerPrimitive.Title ref={forwardedRef} className={styles.title({ className })} {...props} />
  )
})
 
const DrawerBody = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(
  ({ className, ...props }, forwardedRef) => {
    const styles = drawerStyles()
    return <div ref={forwardedRef} className={styles.body({ className })} {...props} />
  }
)
 
const DrawerDescription = React.forwardRef<
  React.ComponentRef<typeof DrawerPrimitive.Description>,
  React.ComponentPropsWithoutRef<typeof DrawerPrimitive.Description>
>(({ className, ...props }, forwardedRef) => {
  const styles = drawerStyles()
  return (
    <DrawerPrimitive.Description
      ref={forwardedRef}
      className={styles.description({ className })}
      {...props}
    />
  )
})
 
const DrawerFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => {
  const styles = drawerStyles()
  return <div className={styles.footer({ className })} {...props} />
}
 
Drawer.displayName = 'Drawer'
DrawerTrigger.displayName = 'Drawer.Trigger'
DrawerClose.displayName = 'Drawer.Close'
DrawerPortal.displayName = 'DrawerPortal'
DrawerOverlay.displayName = 'DrawerOverlay'
DrawerContent.displayName = 'DrawerContent'
DrawerHeader.displayName = 'Drawer.Header'
DrawerTitle.displayName = 'DrawerTitle'
DrawerBody.displayName = 'Drawer.Body'
DrawerDescription.displayName = 'DrawerDescription'
DrawerFooter.displayName = 'DrawerFooter'
 
export {
  Drawer,
  DrawerBody,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerPortal,
  DrawerTitle,
  DrawerTrigger,
}

Usage

Imports

import {
  Drawer,
  DrawerBody,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerPortal,
  DrawerTitle,
  DrawerTrigger,
} from '#/components/drawer'

Example

Browse the Storybook for more examples.

Edit on GitHub

Last updated on 3/24/2025

On this page