Overlays
Drawer
shadcn's Drawer API on the bottom Sheet: a grabber, medium and large detents, drag to resize or dismiss — no vaul.
Installation
pnpm dlx shadcn@latest add https://glasscn.app/r/drawer.jsonReact Native (iOS, Android and web through react-native-web) — same parts and props:
pnpm dlx shadcn@latest add https://glasscn.app/r/native-drawer.jsonOr with the namespace set up: shadcn add @glasscn-app/drawer
shadcn's Drawer parts — Drawer, DrawerTrigger, DrawerClose, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, DrawerTitle, DrawerDescription — on glasscn's bottom Sheet. No vaul dependency.
DrawerContent takes every SheetContent prop except side: detents (default ["medium", "large"]), detent / onDetentChange, grabber, onBeforeDismiss.
Source
components/glass/drawer.tsx
"use client"
import * as React from "react"
import { Sheet, SheetBody, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, type SheetDetent } from "@/components/glass/sheet"
/**
* shadcn's Drawer API on glasscn's bottom Sheet: a panel rising from the bottom with a grabber,
* detents (medium and large by default) and drag-to-dismiss. No vaul — the sheet does the drag.
* Everything Sheet takes works here; Drawer is the name shadcn users reach for.
*/
function Drawer(props: React.ComponentProps<typeof Sheet>) {
return <Sheet data-slot="drawer" {...props} />
}
function DrawerTrigger(props: React.ComponentProps<typeof SheetTrigger>) {
return <SheetTrigger data-slot="drawer-trigger" {...props} />
}
function DrawerClose(props: React.ComponentProps<typeof SheetClose>) {
return <SheetClose data-slot="drawer-close" {...props} />
}
const DEFAULT_DETENTS: SheetDetent[] = ["medium", "large"]
function DrawerContent({ detents = DEFAULT_DETENTS, ...props }: Omit<React.ComponentProps<typeof SheetContent>, "side">) {
return <SheetContent data-slot="drawer-content" side="bottom" detents={detents} {...props} />
}
function DrawerHeader(props: React.ComponentProps<typeof SheetHeader>) {
return <SheetHeader data-slot="drawer-header" {...props} />
}
function DrawerBody(props: React.ComponentProps<typeof SheetBody>) {
return <SheetBody data-slot="drawer-body" {...props} />
}
function DrawerFooter(props: React.ComponentProps<typeof SheetFooter>) {
return <SheetFooter data-slot="drawer-footer" {...props} />
}
function DrawerTitle(props: React.ComponentProps<typeof SheetTitle>) {
return <SheetTitle data-slot="drawer-title" {...props} />
}
function DrawerDescription(props: React.ComponentProps<typeof SheetDescription>) {
return <SheetDescription data-slot="drawer-description" {...props} />
}
export { Drawer, DrawerTrigger, DrawerClose, DrawerContent, DrawerHeader, DrawerBody, DrawerFooter, DrawerTitle, DrawerDescription }