Starting Point
v0.25.0
Start typing to search...
Go to Page
escClose

Sheet

The sheet slides a modal panel in from a screen edge. Use it for edit forms, filters, carts, and mobile navigation; for a centered window, reach for the dialog.

<button id="sheet-1-trigger" class="btn btn-outline">Open</button>
 
<dialog class="sheet" data-sp-toggle="#sheet-1-trigger">
  <div class="sheet-panel">
    <button
      class="btn btn-ghost btn-xs btn-icon absolute top-3 right-3"
      aria-label="Close"
      data-sp-dismiss
    >
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
    </button>
    <div class="sheet-header">
      <h2 class="sheet-title">Edit profile</h2>
      <p class="sheet-description">
        Make changes to your profile here. Click save when you're done.
      </p>
    </div>
    <div class="sheet-content">
      <div class="field-group">
        <div class="field">
          <label class="label" for="sheet-profile-name">Name</label>
          <input class="input" id="sheet-profile-name" value="Pedro Duarte" />
        </div>
        <div class="field">
          <label class="label" for="sheet-profile-username">Username</label>
          <input class="input" id="sheet-profile-username" value="@peduarte" />
        </div>
      </div>
    </div>
    <div class="sheet-footer">
      <button class="btn">Save changes</button>
      <button class="btn btn-outline" data-sp-dismiss>Close</button>
    </div>
  </div>
</dialog>

Usage

Add the sheet class to a <dialog> element. Give your trigger an id, then point the sheet at it with data-sp-toggle. The trigger can be any element. Close the sheet with data-sp-dismiss on a button, a backdrop click, or the Escape key.

ClassDescription
sheetAdd to the <dialog> element; fills the viewport and dims the page
sheet-left sheet-right sheet-top sheet-bottomAdd to sheet to pick the edge; right is the default
sheet-panelAdd to the child element that is the visible panel
sheet-headerAdd to the block holding the title and description
sheet-titleAdd to a heading element to create the sheet title
sheet-descriptionAdd to a paragraph to create the supporting description
sheet-contentAdd to the body section between header and footer
sheet-footerAdd to the action block; it sticks to the bottom of the panel
<!-- This is a button toggling the sheet -->
<button id="my-trigger" class="btn btn-outline">Open Sheet</button>
 
<!-- This is the sheet -->
<dialog class="sheet" data-sp-toggle="#my-trigger">
  <div class="sheet-panel">
    <div class="sheet-header">
      <h2 class="sheet-title">Title</h2>
      <p class="sheet-description">Description</p>
    </div>
    <div class="sheet-footer">
      <button class="btn btn-outline" data-sp-dismiss>Close</button>
    </div>
  </div>
</dialog>

Examples

Side

Pick the edge the sheet slides from with sheet-left, sheet-right, sheet-top, or sheet-bottom. Without one, it defaults to the right.

<!-- Left -->
<button id="side-left" class="btn btn-outline">Left</button>
 
<dialog class="sheet sheet-left" data-sp-toggle="#side-left">
  <div class="sheet-panel">
    <div class="sheet-header">
      <h2 class="sheet-title">Left</h2>
      <p class="sheet-description">Great for navigation menus.</p>
    </div>
    <div class="sheet-footer">
      <button class="btn btn-outline" data-sp-dismiss>Close</button>
    </div>
  </div>
</dialog>
 
<!-- Right -->
<button id="side-right" class="btn btn-outline">Right</button>
 
<dialog class="sheet sheet-right" data-sp-toggle="#side-right">
  <div class="sheet-panel">
    <div class="sheet-header">
      <h2 class="sheet-title">Right</h2>
      <p class="sheet-description">Great for details and settings.</p>
    </div>
    <div class="sheet-footer">
      <button class="btn btn-outline" data-sp-dismiss>Close</button>
    </div>
  </div>
</dialog>
 
<!-- Top -->
<button id="side-top" class="btn btn-outline">Top</button>
 
<dialog class="sheet sheet-top" data-sp-toggle="#side-top">
  <div class="sheet-panel">
    <div class="sheet-header">
      <h2 class="sheet-title">Top</h2>
      <p class="sheet-description">Great for notifications.</p>
    </div>
    <div class="sheet-footer">
      <button class="btn btn-outline self-start" data-sp-dismiss>Close</button>
    </div>
  </div>
</dialog>
 
<!-- Bottom -->
<button id="side-bottom" class="btn btn-outline">Bottom</button>
 
<dialog class="sheet sheet-bottom" data-sp-toggle="#side-bottom">
  <div class="sheet-panel">
    <div class="sheet-header">
      <h2 class="sheet-title">Bottom</h2>
      <p class="sheet-description">Great for actions on mobile.</p>
    </div>
    <div class="sheet-footer">
      <button class="btn btn-outline self-start" data-sp-dismiss>Close</button>
    </div>
  </div>
</dialog>

Mobile navigation

Pair a left sheet with the sidebar menu classes for a simple mobile navigation drawer. For a full navigation layout with a desktop column, reach for the sidebar component instead.

<button id="sheet-nav-trigger" class="btn btn-ghost btn-icon" aria-label="Open menu">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 12h16"/><path d="M4 18h16"/><path d="M4 6h16"/></svg>
</button>
 
<dialog class="sheet sheet-left" aria-label="Main menu" data-sp-toggle="#sheet-nav-trigger">
  <div class="sheet-panel">
    <button
      class="btn btn-ghost btn-xs btn-icon absolute top-3 right-3"
      aria-label="Close"
      data-sp-dismiss
    >
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="size-4"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
    </button>
    <div class="sheet-header">
      <a href="#" class="flex h-10 min-w-0 items-center gap-2 text-foreground">
        <span class="flex size-6 shrink-0 items-center justify-center overflow-hidden rounded-sm bg-primary text-base leading-none text-primary-foreground">
          <i class="font-serif font-bold not-italic">A</i>
        </span>
        <span class="truncate text-sm font-medium">Acme Inc.</span>
      </a>
    </div>
    <div class="sheet-content px-2">
      <nav class="sidebar-menu">
        <div class="sidebar-menu-item">
          <a href="#" class="sidebar-menu-button active">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8"/><path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/></svg>
            <span>Home</span>
          </a>
        </div>
        <div class="sidebar-menu-item">
          <a href="#" class="sidebar-menu-button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 12h-6l-2 3h-4l-2-3H2"/><path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"/></svg>
            <span>Inbox</span>
          </a>
        </div>
        <div class="sidebar-menu-item">
          <a href="#" class="sidebar-menu-button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/></svg>
            <span>Calendar</span>
          </a>
        </div>
        <div class="sidebar-menu-item">
          <a href="#" class="sidebar-menu-button">
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/><circle cx="12" cy="12" r="3"/></svg>
            <span>Settings</span>
          </a>
        </div>
 
      </nav>
    </div>
    <div class="sheet-footer">
      <button class="btn">Upgrade to Pro</button>
    </div>
  </div>
</dialog>

Options

Sheet

Set each option with its own data-sp-* attribute on the sheet element.

AttributeValuesDefault
data-sp-toggleCSS selector—
data-sp-staticBooleanfalse
<dialog class="sheet" data-sp-toggle="#my-trigger" data-sp-static>

JavaScript

Events

Lifecycle events fire on the sheet element; before* events are cancelable.

EventWhen
sp-beforeshowBefore showing (cancelable)
sp-showOpening
sp-shownOpen and settled
sp-beforehideBefore hiding (cancelable)
sp-hideClosing
sp-hiddenClosed
sp-hidepreventedA static sheet refused a backdrop dismiss
el.addEventListener("sp-beforeshow", (e) => {
  if (!ready) e.preventDefault(); // veto the open
});

Methods

Get the instance with sp.sheet(el), then call its methods:

MethodDescription
show()Open the sheet
hide()Close the sheet
toggle()Open if closed, else close
const sheet = sp.sheet(document.querySelector("#my-sheet"));
 
sheet.show();