Marble UI
← Components

Sheet (side panel)

Preview: Right

Modal panel that slides in from an edge (no swipe gestures). Use Drawer for swipeable, snap-point sheets.

Import

import { Sheet, SheetTrigger } from '@marbleui/ui'

Props

<Sheet>

PropTypeDefaultDescription
children *requiredReactNode—
descriptionReactNode—
footerReactNode—
overlayPropsOmit<ModalOverlayProps, 'children'>—
sideSide'right'
titleReactNode—

Also accepts React Aria props (81).

<SheetTrigger>alias of DialogTrigger

Re-exported from React Aria DialogTrigger; see its documentation for props.

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Dialog · React Aria DialogTrigger · React Aria Heading · React Aria Modal · React Aria ModalOverlay. Follow the primitive's docs for the full keyboard map.

Usage notes

Modal panel sliding in from an edge for detail views and forms that need more room than a dialog.

<SheetTrigger>
  <Button>Edit</Button>
  <Sheet side="right" title="Edit issue" footer={<Button>Save</Button>}>…</Sheet>
</SheetTrigger>
  • title is required in practice: it names the dialog.
  • No swipe gestures; use Drawer for touch-first, swipe-to-dismiss and snap points.
Example source · show
import { Button } from '../button'
import { Switch } from '../switch'
import { TextField } from '../text-field'
import { Sheet, SheetTrigger } from './sheet'

export const styles = {
  Right: () => (
    <SheetTrigger>
      <Button variant="outline">Edit profile</Button>
      <Sheet title="Edit profile" description="Changes are visible to your team." footer={<Button slot="close">Save</Button>}>
        <div className="flex flex-col gap-4">
          <TextField label="Name" defaultValue="Maya Chen" />
          <TextField label="Title" defaultValue="Design Engineer" />
          <Switch defaultSelected>Show email on profile</Switch>
        </div>
      </Sheet>
    </SheetTrigger>
  ),
  Left: () => (
    <SheetTrigger>
      <Button variant="outline">Open navigation</Button>
      <Sheet side="left" title="Acme">
        <nav className="flex flex-col gap-1 text-fg">
          {['Home', 'Projects', 'Team', 'Settings'].map((l) => (
            <a key={l} href="#" className="rounded-md px-2 py-1.5 hover:bg-surface-muted">{l}</a>
          ))}
        </nav>
      </Sheet>
    </SheetTrigger>
  ),
  Bottom: () => (
    <SheetTrigger>
      <Button variant="outline">Cookie settings</Button>
      <Sheet side="bottom" title="Cookies" description="Choose which cookies we may use." footer={<Button slot="close">Done</Button>}>
        <div className="mx-auto flex max-w-lg flex-col gap-3">
          <Switch isDisabled defaultSelected>Necessary</Switch>
          <Switch>Analytics</Switch>
          <Switch>Marketing</Switch>
        </div>
      </Sheet>
    </SheetTrigger>
  ),
}

Source: packages/ui/src/sheet/sheet.tsx

Catalog

Category
overlays
Priority
Core
Primitive
react-aria
React Aria
Modal + Dialog
Base UI
Dialog