---
title: Sheet
description: Slide-in panel overlay from any screen edge with structured content slots.
sidebar:
  order: 5
search:
  tags: [drawer, panel, overlay, mobile]
---

# Sheet

> Slide-in panel overlay from any screen edge with structured content slots.

## Import

```tsx
import { Sheet } from 'moraine'
```

## Slot Structure

Wrapper trigger with optional backdrop and a sliding panel with title, body, and footer slots.

```text
trigger
├── overlay (optional)
└── content (portal)
    ├── header (optional)
    │   ├── wrapper (optional)
    │   │   ├── title (optional)
    │   │   └── description (optional)
    │   ├── actions (optional)
    │   └── close (optional)
    ├── body (optional)
    └── footer (optional)
```

## Examples

### Variants

Inset layout with custom close content or hidden close control.

```tsx
function Variants() {
  return (
    <div class="flex flex-wrap gap-3 items-center">
      <Sheet
        inset
        title="Inset sheet"
        close={<span class="text-xs font-semibold">Done</span>}
        body="Inset sheet with custom close content."
      >
        <Button variant="secondary">Inset + custom close</Button>
      </Sheet>

      <Sheet title="No close button" close={false} body="Close button is hidden for this sheet.">
        <Button variant="outline">Close=false</Button>
      </Sheet>
    </div>
  )
}
```

### Sides

Open sheet from each side with shared shell slots.

```tsx
function Sides() {
  const SIDES = ['left', 'right', 'top', 'bottom'] as const

  return (
    <div class="flex flex-wrap gap-3 items-center">
      <For each={SIDES}>
        {(side) => (
          <Sheet
            side={side}
            title={`Sheet ${side}`}
            description={`This sheet opens from ${side}.`}
            body={<p class="text-sm text-foreground">Body content from {side} side.</p>}
          >
            <Button variant="outline" size="sm">
              {side}
            </Button>
          </Sheet>
        )}
      </For>
    </div>
  )
}
```

### Dismiss Control

Prevent close on outside interaction and Escape while counting attempts.

```tsx
function DismissControl() {
  const [preventedCloseCount, setPreventedCloseCount] = createSignal(0)

  return (
    <div class="flex flex-wrap gap-3 items-center">
      <Sheet
        defaultOpen
        dismissible={false}
        onClosePrevent={() => setPreventedCloseCount((value) => value + 1)}
        title="Persistent sheet"
        body={
          <p class="text-sm text-foreground">
            Prevented close attempts: <span class="font-medium">{preventedCloseCount()}</span>
          </p>
        }
      >
        <Button variant="outline">Dismiss blocked</Button>
      </Sheet>
    </div>
  )
}
```

## API Reference

### Attributes

#### `trigger`

Element users activate to open the sheet.

#### `overlay`

Backdrop layer rendered behind the sheet panel.

#### `content`

Slide-in panel containing header, body, footer, and close control.

##### ARIA Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| aria-describedby | boolean \| string \| undefined | References descriptive text associated with the control. |
| aria-labelledby | boolean \| string \| undefined | References the element that labels the control or region. |
| aria-modal | boolean \| string \| undefined | Identifies modal content that traps interaction outside the dialog. |
| role | string | Defines the semantic role exposed to assistive technology. |

#### `header`

Top region for sheet title and description.

#### `wrapper`

Inner wrapper that arranges sheet header, body, footer, and actions.

#### `title`

Accessible title for the sheet.

#### `description`

Supporting text associated with the sheet title.

#### `actions`

Header action region, usually paired with the close control.

#### `close`

Button that dismisses the sheet.

##### ARIA Attributes

| Attribute | Type | Description |
| --- | --- | --- |
| aria-label | boolean \| string \| undefined | Provides an accessible label when visible text is not sufficient. |

#### `body`

Main sheet content region.

#### `footer`

Bottom region for sheet actions.

### Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| action | JSX.Element | — | Additional action elements to render in the header. |
| body | JSX.Element | — | Custom element to render in the scrollable body slot. |
| children | JSX.Element | — | Trigger element that opens the sheet. |
| class | ClassValue | — | Class applied to the component root or trigger element. |
| classes | SheetT.Classes \| undefined | — | — |
| close | boolean \| JSX.Element | true | Whether to show a close button, or a custom element to use as one. |
| defaultOpen | boolean \| undefined | — | Initial open state when uncontrolled. |
| description | JSX.Element | — | Secondary description displayed below the title. |
| dismissible | boolean \| undefined | — | Whether outside interaction and Escape should dismiss the shell. |
| footer | JSX.Element | — | Custom element to render in the footer slot. |
| header | JSX.Element | — | Custom element to render in the header slot. |
| id | string \| undefined | — | Unique identifier used to derive the content id. |
| inset | boolean \| undefined | — | — |
| onClosePrevent | (() => void) \| undefined | — | Called when a dismissal attempt is blocked. |
| onOpenChange | ((open: boolean) => void) \| undefined | — | Called whenever the open state changes. |
| open | boolean \| undefined | — | Controlled open state. |
| overlay | boolean \| undefined | — | Whether to render the overlay element. |
| ref | JSX.HTMLElementTags["span"] extends { ref?: infer Ref; } ? Ref : never \| undefined | — | — |
| side | "bottom" \| "top" \| "right" \| "left" \| undefined | — | — |
| style | JSX.CSSProperties \| undefined | — | — |
| styles | SheetT.Styles \| undefined | — | — |
| title | JSX.Element | — | Primary title displayed in the sheet header. |
| transition | boolean \| undefined | true | Whether to enable transition animations. |

### ARIA

Accessibility attributes and roles emitted by the component markup.

| Attribute | Type | Description |
| --- | --- | --- |
| aria-describedby | boolean \| string \| undefined | References descriptive text associated with the control. |
| aria-hidden | boolean \| string \| undefined | Hides decorative content from assistive technology. |
| aria-label | boolean \| string \| undefined | Provides an accessible label when visible text is not sufficient. |
| aria-labelledby | boolean \| string \| undefined | References the element that labels the control or region. |
| aria-modal | boolean \| string \| undefined | Identifies modal content that traps interaction outside the dialog. |
| role | string | Defines the semantic role exposed to assistive technology. |

### Data Attributes

State and slot attributes exposed for styling hooks and selectors.

| Attribute | Type | Description |
| --- | --- | --- |
| data-slot | string | Identifies the rendered slot for styling hooks and selectors. |
