Sheet

Loading...

Installation

Install the component via the CLI in one command.

npx shadcn@latest add @intentui/sheet

Composed components

When you install this component via the CLI, it automatically loads all composed components, so you don’t need to add them individually.

Manual installation

Use this approach if you prefer to install and wire up the component yourself instead of using the CLI.

npm install react-aria-components cn tailwind-variants

Add the backdrop and stacking animations to your global CSS. @theme static keeps their keyframes available for React Aria’s swipe and stack animations.

@theme static {
  --animate-sheet-backdrop: sheet-backdrop 300ms linear both;
  --animate-sheet-scale-back: sheet-scale-back 300ms ease-out both;

  @keyframes sheet-backdrop {
    from { opacity: 0; }
    to { opacity: 1; }
  }

  @keyframes sheet-scale-back {
    to { transform: translate(var(--sheet-stack-x, 0px), var(--sheet-stack-y, 0px)) scale(0.95); }
  }
}

@supports not (animation-timeline: view()) {
  .react-aria-sheet[data-has-descendants] {
    transform: translate(var(--sheet-stack-x, 0px), var(--sheet-stack-y, 0px)) scale(0.95);
  }
}

sheet-backdrop animates the backdrop opacity from 0 to 1. React Aria uses it through swipeAnimation to keep the fade synchronized with the sheet’s movement.

sheet-scale-back scales the sheet behind to 0.95 and offsets it by 8px toward the opposite edge. SheetContent sets --sheet-stack-x or --sheet-stack-y based on its position. The smaller offset keeps the close button behind the front sheet. The @supports rule provides the stacked appearance in browsers without view timelines.

Anatomy

import { Button } from "@/components/ui/button"
import {
  Sheet,
  SheetBody,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from "@/components/ui/sheet"
<Sheet>
  <SheetTrigger>Open</SheetTrigger>
  <SheetContent position="right">
    <SheetHeader>
      <SheetTitle>Sheet Title</SheetTitle>
      <SheetDescription>Sheet Description</SheetDescription>
    </SheetHeader>
    <SheetBody>Sheet Body</SheetBody>
    <SheetFooter>
      <SheetClose>Cancel</SheetClose>
      <Button>Save</Button>
    </SheetFooter>
  </SheetContent>
</Sheet>

Examples

This example is like Github's profile page. You can see the sheet component is used to display the profile information.

Loading...

Stacking

Nest a Sheet inside another sheet to open a new panel on top. The sheet behind moves back as the next sheet opens. Each sheet has its own close action, so closing the top sheet returns you to the previous one. This example uses three levels: workspace settings, team access, and member permissions.

Loading...

Controlled

You can control the open state of the sheet by using the isOpen prop. You can also use the onOpenChange prop to listen to the open state change.

Loading...

Positioning

Use the position prop to place the sheet at bottom, top, left, right, start, end, or center. The default is bottom. The start and end positions follow the text direction.

Loading...

Snap points

Set snapPoints to control how much of the sheet is visible at each stop. Numbers are pixels; percentages are relative to the sheet’s size. The sheet opens at the first snap point. Set an explicit height for a bottom or top sheet when using percentage snap points.

Loading...

Prevent dismissal

Set preventDismissal to prevent closing by swiping, pressing Escape, or interacting outside. A SheetClose action can still close the sheet. This defaults to false.

Loading...

Custom close

Sheets do not include a built-in close icon. Dismissible bottom sheets show a handle outside the content without changing the header spacing. You can customize the close button by using the SheetClose component. This example demonstrates how to use the SheetClose component to create a custom close button.

Loading...

Float

By default, the sheet floats with a gap from the viewport edges and rounded corners. Set isFloat={false} to make it sit flush against the viewport edge.

Loading...

Sticky

Use SheetBody for scrollable content while keeping the header and footer visible.

Loading...

Component API

Sheet

Sheet extends the React Aria Components <SheetTrigger> component.

SheetTrigger

SheetTrigger extends the Intent UI <DialogTrigger> component.

classNamestring

SheetContent

Requires react-aria-components 1.22.0 or later. Use preventDismissal in place of the previous modal props isDismissable and isKeyboardDismissDisabled.

SheetContent extends the React Aria Components <SheetOverlay>, and composes React Aria’s SheetBackdrop, Sheet, and SheetContent component.

classNamestring
isFloatboolean
Default: true
overlayOmit<SheetOverlayProps, "children" | "position">
snapPointsArray<number | string>
swipeDirection"top" | "bottom" | "left" | "right" | "start" | "end" | "vertical" | "horizontal"
preventDismissalboolean
Default: false (true for alertdialog)
position"bottom" | "top" | "left" | "right" | "start" | "end" | "center"
Default: bottom

SheetHeader

SheetHeader extends the Intent UI <DialogHeader> component.

classNamestring
descriptionstring
titlestring

SheetTitle

SheetTitle extends the Intent UI <DialogTitle> component.

classNamestring

SheetDescription

SheetDescription extends the Intent UI <DialogDescription> component.

classNamestring

SheetBody

SheetBody extends the Intent UI <DialogBody> component.

classNamestring

SheetFooter

SheetFooter extends the Intent UI <DialogFooter> component.

classNamestring

SheetClose

SheetClose extends the Intent UI <DialogClose> component.

classNamestring
intent"primary" | "secondary" | "warning" | "danger" | "success" | "outline" | "plain"
Default: plain

See the React Aria for the full API reference.

Design