Tessera UI

Drawer

An accessible slide-in panel built on Base UI Dialog. Compound component pattern with Header, Body, Footer, Title, and Description. Four sides (right, left, top, bottom). Five sizes. Five corner-rounding options. Auto-stacking footer for sheets. LTR and RTL support.

Installation

pnpm add @tessinaui/ui

Usage

import {
  Drawer,
  DrawerTrigger,
  DrawerClose,
  DrawerContent,
  DrawerHeader,
  DrawerTitle,
  DrawerDescription,
  DrawerBody,
  DrawerFooter,
} from "@tessinaui/ui";
<Drawer>
  <DrawerTrigger className="...">Open</DrawerTrigger>

  <DrawerContent>
    <DrawerHeader>
      <DrawerTitle>Panel title</DrawerTitle>
      <DrawerDescription>Supporting description text.</DrawerDescription>
    </DrawerHeader>

    <DrawerBody>
      <p>Content goes here.</p>
    </DrawerBody>

    <DrawerFooter>
      <DrawerClose className="...">Cancel</DrawerClose>
      <DrawerClose className="...">Save</DrawerClose>
    </DrawerFooter>
  </DrawerContent>
</Drawer>

Playground

Preview

Showcase

Preview

API Reference

Drawer

Root component. Wraps Base UI Dialog.Root and provides context for side, size, and dir.

PropTypeDefaultDescription
side"right" | "left" | "top" | "bottom""right"Which edge the panel slides from
size"sm" | "md" | "lg" | "xl" | "full""md"Panel width (right/left) or max-height (top/bottom)
dir"ltr" | "rtl""ltr"Text direction applied to the panel and its children
openbooleanControlled open state
defaultOpenbooleanUncontrolled initial open state
onOpenChange(open: boolean, event: Event) => voidCalled when the open state changes
dismissiblebooleantrueWhether backdrop click or Escape closes the drawer
modalbooleantrueWhether to use modal behavior (focus trap, scroll lock)

DrawerContent

Renders the panel inside a portal. Includes the backdrop automatically.

PropTypeDefaultDescription
sideDrawerSidefrom contextOverride the slide-in side
sizeDrawerSizefrom contextOverride the panel size
rounded"none" | "sm" | "md" | "lg" | "full""md"Corner rounding (applied to inner corners only)
showHandlebooleantrue for bottom, false otherwiseShow the drag handle pill

Size values:

Sizeright / lefttop / bottom
sm320pxmax-h 40dvh
md400pxmax-h 60dvh
lg512pxmax-h 75dvh
xl640pxmax-h 90dvh
full100%100dvh

DrawerHeader

PropTypeDefaultDescription
iconReactNodeLeading icon rendered beside the title
showClosebooleantrueWhether to render the built-in X close button

The first child of DrawerHeader is treated as the title row (shares a line with the icon). All subsequent children (e.g. DrawerDescription) render full-width below it.

DrawerTitle

Renders as Dialog.Title. Accepts all <div> props plus className.

DrawerDescription

Renders as Dialog.Description. Accepts all <div> props plus className.

DrawerBody

Scrollable content area. Grows to fill available space between header and footer. Accepts all <div> props plus className.

DrawerFooter

Action area. For side="bottom" and side="top" drawers, buttons stack vertically (full-width). For side="left" and side="right" drawers, buttons align horizontally to the end. Pass className="flex-row items-center justify-end" to override the auto-stacking behaviour.

DrawerTrigger

Re-export of Dialog.Trigger. Renders a <button> that opens the drawer. Use the render prop to swap in a custom element.

DrawerClose

Re-export of Dialog.Close. Renders a <button> that closes the drawer. Use the render prop to swap in a custom element.

DrawerBackdrop

Pre-styled backdrop with blur and fade animation. Included automatically by DrawerContent.

On this page