Sheet
Sheet is a view that presents content as a modal sheet. Sheets slide up from the bottom of the screen and are commonly used for presenting forms, settings, or additional content. When `presentationStyle="fullScreen"`, the same component maps to SwiftUI's `.fullScreenCover()` mental model on the web.
Sheet is a view that presents content as a modal sheet. Sheets slide up from the bottom of the screen and are commonly used for presenting forms, settings, or additional content. When `presentationStyle="fullScreen"`, the same component maps to SwiftUI's `.fullScreenCover()` mental model on the web.
Examples
Basic Usage
Preview unavailable for this example in the static docs build.
Show code
function DefaultSheet() {
const [isPresented, setIsPresented] = useState(false)
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Sheet</Button>
<Sheet isPresented={isPresented} onDismiss={() => setIsPresented(false)}>
<VStack spacing={20}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Sheet Title</Text>
<Text>This is a sheet presentation</Text>
<Button onClick={() => setIsPresented(false)}>Dismiss</Button>
</VStack>
</Sheet>
</>
)
}Form Sheet
Preview unavailable for this example in the static docs build.
Show code
function FormSheetComponent() {
const [isPresented, setIsPresented] = useState(false)
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Form Sheet</Button>
<Sheet
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
presentationStyle="formSheet"
>
<VStack spacing={20}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Form Sheet</Text>
<Text>This is a form sheet style</Text>
<Button onClick={() => setIsPresented(false)}>Close</Button>
</VStack>
</Sheet>
</>
)
}Full Screen
Preview unavailable for this example in the static docs build.
Show code
function FullScreenSheet() {
const [isPresented, setIsPresented] = useState(false)
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Full Screen</Button>
<Sheet
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
presentationStyle="fullScreen"
showDragIndicator={false}
>
<VStack spacing={20} style={{ padding: '20px' }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Full Screen</Text>
<Text>This is a full screen presentation</Text>
<Button onClick={() => setIsPresented(false)}>Close</Button>
</VStack>
</Sheet>
</>
)
}Presentation Styling
Preview unavailable for this example in the static docs build.
Show code
function MaterialSheet() {
const [isPresented, setIsPresented] = useState(false)
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Material Sheet</Button>
<Sheet
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
backgroundStyle="thinMaterial"
cornerRadius={28}
>
<VStack spacing={20} style={{ padding: '20px' }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Material Sheet</Text>
<Text>Thin material background with a custom corner radius.</Text>
<Button onClick={() => setIsPresented(false)}>Dismiss</Button>
</VStack>
</Sheet>
</>
)
}Background Interaction
Preview unavailable for this example in the static docs build.
Show code
function LockedBackdropSheet() {
const [isPresented, setIsPresented] = useState(false)
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Locked Sheet</Button>
<Sheet
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
backgroundInteraction="none"
>
<VStack spacing={20} style={{ padding: '20px' }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Locked Backdrop</Text>
<Text>Backdrop taps no longer dismiss this sheet.</Text>
<Button onClick={() => setIsPresented(false)}>Close explicitly</Button>
</VStack>
</Sheet>
</>
)
}Presentation Detents
Preview unavailable for this example in the static docs build.
Show code
function DetentSheet() {
const [isPresented, setIsPresented] = useState(false)
const [selectedDetent, setSelectedDetent] = useState<'medium' | 'large'>('medium')
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Detent Sheet</Button>
<Sheet
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
presentationDetents={['medium', 'large']}
selectedDetent={selectedDetent}
onSelectedDetentChange={(detent) => {
if (detent === 'medium' || detent === 'large') {
setSelectedDetent(detent)
}
}}
>
<VStack spacing={20} style={{ padding: '20px' }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Detent Sheet</Text>
<Text>This sheet starts at the medium detent and cycles when you activate the drag indicator.</Text>
<Text>Current detent: {selectedDetent}</Text>
<Button onClick={() => setIsPresented(false)}>Dismiss</Button>
</VStack>
</Sheet>
</>
)
}Uncontrolled Detents
Preview unavailable for this example in the static docs build.
Show code
function UncontrolledDetentSheet() {
const [isPresented, setIsPresented] = useState(false)
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Uncontrolled Detent Sheet</Button>
<Sheet
defaultSelectedDetent="medium"
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
presentationDetents={['medium', 'large']}
>
<VStack spacing={20} style={{ padding: '20px' }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Uncontrolled Detent Sheet</Text>
<Text>This sheet resets to its default detent each time it is presented.</Text>
<Button onClick={() => setIsPresented(false)}>Dismiss</Button>
</VStack>
</Sheet>
</>
)
}Interactive Dismiss
Preview unavailable for this example in the static docs build.
Show code
function InteractiveDismissDisabledSheet() {
const [isPresented, setIsPresented] = useState(false)
return (
<>
<Button onClick={() => setIsPresented(true)}>Show Locked Interaction Sheet</Button>
<Sheet
isPresented={isPresented}
onDismiss={() => setIsPresented(false)}
interactiveDismissDisabled
>
<VStack spacing={20} style={{ padding: '20px' }}>
<Text style={{ fontSize: 24, fontWeight: 'bold' }}>Interactive Dismiss Disabled</Text>
<Text>Backdrop taps and Escape no longer dismiss this presentation.</Text>
<Button onClick={() => setIsPresented(false)}>Close explicitly</Button>
</VStack>
</Sheet>
</>
)
}API
| Prop | Type | Required | Description |
|---|---|---|---|
isPresented | boolean | Yes | Whether the sheet is presented |
onDismiss | () => void | No | Callback when sheet is dismissed |
presentationStyle | 'pageSheet' | 'formSheet' | 'fullScreen' | No | Sheet presentation style Default: 'pageSheet' |
showDragIndicator | boolean | No | Whether to show drag indicator Default: true |
backgroundInteraction | 'dismiss' | 'none' | No | Whether interacting with the backdrop dismisses the sheet. Default: 'dismiss' |
backgroundStyle | 'automatic' | 'thinMaterial' | 'regularMaterial' | 'clear' | No | Visual background treatment for the presented sheet. Default: 'automatic' |
cornerRadius | number | string | No | Overrides the sheet corner radius. |
presentationDetents | IPresentationDetent[] | No | Available detents for the sheet height. Default: ['large'] |
selectedDetent | IPresentationDetent | No | Currently selected detent. |
defaultSelectedDetent | IPresentationDetent | No | Initial detent when used in uncontrolled mode. |
onSelectedDetentChange | (detent: IPresentationDetent) => void | No | Called when the selected detent changes. |
interactiveDismissDisabled | boolean | No | Prevents interactive dismiss affordances like backdrop tap and Escape. Default: false |
Inherits additional props from IBaseComponent.
Overview
Sheet is a view that presents content as a modal sheet. Sheets slide up from the bottom of the screen and are commonly used for presenting forms, settings, or additional content. When presentationStyle="fullScreen", the same component maps to SwiftUI's .fullScreenCover() mental model on the web.
SwiftUI Correspondence: Similar to SwiftUI's .sheet() modifier.
Form Sheet
Use form sheet style for forms and input:
Full Screen
Present content in full screen:
Presentation Styling
Customize material treatment and corner radius:
Background Interaction
Prevent backdrop taps from dismissing the sheet:
Presentation Detents
Configure the available sheet heights and choose the initial detent. When more than one detent is available, the drag indicator becomes an explicit control that can cycle between them:
Uncontrolled Detents
Use defaultSelectedDetent when the sheet should reset to a known starting detent each time it is presented:
Interactive Dismiss
Disable backdrop and keyboard dismissal when the presentation must stay locked until an explicit action:
Notes
- Sheet requires
isPresentedandonDismissprops - Sheet supports different presentation styles
- Sheet automatically handles dismiss gestures
defaultSelectedDetentresets uncontrolled detent state on each new presentation- Use Sheet for modal presentations
- Sheet can contain any React content
Best Practices
- Dismiss handling: Always provide
onDismisshandler - Presentation style: Choose appropriate style for your content
- Drag indicator: Show drag indicator for better UX
- Content: Keep sheet content focused and concise
- Accessibility: Ensure sheet content is accessible and keyboard navigable
ShareLink
ShareLink presents a platform share action. On the web it uses the Web Share API when available and falls back to opening shareable URLs.
Slider
Slider is a control for selecting a value from a bounded linear range of values. Slider is built on a native `<input type="range">`, so it keeps standard keyboard support, focus behavior, and form participation.