How to build an accessible BottomSheet in React
Renders role="dialog" with aria-modal; the title labels it via aria-labelledby and the description via aria-describedby. FocusScope traps Tab focus and restores it on close; DismissableLayer handles Escape and outside-pointer dismissal. The grab handle is a labelled separator and a Close button gives a non-gesture dismissal path so the sheet stays keyboard-operable.
When to use a BottomSheet
- A mobile surface that rises from the bottom and can be resized between detents by dragging
- Showing secondary content, filters, or a form where the user can peek at half height then expand
- A touch-first overlay that dismisses by flinging or dragging it down past the lowest detent
When not to use it
- A short yes/no confirmation — use AlertDialog
- A non-resizable edge panel without gestures — use Drawer or Sheet
- A desktop-first side panel for navigation — use Drawer
Keyboard interactions
Role dialog, verified at WCAG 2.2-AA.
EscapeTabShift+Tab
Common mistakes
Avoid: <BottomSheet title="Delete item?">Are you sure?</BottomSheet>
Prefer: <AlertDialog title="Delete item?" />
A resizable gesture surface is overkill for a focused yes/no decision
Example
<BottomSheet open={isOpen} onOpenChange={setIsOpen} title="Filters">
<FilterForm />
</BottomSheet>