Basic
A single sheet with no snap points. That puts it in content mode, where the sheet takes the height of its own content. Drag it down far enough and it closes. Clicking the overlay closes it too.
tsx
import { useState } from "react";
import { Sheet } from "snap-bottom-sheet/react";
// `frame` is the box this demo runs in: it is passed to
// `Sheet.Portal container`, so the sheet stays inside the box instead of
// covering the page. Leave `container` out and the sheet portals to <body>.
function Basic({ frame }: { frame: HTMLElement }) {
const [open, setOpen] = useState(false);
return (
<div className="demo-page">
<button
type="button"
className="demo-button"
onClick={() => setOpen(true)}
>
Open the sheet
</button>
<Sheet open={open} onOpenChange={setOpen}>
<Sheet.Portal container={frame}>
<Sheet.Overlay className="demo-overlay" />
<Sheet.Content className="demo-sheet">
<Sheet.Handle className="demo-handle" />
<Sheet.Header className="demo-header">
<Sheet.Title className="demo-title">Content mode</Sheet.Title>
<Sheet.Description className="demo-description">
No snap points, so the sheet hugs its own height.
</Sheet.Description>
</Sheet.Header>
<Sheet.Body className="demo-body">
<p>Drag it down past the threshold to dismiss it.</p>
<Sheet.Close className="demo-button">Close</Sheet.Close>
</Sheet.Body>
</Sheet.Content>
</Sheet.Portal>
</Sheet>
</div>
);
}This demo is modal
It runs with the default modal, and the page you are reading still scrolls. When Sheet.Portal has a container, the scroll lock covers that container instead of the document. The sheet is then modal inside its own box. Only the frame's children are marked inert, Escape still closes the sheet, and the rest of the page is left alone. See Accessibility.