suiss/ui · Component
Sheet
A panel that slides in from an edge of the screen over the page.
Sheet is an open-source component from suiss/ui for React, React Native, SwiftUI and Jetpack Compose. The @esuiss/ui CLI copies its source into your project, so you own the code.
Sheet is built on the dialog primitive of the chosen base. SheetTrigger opens it, and SheetContent renders the panel in a portal over a dimming backdrop. Inside, SheetHeader holds a SheetTitle and SheetDescription, and SheetFooter holds actions. SheetClose closes the sheet from any element.
The panel floats inset from the screen edge with rounded corners and slides in from its side. Use a sheet for supporting tasks, such as editing details or showing navigation, that should keep the page in context. For short, centered confirmations, use Dialog or AlertDialog.
Installation
CLI
Works in any project with a components.json. See Installation for the one-line registry setup. Or use the suiss/ui CLI:
Manual
- Install the dependencies and add the
cnhelper:
-
Add the pieces it builds on: Button,
use-scrollbar-gap. -
Copy the source into
components/ui/sheet.tsx:
- Update the import paths to match your project.
Usage
Use defaultOpen for an uncontrolled sheet, or open with onOpenChange to control it. Use the render prop on SheetTrigger and SheetClose to render them as a Button.
Use defaultOpen for an uncontrolled sheet, or open with onOpenChange to control it. Set asChild on SheetTrigger and SheetClose to render a Button in their place.
Use defaultOpen for an uncontrolled sheet, or isOpen with onOpenChange to control it. The Button placed first inside Sheet opens it, and a Button with slot="close" closes it.
SheetFooter sits at the bottom of the panel with mt-auto. By default SheetContent adds an icon close button in the top corner; set closeLabel to show a text button instead, or showCloseButton={false} to remove it.
Examples
Sides
Opens a sheet from each of the four edges.
Left
Renders a sheet open on the left side.
Bottom
Renders a sheet open along the bottom edge.
Without close button
Removes the built-in close button.
With close label
Replaces the icon close button with a text button labelled Done.
API Reference
Sheet
The root that holds the open state.
Also accepts the props of the primitive part it wraps.
SheetTrigger
The element that opens the sheet.
Also accepts the props of the primitive part it wraps.
SheetClose
An element that closes the sheet when pressed.
Also accepts the props of the primitive part it wraps.
SheetContent
The sliding panel, rendered in a portal with a backdrop.
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" | Chooses the edge the sheet slides in from. |
showCloseButton | boolean | true | Shows the built-in close button in the top corner. |
closeLabel | string | - | Shows this text in the close button instead of an icon. |
Also accepts the props of the primitive part it wraps.
SheetHeader
A padded stack for the title and description.
Also accepts the props of React.ComponentProps<"div">.
SheetFooter
A padded stack for actions, pushed to the bottom of the panel.
Also accepts the props of React.ComponentProps<"div">.
SheetTitle
The sheet's title, which names the dialog.
Also accepts the props of the primitive part it wraps.
SheetDescription
Supporting text, which describes the dialog.
Also accepts the props of the primitive part it wraps.
Accessibility
- The panel has the
dialogrole.SheetTitlegives it an accessible name andSheetDescriptionan accessible description. - Opening the sheet moves focus inside it.
Escapecloses the sheet, and focus returns to the trigger.- The icon close button has the hidden label
Close.
Notes
- Parts carry
data-slotattributes such assheet-content,sheet-overlayandsheet-close; the panel also setsdata-side. - Left and right sheets are 3/4 of the screen wide, up to
max-w-smfrom thesmbreakpoint. Slide directions flip in right-to-left layouts. - The panel uses
bg-popoverand the backdrop usesbg-black/50.

Sheet is built on the drawer primitive. SheetContent renders in a portal, above a dimmed overlay, as a rounded floating panel inset from the screen edges and the safe area. It enters and exits with a Reanimated fade-and-slide from its side and can be dismissed by swiping toward that edge.
Use right or left for navigation and detail panels that span the screen height, and top or bottom for short panels that span the width. For snap points and a drag handle, use Drawer instead.
Installation
The CLI also adds what it builds on: Button, Icon, Text. On React Native it also adds the animated view components/ui/animated-view.tsx.
Manual
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, Text, and the primitives
components/primitives/drawer.tsx,components/primitives/use-render.tsx, and the animated viewcomponents/ui/animated-view.tsxfrom the next step. -
Copy the animated view into
components/ui/animated-view.tsx:
- Copy the source into
components/ui/sheet.tsx:
- Update the import paths to match your project.
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, Text, and the primitives
components/primitives/drawer.tsx,components/primitives/use-render.tsx, and the animated viewcomponents/ui/animated-view.tsxfrom the next step. -
Copy the animated view into
components/ui/animated-view.tsx:
- Copy the source into
components/ui/sheet.tsx:
- Update the import paths to match your project.
- Install the dependencies:
-
Add the pieces it builds on: Button, Icon, Text, and the primitives
components/primitives/drawer.tsx,components/primitives/use-render.tsx, and the animated viewcomponents/ui/animated-view.tsxfrom the next step. -
Copy the animated view into
components/ui/animated-view.tsx:
- Copy the source into
components/ui/sheet.tsx:
- Update the import paths to match your project.
-
Target iOS 17 or later.
-
Add the Swift package to your app:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Add the files to your app target.
- Set
minSdkto 24 or higher and add the dependencies:
- Copy the theme files every view uses:
- Copy the source and every file it uses:
- Update the
com.esuiss.uipackage names to match your project.
Usage
Wrap a SheetTrigger and a SheetContent in Sheet. Inside the content, compose SheetHeader with SheetTitle and SheetDescription, your body, and a SheetFooter, which is pushed to the bottom. Use SheetTrigger and SheetClose with render to turn a Button into a trigger or close control.
Sheet accepts open, defaultOpen and onOpenChange for controlled or uncontrolled use, plus modal, disablePointerDismissal, onOpenChangeComplete and actionsRef. The swipe direction follows the side of its content.
A close button is shown in the top corner by default. Set closeLabel to show a text button instead of the X icon, or showCloseButton={false} to remove it. SheetHeader adds end padding so the title does not run under the button.
Examples
Default

Sides
One sheet for each side: top, right, bottom and left.

With close label
A bottom sheet whose close button reads "Done" instead of showing an icon.

API Reference
Sheet
Root that holds the open state.
Also accepts the props of DrawerPrimitive.RootProps.
SheetContent
The panel, rendered in a portal with an overlay and an optional close button.
| Prop | Type | Default | Description |
|---|---|---|---|
portalHost | string | - | Name of the portal host to render into. |
side | SheetSide | "right" | Edge the sheet slides in from: top, right, bottom or left. Defaults to right. |
showCloseButton | boolean | true | Shows the close button in the top corner. Defaults to true. |
closeLabel | string | - | Text for the close button. When omitted, an X icon is shown. |
Also accepts the props of React.ComponentProps<typeof DrawerPrimitive.Popup>.
SheetHeader
Column for the title and description.
Also accepts the props of ViewProps.
SheetFooter
Column of actions pushed to the bottom of the panel.
Also accepts the props of ViewProps.
SheetTitle
Heading that labels the sheet.
Also accepts the props of React.ComponentProps<typeof DrawerPrimitive.Title>.
SheetDescription
Secondary text under the title.
Also accepts the props of React.ComponentProps<typeof DrawerPrimitive.Description>.
Accessibility
- The panel has the
dialogrole and is labeled bySheetTitlewhen one is present. - It is modal by default, so VoiceOver keeps focus inside the sheet.
- The VoiceOver escape gesture and the Android back button close the sheet.
- The icon-only close button has the accessibility label "Close".
- Animations respect the system reduce motion setting.
Notes
- Uses
bg-popoverfor the panel andbg-black/50for the overlay; colors follow the system appearance. - On iOS the sheet renders inside a
FullWindowOverlayfromreact-native-screens, so it appears above native modals. - Side sheets are three quarters of the screen width, capped at
max-w-smon larger screens.



