BottomSheet
Present draggable bottom sheets with optional peek handle and collapsed snap point.
BottomSheet is a client component built on vaul that slides a draggable panel up from the bottom of the viewport. Use it for filters, details and short tasks on mobile-first layouts. It supports controlled and uncontrolled use, a peek handle while closed, and an optional collapsed snap point.
Import#
import { BottomSheet } from "@reactberry/system/blocks";
Usage#
import { useState } from "react";
import { BottomSheet } from "@reactberry/system/blocks";
import { Box, Button, Text } from "@reactberry/system/elements";
export default function Filters() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button variant="default" onClick={() => setIsOpen(true)}>
Filters
</Button>
<BottomSheet open={isOpen} onOpenChange={setIsOpen} title="Filters" peekHeight={0} showCloseButton>
<Box p="m">
<Text>Sheet content</Text>
</Box>
</BottomSheet>
</>
);
}
Examples#
Collapsed snap point#
Set collapsedHeight to add a collapsed snap point; drag the handle up to expand. peekContent is shown at the collapsed point. With showBackdrop={false} the page stays interactive, and showBackdropWhenExpanded adds a backdrop only when expanded.
Explicit close#
Set closeOnBackdropClick={false} and closeOnEscape={false} so the sheet closes only through its buttons or by dragging it down.
API#
BottomSheet#
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Sheet body, rendered in a scrollable area below the header. |
title | ReactNode | — | Header title, also used as the accessible title. Without it, a visually hidden "Bottom sheet" title is rendered. |
description | ReactNode | — | Accessible description. It is visually hidden. |
peekContent | ReactNode | — | Content shown in the header. With |
open | boolean | — | Controlled open state. |
defaultOpen | boolean | true | Initial open state when uncontrolled. |
defaultCollapsed | boolean | false | Opens at the collapsed snap point instead of the expanded one. Requires |
onOpenChange | ((open: boolean) => void) | — | Called with the new open state. |
onClose | (() => void) | — | Called when the sheet closes. |
peekHeight | number | 44 | Height in pixels of the fixed handle shown at the bottom of the viewport while closed. |
collapsedHeight | string | number | — | Enables a collapsed snap point at this height. Numbers are pixels. |
expandedSnapPoint | string | number | — | Expanded snap point used with |
height | string | 28rem | Fixed panel height, used when neither |
maxHeight | string | — | When supplied, the panel sizes to its content and is capped at
this value instead of taking the fixed |
maxWidth | string | 30rem | Maximum width of the panel. |
zIndex | number | 10000 | Stacking order of the sheet. The backdrop uses |
showBackdrop | boolean | true | Renders a backdrop and makes the sheet modal. When |
showBackdropWhenExpanded | boolean | false | With |
backdropBlur | string | 8px | Backdrop blur. |
closeOnBackdropClick | boolean | true | Closes the sheet when the backdrop is clicked. |
closeOnEscape | boolean | true | Closes the sheet when Escape is pressed. |
showCloseButton | boolean | false | Renders a close button in the header. |
children is rendered in a scrollable area below the header. No other props are accepted and nothing is spread.
Keyboard#
| Key | Action |
|---|---|
Escape | Closes the sheet, unless `closeOnEscape` is `false`. |
Accessibility#
- The panel is a vaul
Drawer.ContentwithDrawer.TitleandDrawer.Description. A stringtitleis the accessible title; withouttitle, a visually hidden "Bottom sheet" title is rendered.descriptionis visually hidden and only read by assistive technology. - Focus is not moved into the sheet when it opens.
- The close button has
aria-label="Close sheet". The peek handle is abuttonlabelled"Open " + titlefor a string title, otherwise "Open bottom sheet".
Notes#
defaultOpenistrue, so an uncontrolled sheet opens on mount. Passopen={false}ordefaultOpen={false}to start closed.- While closed, a handle
buttonis fixed to the bottom of the viewport unlesspeekHeightis0. - With
collapsedHeight, the sheet is unmounted while closed. - Passing
maxHeightmakes the panel size to its content up to that value instead of using the fixedheight. It is ignored whencollapsedHeightis set. - The sheet can always be dragged down to close, even with
closeOnBackdropClickandcloseOnEscapeset tofalse.