Overlays

Sheet

A modal panel that slides in from the left or right edge of the screen. Use Drawer when the panel needs swipe gestures.

Installation

pnpm dlx @mielui/svelte add sheet

Usage

Compose Root, Trigger, and Content with a Header that holds the Title and an optional Description. side on Content picks the left or right edge, right by default. Focus stays within the open sheet and returns to its trigger when it closes.

<script lang="ts">
    import { Button } from '@mielui/svelte/components/button';
    import * as Sheet from '@mielui/svelte/components/sheet';

    let open = $state(false);
</script>

<Sheet.Root bind:open>
    <Sheet.Trigger>Open</Sheet.Trigger>
    <Sheet.Content side="right">
        <Sheet.Header>
            <Sheet.Title>Title</Sheet.Title>
            <Sheet.Description>Describe what lives here.</Sheet.Description>
        </Sheet.Header>
        <!-- Panel content -->
        <Sheet.Footer>
            <Sheet.Close>Cancel</Sheet.Close>
            <Button
                onclick={() => {
                    open = false;
                }}
            >
                Save
            </Button>
        </Sheet.Footer>
    </Sheet.Content>
</Sheet.Root>

Bind open on Root when another control needs to open or close the panel. onOpenChange reports changes made inside the component; updating your bound value does not call it again. Each Root keeps its own state.

Footer renders on the outer frame below the inner surface, like Dialog.Footer, wherever you place it inside Content. Its actions sit in one row; a Close in the footer moves to the start so the other actions line up at the end. The theme setting chrome.borders chooses single or double framing, single by default.

Examples

Issue form

A full form with selects in the body and the submit action in the footer.

Left side

Glass surface

surface="glass" on Content gives the panel a translucent, blurred background. Omit surface to inherit --mielui-surface from your theme, or set surface="solid" to override it. Glass keeps an opaque fallback when backdrop filtering is unavailable and respects reduced-transparency preferences.

Stay open on outside press

allowClickOutside={false} on Content keeps the sheet open when the page behind it is pressed, and showClose={false} on Header leaves the footer buttons as the only way out besides Escape.

Dismissal

A sheet closes from its corner button, Escape, a Close button, or a press on the page behind it. Set allowClickOutside={false} on Content to ignore that last one, which suits a form the person could lose by a stray click. Header shows the corner button by default; pass showClose={false} when your own Close button is enough.

Buttons and text parts

Trigger and Close are built on Button, so they accept its props: variant, size, disabled, href, loading with its labels, unstyled, and bind:element. onclick runs before the part does its own work; call event.preventDefault() there to keep the sheet as it is.

Content, Header, Title, Description and Footer render their children and accept class.

Labels

Built-in text is English by default. Pass a labels object of type SheetLabels to Sheet.Root to translate the accessible name of the close button in the header. Every key is optional; omitted keys keep their default.

<script lang="ts">
    import * as Sheet from '@mielui/svelte/components/sheet';
    import type { SheetLabels } from '@mielui/svelte/components/sheet';

    const labels: SheetLabels = {
        close: 'Fermer'
    };
</script>

<Sheet.Root {labels}>
    โ€ฆ
</Sheet.Root>

API reference

Sheet.Root

Controls sheet state.

  • labels
    SheetLabels

    Overrides the built-in text and accessible names. Every key is optional and English is the fallback.

  • open Bindable
    boolean

    Whether it is open. Bind it to control the state from outside.

    Default false

  • onOpenChange
    ((open: boolean) => void)

    Called with the new state whenever it opens or closes.

  • children
    Snippet<[]>

    Content rendered inside.

Sheet.Close

Closes the sheet.

  • disabled
    boolean

    Prevents activation. A disabled link loses its destination and is skipped by Tab.

  • variant
    ButtonVariant

    Visual style. Choose it for what the action means, not for decoration.

  • size
    "sm" | "md" | "lg" | "icon"

    Control height. icon is a square button for a single icon.

  • children
    Snippet<[]>

    Content rendered inside.

  • element Bindable
    HTMLButtonElement | HTMLAnchorElement

    Bindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site:

  • unstyled
    boolean

    Skip the variant/size base classes and render with class alone.

  • status
    ButtonStatus

    Controlled visual state. Loading remains focusable and refuses activation.

  • loading
    boolean

    Convenience alias for status="loading".

  • labels
    ButtonLabels

    Overrides the built-in text and accessible names. Every key is optional and English is the fallback.

  • onclick
    ((event: MouseEvent) => void)

    Called when the button is activated. Loading and disabled buttons do not call it.

  • onkeydown
    ((event: KeyboardEvent) => void)

    Called on key down, before the button handles the key itself.

  • href
    string

    Renders a link to this address instead of a button.

Sheet.Content

Renders the sheet surface.

  • surface
    "solid" | "glass"

    Surface treatment. Omit it to inherit --mielui-surface from the theme.

  • allowClickOutside
    boolean

    Closes when the pointer is pressed outside it. Set false to keep it open until it is dismissed another way.

    Default true

  • side
    "left" | "right"

    Viewport edge the sheet slides in from.

    Default 'right'

  • class
    string

    Classes added to the element.

  • children
    Snippet<[]>

    Content rendered inside.

Sheet.Description

Renders the sheet description.

  • class
    string

    Classes added to the element.

  • children
    Snippet<[]>

    Content rendered inside.

Sheet.Footer

Groups sheet actions.

  • class
    string

    Classes added to the element.

  • children
    Snippet<[]>

    Content rendered inside.

Sheet.Header

Groups sheet heading content.

  • class
    string

    Classes added to the element.

  • children
    Snippet<[]>

    Content rendered inside.

  • showClose
    boolean

    Shows the close button in the corner. Defaults to true.

    Default true

Sheet.Title

Renders the sheet title.

  • class
    string

    Classes added to the element.

  • children
    Snippet<[]>

    Content rendered inside.

Sheet.Trigger

Opens the sheet.

  • disabled
    boolean

    Prevents activation. A disabled link loses its destination and is skipped by Tab.

  • variant
    ButtonVariant

    Visual style. Choose it for what the action means, not for decoration.

  • size
    "sm" | "md" | "lg" | "icon"

    Control height. icon is a square button for a single icon.

  • children
    Snippet<[]>

    Content rendered inside.

  • element Bindable
    HTMLButtonElement | HTMLAnchorElement

    Bindable reference to the rendered DOM element. Type is the union of the two possible element types -- narrow at the use site:

  • unstyled
    boolean

    Skip the variant/size base classes and render with class alone.

  • status
    ButtonStatus

    Controlled visual state. Loading remains focusable and refuses activation.

  • loading
    boolean

    Convenience alias for status="loading".

  • labels
    ButtonLabels

    Overrides the built-in text and accessible names. Every key is optional and English is the fallback.

  • onclick
    ((event: MouseEvent) => void)

    Called when the button is activated. Loading and disabled buttons do not call it.

  • onkeydown
    ((event: KeyboardEvent) => void)

    Called on key down, before the button handles the key itself.

  • href
    string

    Renders a link to this address instead of a button.