Sheet

ui-sheet is a modal panel attached to one edge of the viewport. It is a thin wrapper around Dialog with side set, and behaves the same way. It opens with showModal(), traps focus, closes on Escape, a backdrop click or the close button, and returns focus to the trigger when it closes. The default side is right.

It has the same parts as the dialog: ui-sheet-trigger, ui-sheet-header with ui-sheet-title and ui-sheet-description, ui-sheet-footer and ui-sheet-close.

Previewindex.html
Open sheet Edit profile Make changes to your profile here. Click save when you are done. Name Username Save changes
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Sheet demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/field.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/input.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/label.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/sheet.html"></import-element>

  <ui-sheet>
    <ui-sheet-trigger><ui-button variant="outline">Open sheet</ui-button></ui-sheet-trigger>
    <ui-sheet-header>
      <ui-sheet-title>Edit profile</ui-sheet-title>
      <ui-sheet-description>Make changes to your profile here. Click save when you are done.</ui-sheet-description>
    </ui-sheet-header>
    <ui-field>
      <ui-label for="sheet-profile-name">Name</ui-label>
      <ui-input id="sheet-profile-name" value="Pedro Duarte"></ui-input>
    </ui-field>
    <ui-field>
      <ui-label for="sheet-profile-username">Username</ui-label>
      <ui-input id="sheet-profile-username" value="@peduarte"></ui-input>
    </ui-field>
    <ui-sheet-footer>
      <ui-sheet-close><ui-button>Save changes</ui-button></ui-sheet-close>
    </ui-sheet-footer>
  </ui-sheet>
</body>
</html>

Examples

Sides

Set side to top, right, bottom or left. Left and right sheets are full height. Top and bottom sheets are full width.

Previewindex.htmlsheet-side-demo.html
Top Right Bottom Left Menu Jump to a section of the app. Close
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Sheet demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/sheet.html"></import-element>

  <import-element from="./sheet-side-demo.html"></import-element>
  <sheet-side-demo></sheet-side-demo>
</body>
</html>
<custom-element name="sheet-side-demo">
  <script>
    const panel = useState({ side: "right" });

    function open(side) {
      panel.side = side;
      refs.sheet.showModal();
    }
  </script>

  <style>
    :host {
      display: flex;
      flex-wrap: wrap;
      gap: calc(var(--spacing) * 2);
    }
    nav {
      display: grid;
      gap: calc(var(--spacing) * 2);
      font-size: var(--text-sm);
    }
  </style>

  <ui-button variant="outline" onclick="open('top')">Top</ui-button>
  <ui-button variant="outline" onclick="open('right')">Right</ui-button>
  <ui-button variant="outline" onclick="open('bottom')">Bottom</ui-button>
  <ui-button variant="outline" onclick="open('left')">Left</ui-button>
  <ui-sheet ref="sheet" _side="#panel.side">
    <ui-sheet-header>
      <ui-sheet-title>Menu</ui-sheet-title>
      <ui-sheet-description>Jump to a section of the app.</ui-sheet-description>
    </ui-sheet-header>
    <nav>
      <a href="#sheet-overview">Overview</a>
      <a href="#sheet-projects">Projects</a>
      <a href="#sheet-settings">Settings</a>
    </nav>
    <ui-sheet-footer>
      <ui-sheet-close><ui-button variant="outline">Close</ui-button></ui-sheet-close>
    </ui-sheet-footer>
  </ui-sheet>
</custom-element>

React to closing

close fires on the sheet after it closes, however it was closed.

Previewindex.htmlsheet-close-demo.html
Filters Filters Press Escape or click outside to close. Closed times
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Sheet demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/button.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/sheet.html"></import-element>

  <import-element from="./sheet-close-demo.html"></import-element>
  <sheet-close-demo></sheet-close-demo>
</body>
</html>
<custom-element name="sheet-close-demo">
  <script>
    const filters = useState({ closed: 0 });

    function closed() {
      filters.closed++;
    }
  </script>

  <style>
    :host {
      display: flex;
      align-items: center;
      gap: calc(var(--spacing) * 4);
      font-size: var(--text-sm);
    }
  </style>

  <ui-sheet side="left" onclose="closed()">
    <ui-sheet-trigger><ui-button variant="outline">Filters</ui-button></ui-sheet-trigger>
    <ui-sheet-header>
      <ui-sheet-title>Filters</ui-sheet-title>
      <ui-sheet-description>Press Escape or click outside to close.</ui-sheet-description>
    </ui-sheet-header>
  </ui-sheet>
  <span>Closed <slot name="#filters.closed"></slot> times</span>
</custom-element>

API

Parts

Part Slot Renders
ui-sheet A ui-dialog attached to the side edge.
ui-sheet-trigger trigger Its content, outside the sheet. A click on it focuses the element inside and opens the sheet.
ui-sheet-header header A column for the title and description at the top.
ui-sheet-title (default) An <h2> in var(--text-lg) semibold. Its text becomes the sheet's accessible name.
ui-sheet-description (default) A <p> in muted var(--text-sm). Its text becomes the sheet's accessible description.
ui-sheet-footer footer A row of actions at the bottom, aligned to the end.
ui-sheet-close (default) Its content. A click on it closes the sheet.

Parts with a slot assign themselves to it, so you do not write slot. Everything else goes in the body in source order.

ui-sheet attributes

Attribute Type Default Description
open boolean false Whether the sheet is open. Setting it opens the sheet modally. Reflects.
side "top" | "right" | "bottom" | "left" "right" The edge the sheet is attached to.

Properties and methods

Name Description
showModal() Opens the sheet.
show() Same as showModal().
close() Closes the sheet.
requestClose() Fires cancel on the inner dialog, then closes unless it was cancelled.
open Boolean property mirroring the attribute.

Commands

Command Action
--show-modal Opens the sheet.
--close Closes the sheet.
--request-close Same as requestClose().

ui-button also accepts the commands without the -- prefix. A plain <button> needs the prefix.

Events

Event Detail Description
close none Fired after the sheet has closed. Does not bubble.

CSS parts

Element Part Description
ui-sheet dialog The inner ui-dialog element. Its own parts are not exported.
ui-sheet-title title The <h2>.
ui-sheet-description description The <p>.

Accessibility

ui-sheet inherits the behaviour of ui-dialog. The page behind it is inert, focus moves into the sheet on open and back to the trigger on close, Escape and a backdrop click close it, and the close button has aria-label="Close". The title and description text name and describe the sheet.

Edit this page on GitHub · View as Markdown