CoreUI is in beta - APIs and components may change.
CoreUI
Base Components

Drawer

A panel which slides out from the edge of the screen.


Installation

Install the following dependencies:

npm install @radix-ui/react-dialog

Create a drawer.tsx file and paste the following code into it.

components/ui/drawer.tsx
// CoreUI Drawer v0.0.0'use client';import * as React from 'react';import * as DialogPrimitive from '@radix-ui/react-dialog';import { RiCloseLine } from '@remixicon/react';import * as CompactButton from '@/components/ui/compact-button';import { cn } from '@/utils/cn';const DrawerRoot = DialogPrimitive.Root;DrawerRoot.displayName = 'Drawer';const DrawerTrigger = DialogPrimitive.Trigger;DrawerTrigger.displayName = 'DrawerTrigger';const DrawerClose = DialogPrimitive.Close;DrawerClose.displayName = 'DrawerClose';const DrawerPortal = DialogPrimitive.Portal;DrawerPortal.displayName = 'DrawerPortal';const DrawerOverlay = React.forwardRef<  React.ComponentRef<typeof DialogPrimitive.Overlay>,  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>>(({ className, ...rest }, forwardedRef) => {  return (    <DialogPrimitive.Overlay      ref={forwardedRef}      className={cn(        // base        'fixed inset-0 z-50 grid grid-cols-1 place-items-end overflow-hidden bg-overlay backdrop-blur-[10px]',        // animation        'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',        className,      )}      {...rest}    />  );});DrawerOverlay.displayName = 'DrawerOverlay';const DrawerContent = React.forwardRef<  React.ComponentRef<typeof DialogPrimitive.Content>,  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>>(({ className, children, ...rest }, forwardedRef) => {  return (    <DrawerPortal>      <DrawerOverlay>        <DialogPrimitive.Content          ref={forwardedRef}          className={cn(            // base            'size-full max-w-100 overflow-y-auto',            'border-l border-stroke-soft-200 bg-bg-white-0',            // animation            'data-[state=open]:duration-200 data-[state=open]:ease-out data-[state=open]:animate-in',            'data-[state=closed]:duration-200 data-[state=closed]:ease-in data-[state=closed]:animate-out',            'data-[state=open]:slide-in-from-right-full',            'data-[state=closed]:slide-out-to-right-full',            className,          )}          {...rest}        >          <div className='relative flex size-full flex-col'>{children}</div>        </DialogPrimitive.Content>      </DrawerOverlay>    </DrawerPortal>  );});DrawerContent.displayName = 'DrawerContent';function DrawerHeader({  className,  children,  showCloseButton = true,  ...rest}: React.HTMLAttributes<HTMLDivElement> & {  showCloseButton?: boolean;}) {  return (    <div      className={cn(        'flex items-center gap-3 border-stroke-soft-200 p-5',        className,      )}      {...rest}    >      {children}      {showCloseButton && (        <DrawerClose asChild>          <CompactButton.Root variant='ghost' size='large'>            <CompactButton.Icon as={RiCloseLine} />          </CompactButton.Root>        </DrawerClose>      )}    </div>  );}DrawerHeader.displayName = 'DrawerHeader';const DrawerTitle = React.forwardRef<  React.ComponentRef<typeof DialogPrimitive.Title>,  React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>>(({ className, ...rest }, forwardedRef) => {  return (    <DialogPrimitive.Title      ref={forwardedRef}      className={cn('flex-1 text-label-lg text-text-strong-950', className)}      {...rest}    />  );});DrawerTitle.displayName = 'DrawerTitle';function DrawerBody({  className,  children,  ...rest}: React.HTMLAttributes<HTMLDivElement>) {  return (    <div className={cn('flex-1', className)} {...rest}>      {children}    </div>  );}DrawerBody.displayName = 'DrawerBody';function DrawerFooter({  className,  ...rest}: React.HTMLAttributes<HTMLDivElement>) {  return (    <div      className={cn(        'flex items-center gap-4 border-stroke-soft-200 p-5',        className,      )}      {...rest}    />  );}DrawerFooter.displayName = 'DrawerFooter';export {  DrawerRoot as Root,  DrawerTrigger as Trigger,  DrawerClose as Close,  DrawerContent as Content,  DrawerHeader as Header,  DrawerTitle as Title,  DrawerBody as Body,  DrawerFooter as Footer,};

Examples

Basic

API Reference

This component is based on the Radix UI Dialog primitives. Refer to their documentation for the API reference.

Drawer.Root

This component is based on the Dialog.Root primitive.

Drawer.Trigger

This component is based on the Dialog.Trigger primitive.

Drawer.Close

This component is based on the Dialog.Close primitive.

Drawer.Content

This component is based on the Dialog.Content primitive. Wrapped by Portal and Overlay.

Drawer.Header

This component is based on the <div> element and supports all of its props. And adds:

PropTypeDefault
showCloseButtonbooleantrue

Drawer.Title

This component is based on the Dialog.Title primitive.

Drawer.Body

This component is based on the <div> element and supports all of its props.

Drawer.Footer

This component is based on the <div> element and supports all of its props.

On this page