Sheet
A slide-over panel from any screen edge with header, body, and footer sections.
Rendering Sheet…
Installation
Copy the source into your project with the CLI. It lands under @/components/ui and is yours to edit.
npx mlola-ui add sheetUsage
"use client";
import * as React from "react";
import { Button } from "@/components/ui/button";
import { Sheet, SheetBody, SheetFooter } from "@/components/ui/sheet";
export default function Example() {
const [open, setOpen] = React.useState(false);
const close = () => setOpen(false);
return (
<>
<Button variant="secondary" onClick={() => setOpen(true)}>Settings</Button>
<Sheet open={open} onClose={close} title="Account settings" description="Changes apply instantly.">
<SheetBody>Escape closes the panel, and so does the backdrop.</SheetBody>
<SheetFooter>
<Button onClick={close}>Done</Button>
</SheetFooter>
</Sheet>
</>
);
}Styling comes from the engine stylesheet and the nearest theme. Set it once at the root:
<html data-theme="graphite" data-mode="light">HTML
Without React, write this markup and load @mlola-ui/behavior once. It runs the keyboard, focus and state for every element marked data-ml="sheet", including markup added later, and needs no build step.
<button class="ml-button" type="button" data-variant="secondary" data-ml-opens="account-settings">
<span class="ml-button-label">Settings</span>
</button>
<div class="ml-sheet-overlay" data-ml-for="account-settings" hidden></div>
<div class="ml-sheet-panel" id="account-settings" data-ml="sheet" role="dialog" aria-modal="true" aria-labelledby="account-settings-title" data-side="right" data-size="md" tabindex="-1" hidden>
<div class="ml-sheet-header">
<div class="ml-sheet-heading">
<h2 class="ml-sheet-title" id="account-settings-title">Account settings</h2>
<p class="ml-sheet-description">Changes apply instantly.</p>
</div>
<button class="ml-sheet-close" type="button" aria-label="Close panel"><svg class="mlola-glyph" width="1em" height="1em" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M18 6 6 18M6 6l12 12"/></svg></button>
</div>
<div class="ml-sheet-body">
<p>Escape closes the panel, and so does the backdrop.</p>
</div>
</div><script type="module">
import { observe } from "@mlola-ui/behavior";
observe();
</script>Options
| Prop | Values | Default |
|---|---|---|
side | leftrighttopbottom | right |
size | smmdlg | md |
Every prop with a fixed set of values, read from the exported TypeScript types with its doc comment. Open the Code tab above for the rest of the API.
Classes and attributes
A class names each element; data-* and aria-* attributes carry its variant and state. The values listed are the ones the stylesheet draws; the default needs no attribute.
| Class | Attributes |
|---|---|
ml-sheet-overlay | — |
ml-sheet-close | — |
ml-sheet-layer | — |
ml-sheet-panel | data-side="bottom | left | right | top"data-size="lg | sm" |
ml-sheet-header | — |
ml-sheet-heading | — |
ml-sheet-title | — |
ml-sheet-description | — |
ml-sheet-body | — |
ml-sheet-footer | — |
Accessibility and theming
- Semantic elements, accessible names and state relationships are part of the contract.
- Keyboard, pointer and touch paths are operable; focus stays visible in every theme.
- Light and dark modes pass WCAG AA contrast in all 5 canonical themes.
- Reduced motion and forced colors keep meaning and operation.
Dependencies
Installed alongside this component. No third-party UI runtime is ever added.
@mlola-ui/behavior@mlola-ui/icons