HeroUI Pro

Sheet

A bottom sheet overlay with snap points, swipe-to-dismiss, and placement options for mobile-friendly dialogs.

Usage

Backdrop Variants

Controlled

Detached

Emoji Picker Sheet

Handle Only

Nested

Non Dismissable

Placements

Professions Picker

Scrollable Content

Slack Message Actions

Snap Points

Snap Points Custom Fade

Snap Points Sequential

With Form

CSS Classes

Base & Variant Classes

  • .sheet__backdrop — Fixed fullscreen overlay behind the sheet. Uses a ::before pseudo-element for the backdrop visual so opacity animations don't affect the panel.
  • .sheet__backdrop--opaque — Solid backdrop using bg-backdrop.
  • .sheet__backdrop--blur — Semi-transparent backdrop with backdrop-blur-sm.
  • .sheet__backdrop--transparent — Fully transparent backdrop.

Content & Placement Classes

  • .sheet__content — The sliding panel container. Fixed position with z-index: 50.
  • .sheet__content--bottom — Anchored to bottom edge with rounded-t-2xl and max-height: 96vh.
  • .sheet__content--top — Anchored to top edge with rounded-b-2xl and max-height: 96vh.
  • .sheet__content--left — Anchored to left edge with rounded-r-2xl and max-width: 96vw.
  • .sheet__content--right — Anchored to right edge with rounded-l-2xl and max-width: 96vw.

Dialog & Layout Classes

  • .sheet__dialog — The visible dialog surface inside the content panel. Has bg-overlay, shadow-overlay, and flex column layout.
  • .sheet__dialog--bottom — Bottom dialog rounding and max-height.
  • .sheet__dialog--top — Top dialog rounding and max-height.
  • .sheet__dialog--left — Left dialog rounding with height: 100%.
  • .sheet__dialog--right — Right dialog rounding with height: 100%.

Element Classes

  • .sheet__header — Flex column container for heading content. Padded with 1rem 1.25rem.
  • .sheet__heading — Title text with text-lg and font-semibold.
  • .sheet__body — Scrollable content area with overflow-y: auto and flex-grow.
  • .sheet__footer — Bottom action bar with flex row layout and gap-0.5rem.
  • .sheet__handle — Drag handle area with grab cursor. Centered with padding.
  • .sheet__handle-bar — The visible pill-shaped bar inside the handle (bg-default, 2rem × 0.3rem).
  • .sheet__close-trigger — Absolutely positioned close button (top-right). Uses text-muted with hover-to-foreground transition.

Interactive States

  • Entering: [data-entering] on [data-sheet-drawer] — triggers slide-in animation per placement direction.
  • Exiting: [data-exiting] on [data-sheet-drawer] — triggers slide-out animation with animation-fill-mode: forwards.
  • Dragging: .sheet-dragging on [data-sheet-drawer] — promotes to compositor layer with will-change: transform.
  • Snap points: [data-sheet-snap-points="true"] — enables JS-driven transforms via --snap-point-height.
  • Detached: [data-sheet-detached] — floats the sheet with 0.5rem inset and full rounded-2xl.
  • Handle hover/active: .sheet__handle:hover / .sheet__handle:active — increases opacity and changes cursor to grabbing.
  • Close trigger hover: .sheet__close-trigger:hover — changes from text-muted to text-foreground.
  • Close trigger focus: .sheet__close-trigger[data-focus-visible="true"] — applies focus ring.
  • Reduced motion: @media (prefers-reduced-motion: reduce) — near-zero animation/transition durations.

CSS Variables

  • --sheet-backdrop-opacity — JS-driven backdrop opacity for snap-point mode.
  • --initial-transform — Starting transform for slide animations (default: 100%). Detached mode uses calc(100% + 8px).
  • --snap-point-height — Current snap-point offset in pixels, set by JS.

Keyframes

  • sheet-fadeIn / sheet-fadeOut — Backdrop opacity fade.
  • sheet-slideFromBottom / sheet-slideToBottom — Bottom placement slide.
  • sheet-slideFromTop / sheet-slideToTop — Top placement slide.
  • sheet-slideFromLeft / sheet-slideToLeft — Left placement slide.
  • sheet-slideFromRight / sheet-slideToRight — Right placement slide.

API Reference

Sheet

The root provider that manages open state, drag behavior, snap points, and nested sheets.

PropTypeDefaultDescription
isOpenbooleanControlled open state.
defaultOpenbooleanfalseInitial open state (uncontrolled).
onOpenChange(open: boolean) => voidCallback when open state changes.
placement"top" | "bottom" | "left" | "right""bottom"Which edge the sheet slides from.
isDismissablebooleantrueWhether clicking outside or dragging can close the sheet.
isDetachedbooleanfalseFloat the sheet away from the viewport edge with rounded corners on all sides.
isModalbooleantrueWhether the sheet renders as a modal overlay.
isNestedbooleanWhether this sheet is nested inside another sheet.
isHandleOnlybooleanfalseRestrict dragging to the handle element only.
snapPoints(number | string)[]Array of snap point heights.
activeSnapPointnumber | string | nullControlled active snap point.
onActiveSnapPointChange(snapPoint: number | string | null) => voidCallback when active snap point changes.
fadeFromIndexnumberLast snap indexIndex from which backdrop begins fading.
closeThresholdnumber0.25Fraction of visible height that triggers close on release.
shouldScaleBackgroundbooleanfalseScale the page background when the sheet opens.
onDrag(event: PointerEvent, percentageDragged: number) => voidCallback during drag.
onRelease(event: PointerEvent, open: boolean) => voidCallback when drag ends.
onClose() => voidCallback when the sheet closes.
onAnimationEnd(open: boolean) => voidCallback after open/close animation completes.
shouldAutoFocusbooleanfalseWhether to auto-focus the first focusable element.

Sheet.Trigger

Renders its child element and opens the sheet when pressed.

PropTypeDefaultDescription
childrenReactElementA single pressable element. Receives an injected onPress handler.

Sheet.Close

Renders its child element and closes the sheet when pressed.

PropTypeDefaultDescription
childrenReactElementA single pressable element. Receives an injected onPress handler.

Sheet.Backdrop

The fullscreen overlay behind the sheet. Must wrap Sheet.Content.

PropTypeDefaultDescription
variant"opaque" | "blur" | "transparent""opaque"Backdrop visual style.

Also supports all RAC ModalOverlay props (except isOpen and onOpenChange, which are managed by Sheet).

Sheet.Content

The sliding panel element. Must be placed inside Sheet.Backdrop.

Also supports all RAC Modal props (except isOpen and onOpenChange).

Sheet.Dialog

The visible dialog surface inside the content panel. Provides aria-labelledby wiring with Sheet.Heading.

Also supports all RAC Dialog props.

Sheet.Header

Flex column container for the heading area. Renders a plain <div>.

Sheet.Heading

Title text with automatic aria-labelledby wiring to the parent Sheet.Dialog.

Also supports all RAC Heading props.

Sheet.Body

Scrollable content area with flex-grow and overflow-y: auto. Renders a plain <div>.

Sheet.Footer

Bottom action bar. Renders a flex row <div> with end-aligned items.

Sheet.Handle

A draggable handle element for swipe interactions. Clicking it cycles through snap points or closes the sheet.

PropTypeDefaultDescription
preventCyclebooleanfalseDisable snap-point cycling on click.

Sheet.CloseTrigger

An × close button absolutely positioned in the top-right corner.

Also supports all HeroUI CloseButton props.

Sheet.NestedRoot

A nested sheet that must be placed inside another Sheet. Automatically manages parent scaling and displacement animations.

Accepts the same props as Sheet (the root provider).

On this page