Sheet

Side drawer panel.

Usage

A Sheet is a Dialog anchored to an edge — it is not a separate primitive. It composes Bits Dialog, so the focus trap, ESC handling, scroll lock and ARIA all come from there rather than being reimplemented. Title is required, because Bits points aria-labelledby at it.

Sides

side pins the panel to an edge and spans the perpendicular axis. right is the default because it is the least disruptive on desktop; bottom is usually the right call on mobile, where the thumb is.

Sizes

size applies to whichever axis the panel actually grows along — width for left/right, height for top/bottom. Every size is capped against the viewport, so a large sheet still fits on a small screen.

Sheet vs Dialog

Same mechanics, different intent. Use a Dialog for a focused, self-contained task the user finishes and leaves. Use a Sheet for a secondary surface they move through and refer back to — a nav drawer, a filter panel, a detail pane. The edge anchoring is what signals "this sits beside your work" rather than "this interrupts it".

Props

Root, Trigger and Close are re-exported from Bits Dialog unchanged — open is bindable on Root.

Sheet.Content

PropTypeDefault
side Which edge the panel slides in from.'left' | 'right' | 'top' | 'bottom''right'
size Panel thickness — width for left/right, height for top/bottom.'sm' | 'md' | 'lg''md'
class Extra classes merged onto the panel.string
child bits-ui Snippet<[DialogContentSnippetProps & { props: Record<string, unknown>; }]> | undefined
children bits-ui Snippet<[]> | undefined
escapeKeydownBehavior bits-ui Escape behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to its parent component that has an escape keydown handler. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an escape key press.EscapeBehaviorType | undefined`close`
forceMount bits-ui Whether to force mount the component.boolean | undefined
id bits-ui string | undefined
interactOutsideBehavior bits-ui Interact outside behavior type. `close`: Closes the element immediately. `defer-otherwise-close`: Delegates the action to the parent element. If no parent is found, it closes the element. `defer-otherwise-ignore`: Delegates the action to the parent element. If no parent is found, nothing is done. `ignore`: Prevents the element from closing and also blocks the parent element from closing in response to an outside interaction.InteractOutsideBehaviorType | undefined`close`
onCloseAutoFocus bits-ui Event handler called when auto-focusing on close. Can be prevented.EventCallback | undefined
onEscapeKeydown bits-ui Callback fired when escape is pressed.((e: KeyboardEvent) => void) | undefined
onFocusOutside bits-ui Callback fired when focus leaves the dismissible layer.((event: FocusEvent) => void) | undefined
onInteractOutside bits-ui Callback fired when an outside interaction event completes, which is either a `pointerup`, `mouseup`, or `touchend` event, depending on the user's input device.InteractOutsideEventHandler | undefined
onOpenAutoFocus bits-ui Event handler called when auto-focusing on open. Can be prevented.EventCallback | undefined
preventOverflowTextSelection bits-ui Passing `true` will prevent the overflow of text selection outside the element, provided the element is the top layer.boolean | undefined`true`
preventScroll bits-ui Whether to prevent body scrolling when the content is open.boolean | undefinedtrue
ref bits-ui HTMLElement | null | undefined
restoreScrollDelay bits-ui The delay in milliseconds before the scrollbar is restored after closing the dialog. This is only applicable when using the `child` snippet for custom transitions and `preventScroll` is `true`. You should set this to a value greater than the transition duration to prevent content from shifting during the transition.number | null | undefinednull
trapFocus bits-ui Whether focus is trapped within the focus scope.boolean | undefinedfalse

Title, Description and Overlay each take class plus their native attributes.