Drawer
Slide-in panels from any edge: right-side detail on desktop, bottom sheet on mobile; size sm, md or lg.
Wraps: vaul
Direction
Right panel on wide screens, bottom sheet on phones (the default).
Use it
Examples import from the package. With copied source, import from @/components/ui/drawer instead.
import { Button, Drawer, DrawerClose, DrawerContent, DrawerTitle, DrawerTrigger } from "@zedtech/zedkit-ui";
<Drawer direction="right">
<DrawerTrigger asChild><Button>Open</Button></DrawerTrigger>
<DrawerContent>
<DrawerClose asChild><Button variant="ghost" size="sm">Close</Button></DrawerClose>
<DrawerTitle>Details</DrawerTitle>
</DrawerContent>
</Drawer>Bottom sheet
import { Button, Drawer, DrawerContent, DrawerHandle, DrawerTitle, DrawerTrigger } from "@zedtech/zedkit-ui";
<Drawer>
<DrawerTrigger asChild><Button variant="outline">Filters</Button></DrawerTrigger>
<DrawerContent>
<DrawerHandle />
<DrawerTitle>Filters</DrawerTitle>
</DrawerContent>
</Drawer>Side panel on every screen
import { Button, Drawer, DrawerBody, DrawerCloseButton, DrawerContent, DrawerHeader, DrawerTitle, DrawerTrigger } from "@zedtech/zedkit-ui";
<Drawer direction="left" mobile="side">
<DrawerTrigger asChild><Button variant="outline">Menu</Button></DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Menu</DrawerTitle>
<DrawerCloseButton />
</DrawerHeader>
<DrawerBody>Links</DrawerBody>
</DrawerContent>
</Drawer>Kit not installed yet?
Install
Terminal pnpm add @zedtech/zedkit-ui @fontsource-variable/inter @fontsource-variable/space-groteskLoad the styles
Tailwind does not scan node_modules, so the @source line points it at the kit's class names. The path is relative to this file.
src/app/globals.cssReplace the contents@import "tailwindcss"; @import "@zedtech/zedkit-ui/styles.css"; @source "../../node_modules/@zedtech/zedkit-ui/src/**/*.{ts,tsx}"; @source not "../../node_modules/@zedtech/zedkit-ui/src/**/*.test.*";Pick a look
Set data-identity="glass" on <html> so the finished app matches the site. Fresh app: replace src/app/layout.tsx. Existing app: merge, and keep ThemeProvider and other providers.
src/app/layout.tsxReplace the contentsimport "./globals.css"; import "./fonts"; export default function RootLayout({ children }: { children: React.ReactNode }) { return ( <html lang="en" data-identity="glass"> <body>{children}</body> </html> ); }Load the fonts
The Glass look uses Inter and Space Grotesk; these imports self-host them.
src/app/fonts.tsCreate the fileimport "@fontsource-variable/inter"; import "@fontsource-variable/space-grotesk";Import and render
src/app/page.tsxReplace the contentsimport { Button, Drawer, DrawerClose, DrawerContent, DrawerTitle, DrawerTrigger } from "@zedtech/zedkit-ui"; export default function Page() { return ( <main className="px-page-gutter py-section-sm"> <Drawer direction="right"> <DrawerTrigger asChild><Button>Open</Button></DrawerTrigger> <DrawerContent> <DrawerClose asChild><Button variant="ghost" size="sm">Close</Button></DrawerClose> <DrawerTitle>Details</DrawerTitle> </DrawerContent> </Drawer> </main> ); }
Package version 2.0.1.
Props
Prop
Type
Accessibility
Modal drawers use Vaul / Radix Dialog: focus lands on the panel itself on open (never a field, never a text selection) so the focus trap engages; initialFocus (a ref or a selector) opts a field in, with the caret at the end. Escape to close and focus returns to the trigger; rest of the page is hidden from assistive tech while open (role="dialog"). modal={false} (and matching DrawerContent) renders a kit inline panel with Surface styling—not Vaul/Radix—so the page stays pointer- and keyboard-reachable, without aria-hidden on siblings; mount autofocus stays off, Escape still closes and returns focus to the trigger. Provide DrawerTitle (and DrawerDescription when the panel needs context). Use DrawerCloseButton (44px touch target) plus DrawerHandle for swipe-down; the handle hides itself on left and right drawers and moves to the bottom edge of a top drawer. Every direction closes by dragging toward its edge, tapping the dimmed area, or pressing Escape on modal drawers. Safe-area insets are respected, and fields inside a drawer stay at 16px on touch screens. Sticky DrawerHeader / DrawerFooter keep title and actions visible; DrawerBody scrolls with overscroll-behavior: contain.
Troubleshooting
Dim overlay missing after `shadcn add` — install the drawer registry item (it injects the `--overlay` token) or add the token to your theme. `direction="right"` with default `mobile="sheet"` becomes a bottom sheet under 640px; pass `mobile="side"` to keep a full-height side panel on phones (up to 90% of the width, so the dimmed page stays tappable).