Cognition

Components

Drawer

A panel that slides up from the bottom of the screen, keeping the page behind it in view. Built for focused, touch-friendly tasks: quick edits, confirmations, or a short read, dismissed by dragging the handle or tapping outside.

Preview

Rendered with live Cognition tokens: the panel surface, overlay scrim, and text remap on theme change, no dark: classes. Trigger it to slide the panel up.

Variants

<Drawer>
  <DrawerTrigger asChild>
    <Button variant="outline">Open Drawer</Button>
  </DrawerTrigger>
  <DrawerContent>
    <div className="mx-auto w-full max-w-sm">
      <DrawerHeader>
        <DrawerTitle>Move Goal</DrawerTitle>
        <DrawerDescription>Set your daily activity goal.</DrawerDescription>
      </DrawerHeader>
      {/* stepper + chart */}
      <DrawerFooter>
        <Button>Set Goal</Button>
        <DrawerClose asChild>
          <Button variant="outline">Cancel</Button>
        </DrawerClose>
      </DrawerFooter>
    </div>
  </DrawerContent>
</Drawer>
<DrawerContent>
  <div className="mx-auto w-full max-w-sm">
    <DrawerHeader>
      <DrawerTitle>Edit profile</DrawerTitle>
      <DrawerDescription>Make changes to your profile here.</DrawerDescription>
    </DrawerHeader>
    <div className="grid gap-4 p-4">
      <Input id="name" defaultValue="Tony Yates" />
      <Input id="username" defaultValue="@tony" />
    </div>
    <DrawerFooter>…</DrawerFooter>
  </div>
</DrawerContent>
<DrawerContent>
  <div className="mx-auto w-full max-w-sm">
    <DrawerHeader>
      <DrawerTitle>Title Text</DrawerTitle>
      <DrawerDescription>This is a drawer description.</DrawerDescription>
    </DrawerHeader>
    <div className="max-h-[50vh] overflow-y-auto px-4 text-sm text-text-subtle">
      <p>…</p>
    </div>
    <DrawerFooter>…</DrawerFooter>
  </div>
</DrawerContent>

The same primitive frames a statistic with steppers, a short form, or a block of text. Constrain the body with mx-auto w-full max-w-sm so it stays readable on wide screens.

States

<Drawer>…</Drawer>            {/* drag or tap overlay closes */}
<Drawer dismissible={false}>…</Drawer>  {/* only a button closes */}

By default a drawer is dismissible: drag the handle down or tap the overlay. Set dismissible={false} to require an explicit action, for steps the user must acknowledge.

API

Part
Description
Drawer
Root. Holds open / onOpenChange, shouldScaleBackground (scales the page behind it), dismissible, and direction.
DrawerTrigger
Opens the drawer. Use asChild to render your own button.
DrawerContent
The sliding panel: portals over an overlay and renders the drag handle, then your content.
DrawerHeader
Title + description block at the top. Centers on mobile, left-aligns from sm.
DrawerFooter
Actions pinned to the bottom: stacks the primary action over a close.
DrawerTitle / DrawerDescription
Accessible title and supporting text, wired to the dialog for screen readers.
DrawerClose
Closes the drawer. Wrap a button with asChild.

Don't and Do

Don't

Don't use a drawer for a desktop-first dialog: reach for Dialog there. And don't stack drawers or nest one inside another; a drawer is a single focused surface, not a navigation layer.

Do
<Drawer>
  <DrawerTrigger asChild>
    <Button variant="outline">Open</Button>
  </DrawerTrigger>
  <DrawerContent>…</DrawerContent>
</Drawer>
import {
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from "@/components/ui/drawer";

export function GoalDrawer() {
  return (
    <Drawer>
      <DrawerTrigger asChild>
        <Button variant="outline">Open</Button>
      </DrawerTrigger>
      <DrawerContent>
        <div className="mx-auto w-full max-w-sm">
          <DrawerHeader>
            <DrawerTitle>Move Goal</DrawerTitle>
            <DrawerDescription>Set your daily activity goal.</DrawerDescription>
          </DrawerHeader>
          <DrawerFooter>
            <Button>Set Goal</Button>
            <DrawerClose asChild>
              <Button variant="outline">Cancel</Button>
            </DrawerClose>
          </DrawerFooter>
        </div>
      </DrawerContent>
    </Drawer>
  );
}
API matches fe-distillery/components/ui/drawer.tsx Drawer and its Trigger / Content / Header / Footer / Title / Description / Close parts, built on vaul. The raw surface, scrim, handle, and muted text are replaced with Cognition tokens.