An edge panel that keeps the list behind it in view — quick edit, record preview, mobile filters and navigation. Logical sides, four widths, an inset floating style, a non-modal preview mode, and a Drawer that closes by dragging down.
Installation
The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";
Usage
import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetBody, SheetFooter, Button } from "@vamos-ui/react";
<Sheet>
<SheetTrigger asChild><Button>Quick edit</Button></SheetTrigger>
<SheetContent side="end" size="md">
<SheetHeader title="Edit contact" />
<SheetBody>…</SheetBody>
<SheetFooter>…</SheetFooter>
</SheetContent>
</Sheet>Blur turns off while dragging (data-dragging), following the glass budget.
A docked, resizable preview column belongs to Record detail / List layout, not to Sheet.
Examples
Sides
start / end are logical and flip in RTL. inset floats the panel with an 8px gutter.
Record preview (CRM)
modal={false}: no overlay or focus trap, the list stays clickable and switching rows updates the panel. Esc still closes.
Filters as a bottom sheet
side="bottom" fits its content up to the size cap; the footer keeps the result count visible.
Drawer
Drag the handle or header down to close. Drags never start on controls or inside a scrolled body; Esc and × always work.
API
Sheet / Drawer
| Prop | Type | Default |
|---|---|---|
open / defaultOpen / onOpenChangeSame as Dialog. | boolean / boolean / (open) => void | — |
modalfalse → page stays interactive, no overlay, outside clicks don't close (aria-modal="false"). | boolean | true |
SheetContent
| Prop | Type | Default |
|---|---|---|
sideLogical edge. left / right are accepted as aliases of start / end. | "start" | "end" | "top" | "bottom" | "end" |
sizestart/end width: 360 / 440 / 560 / 720 px. top/bottom height cap: 40 / 60 / 75 / 85 % of the viewport. | "sm" | "md" | "lg" | "xl" | "full" | "md" |
inset8px gutter and full radius — a floating panel. | boolean | false |
dismissible / onBeforeClose / hideClose / container / labelsShared layer behaviour. | as DialogContent | — |
DrawerContent
| Prop | Type | Default |
|---|---|---|
dragToDismissClose by dragging down past 30% of the height, or with a quick flick. | boolean | true |
handleShow the grab handle (aria-hidden). | boolean | true |
sizeHeight cap. | SheetContent size | "lg" |
Parts
| Prop | Type | Default |
|---|---|---|
SheetHeader / SheetBody / SheetFooterSame API as the Dialog parts. | LayerHeader / LayerBody / LayerFooter | — |
DrawerHeader / DrawerBody / DrawerFooter / DrawerHandleDrawer variants; DrawerBody marks the scroll area for drag handling. | layout parts | — |
SheetTrigger / SheetClose / DrawerTrigger / DrawerCloseUse asChild with a Button. | Radix parts | — |
useDragDismiss()The pointer logic, for custom bottom panels. | ({ onDismiss, threshold?, velocity?, enabled? }) => { ref, handlers } | — |