sc1m/design
ComponentsDrawer

Drawer

Drawer component built on Base UI, styled with sc1m tokens.

StableBase UI

Live preview

Installation

pnpm dlx shadcn@latest add @sc1m/drawer

This also merges the token layer and installs src/lib/cn.ts plus @base-ui/react. For the manual route — prerequisites, components.json, and app-level setup — see Installation.

Usage

import {
  Drawer,
  DrawerTrigger,
  DrawerContent,
  DrawerTitle,
  DrawerDescription,
  DrawerClose,
} from "@/components/ui/drawer";

Composition

Every part is a separate export. Drawer owns state; the rest are presentational and must appear in this order.

Drawer├── DrawerTrigger└── DrawerContent    ├── DrawerTitle    ├── DrawerDescription    └── DrawerClose

Example

The preview above, with its source. This is the demo module verbatim, so the code and the thing it renders cannot drift apart.

<Drawer>
  <DrawerTrigger render={<Button variant="secondary" />}>
    Open drawer
  </DrawerTrigger>
  <DrawerContent>
    <DrawerTitle className="text-base font-semibold">
      Notifications
    </DrawerTitle>
    <DrawerDescription className="mt-1 text-sm text-fg-muted">
      You are all caught up. Good job!
    </DrawerDescription>
    <div className="mt-5 flex justify-end gap-2">
      <DrawerClose render={<Button variant="ghost" />}>Close</DrawerClose>
    </div>
  </DrawerContent>
</Drawer>

API reference

Each part forwards every prop of its Base UI counterpart; the tables list the ones declared on the part itself. See Base UI's reference for the inherited element props.

Drawer

PropTypeDefaultDescription
openbooleanWhether the drawer is currently open.
defaultOpenbooleanfalseWhether the drawer is initially open.
modalboolean | 'trap-focus'trueDetermines if the drawer enters a modal state when open.
onOpenChange((open: boolean, eventDetails: DrawerRoot.ChangeEventDetails) => void)Event handler called when the drawer is opened or closed.
onOpenChangeComplete((open: boolean) => void)Event handler called after any animations complete when the drawer is opened or closed.
disablePointerDismissalbooleanfalseWhether to prevent the drawer from closing on outside presses.
actionsRefReact.RefObject<DrawerRoot.Actions | null>A ref to imperative actions.
handleDrawerHandle<Payload>A handle to associate the drawer with a trigger.
triggerIdstring | nullID of the trigger that the drawer is associated with.
defaultTriggerIdstring | nullID of the trigger that the drawer is associated with.
swipeDirectionDrawerSwipeDirection'down'The swipe direction used to dismiss the drawer.
snapPointsDrawerSnapPoint[]Snap points used to position the drawer.
snapToSequentialPointsbooleanfalseDisables velocity-based snap skipping so drag distance determines the next snap point.
snapPointDrawerSnapPoint | nullThe currently active snap point.
defaultSnapPointDrawerSnapPoint | nullThe initial snap point value when uncontrolled.
onSnapPointChange((snapPoint: DrawerSnapPoint | null, eventDetails: DrawerRoot.SnapPointChangeEventDetails) => void)Callback fired when the snap point changes.

DrawerTrigger

PropTypeDefaultDescription
handleDrawerHandle<Payload>A handle to associate the trigger with a drawer.
payloadPayloadA payload to pass to the drawer when it is opened.
idstringID of the trigger.

DrawerContent

PropTypeDefaultDescription
initialFocusboolean | React.RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void)Determines the element to focus when the drawer is opened.
finalFocusboolean | React.RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void)Determines the element to focus when the drawer is closed.

Accessibility

Behaviour, focus management, and ARIA wiring come from Base UI's Drawer — see its reference for the full keyboard map.

  • Decorative glyphs are aria-hidden, so they are not announced.

Design tokens

The component reads semantic tokens only — no raw colour, radius, or duration appears in its source. Override the token, not the component.

TokenApplied to
--brand-radius-xlDrawerContent
--fgDrawerContent
--lineDrawerContent
--line-strongDrawerContent
--shadow-overlayDrawerContent
--surface-raisedDrawerContent

Source

src/components/ui/drawer/drawer.tsx — no next/* imports, so it drops into any React 19 + Tailwind v4 app.