Sheet
A panel that slides in from the edge of the screen, typically used for navigation or supplementary content.
The Sheet component is a slide-in panel that appears from any edge of the screen. It supports four sides (top, bottom, left, right), animated transitions with React Native Reanimated, a backdrop overlay, and a compound component API with header, footer, title, description, and close parts.
Preview
Installation
npx novaui-cli add sheetDependencies
The Sheet requires the following peer dependencies:
react-native-reanimated>= 3lucide-react-native>= 0.300
Import
import {
Sheet,
SheetTrigger,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
SheetClose,
} from 'novaui-components'Basic Usage
The Sheet is a compound component with these parts:
Sheet- Root container with open/close stateSheetTrigger- Button that opens the sheetSheetContent- The sliding panel (includes portal and overlay)SheetHeader- Groups the title and descriptionSheetFooter- Groups the action buttonsSheetTitle- The sheet headingSheetDescription- The sheet body textSheetClose- A button that closes the sheet
import {
Sheet,
SheetTrigger,
SheetContent,
SheetHeader,
SheetTitle,
SheetDescription,
} from 'novaui-components'
import { Button } from 'novaui-components'
export function BasicSheet() {
return (
<Sheet>
<SheetTrigger>
<Button variant="outline" label="Open Sheet" />
</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<SheetTitle>Sheet Title</SheetTitle>
<SheetDescription>
This is a sheet that slides in from the right side of the screen.
</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
)
}Side Variants
The sheet can slide in from any edge. Use the side prop on SheetContent:
Right (default)
<Sheet>
<SheetTrigger>
<Button variant="outline" label="Right Sheet" />
</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<SheetTitle>Right Sheet</SheetTitle>
<SheetDescription>Slides in from the right edge.</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>Left
<Sheet>
<SheetTrigger>
<Button variant="outline" label="Left Sheet" />
</SheetTrigger>
<SheetContent side="left">
<SheetHeader>
<SheetTitle>Left Sheet</SheetTitle>
<SheetDescription>Slides in from the left edge.</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>Bottom
<Sheet>
<SheetTrigger>
<Button variant="outline" label="Bottom Sheet" />
</SheetTrigger>
<SheetContent side="bottom">
<SheetHeader>
<SheetTitle>Bottom Sheet</SheetTitle>
<SheetDescription>Slides in from the bottom edge.</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>Controlled State
Control the sheet open/close state programmatically:
import { useState } from 'react'
export function ControlledSheet() {
const [open, setOpen] = useState(false)
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger>
<Button variant="outline" label="Controlled Sheet" />
</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<SheetTitle>Controlled</SheetTitle>
<SheetDescription>
This sheet's state is managed externally.
</SheetDescription>
</SheetHeader>
<SheetFooter>
<SheetClose>
<Button variant="outline" label="Close" />
</SheetClose>
<Button label="Save" onPress={() => setOpen(false)} />
</SheetFooter>
</SheetContent>
</Sheet>
)
}Navigation Sheet
Use a left-side sheet for mobile navigation:
export function NavigationSheet() {
return (
<Sheet>
<SheetTrigger>
<Button variant="outline" label="Menu" />
</SheetTrigger>
<SheetContent side="left">
<SheetHeader>
<SheetTitle>Navigation</SheetTitle>
</SheetHeader>
<View className="flex flex-col gap-2 mt-4">
<Pressable className="px-3 py-2 rounded-md hover:bg-accent">
<Text className="text-sm font-medium text-foreground">Home</Text>
</Pressable>
<Pressable className="px-3 py-2 rounded-md hover:bg-accent">
<Text className="text-sm font-medium text-foreground">Settings</Text>
</Pressable>
<Pressable className="px-3 py-2 rounded-md hover:bg-accent">
<Text className="text-sm font-medium text-foreground">Profile</Text>
</Pressable>
</View>
</SheetContent>
</Sheet>
)
}Props API
Sheet Props
Extends React.ComponentPropsWithoutRef<typeof View> and includes:
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Controlled open state |
onOpenChange | (open: boolean) => void | - | Callback when open state changes |
SheetTrigger Props
Extends React.ComponentPropsWithoutRef<typeof Pressable>:
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as the child element instead of a Pressable |
SheetContent Props
Extends React.ComponentPropsWithoutRef<typeof View>:
| Prop | Type | Default | Description |
|---|---|---|---|
side | 'top' | 'bottom' | 'left' | 'right' | 'right' | Which edge the sheet slides in from |
className | string | - | Additional CSS classes |
SheetHeader Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
SheetFooter Props
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
SheetTitle Props
Extends React.ComponentPropsWithoutRef<typeof Text>:
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
SheetDescription Props
Extends React.ComponentPropsWithoutRef<typeof Text>:
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
SheetClose Props
Extends React.ComponentPropsWithoutRef<typeof Pressable>:
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as the child element instead of a Pressable |
Animation
The Sheet uses react-native-reanimated for entrance/exit animations:
- Overlay: Fades in with
FadeIn/FadeOut - Content: Slides in/out based on the
sideprop (SlideInRight,SlideOutRight, etc.) - Duration: Controlled by Reanimated's default spring/timing configuration
Accessibility
- Uses React Native
Modalfor proper overlay behavior onRequestClosehandles the Android back buttonstatusBarTranslucentensures the overlay covers the full screen- Backdrop press dismisses the sheet
Best Practices
-
Choose the right side: Use
rightfor settings/details,leftfor navigation,bottomfor actions on mobile -
Keep width reasonable: Left and right sheets default to
w-3/4 sm:max-w-sm— don't make them too wide -
Use header and footer: Structure content with
SheetHeaderandSheetFooterfor consistent layouts -
Provide escape routes: The backdrop close and X button are built in — add explicit close buttons in the footer too
-
Don't overload content: Sheets are for focused tasks — use full-screen navigation for complex flows
Related Components
- Use
Dialogfor centered modal content - Use
Drawerfor mobile-optimized bottom sheets with drag gestures - Use
AlertDialogfor confirmation prompts