Dialog
The dialog opens a modal window above the page and blocks interaction with everything behind it. Use it for confirmations, short forms, and alerts that need a decision; for a panel that slides in from the edge, reach for the sheet.
<button id="dialog-1-trigger" class="btn btn-outline">Open Dialog</button>
<dialog class="dialog" data-sp-toggle="#dialog-1-trigger">
<form class="dialog-panel">
<button
type="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="dialog-header">
<h2 class="dialog-title">Edit profile</h2>
<p class="dialog-description">
Make changes to your profile here. Click save when you're done.
</p>
</div>
<div class="dialog-content">
<div class="field-group">
<div class="field">
<label class="label" for="dialog-profile-name">Name</label>
<input
class="input"
id="dialog-profile-name"
name="name"
value="Pedro Duarte"
/>
</div>
<div class="field">
<label class="label" for="dialog-profile-username">Username</label>
<input
class="input"
id="dialog-profile-username"
name="username"
value="@peduarte"
/>
</div>
</div>
</div>
<div class="dialog-footer">
<button type="button" class="btn btn-outline" data-sp-dismiss>
Cancel
</button>
<button type="submit" class="btn">Save changes</button>
</div>
</form>
</dialog>Usage
Add the dialog class to a <dialog> element. Give your trigger an id, then point the dialog at it with data-sp-toggle. The trigger can be any element. Close the dialog with data-sp-dismiss on a button, a backdrop click, or the Escape key.
<!-- This is a button toggling the dialog -->
<button id="my-trigger" class="btn btn-outline">Open Dialog</button>
<!-- This is the dialog -->
<dialog class="dialog" data-sp-toggle="#my-trigger">
<div class="dialog-panel">
<div class="dialog-header">
<h2 class="dialog-title">Title</h2>
<p class="dialog-description">Description</p>
</div>
<div class="dialog-footer">
<button class="btn btn-outline" data-sp-dismiss>Close</button>
</div>
</div>
</dialog>Examples
Custom close button
Any element with data-sp-dismiss closes the dialog, so put close buttons wherever the layout needs them.
<button id="dialog-share-trigger" class="btn btn-outline">Share</button>
<dialog class="dialog" data-sp-toggle="#dialog-share-trigger">
<div class="dialog-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="dialog-header">
<h2 class="dialog-title">Share link</h2>
<p class="dialog-description">
Anyone who has this link will be able to view this.
</p>
</div>
<div class="dialog-content">
<div class="field">
<label class="label sr-only" for="dialog-share-link">Link</label>
<input
class="input"
id="dialog-share-link"
value="https://startingpointui.com/guides/installation"
readonly
/>
</div>
</div>
<div class="dialog-footer sm:justify-start">
<button class="btn" data-sp-dismiss>Close</button>
</div>
</div>
</dialog>Sticky footer
Cap the body's height and let it scroll on its own: the header and footer stay pinned while the content scrolls between them.
<button id="dialog-sticky-trigger" class="btn btn-outline">
Sticky Footer
</button>
<dialog class="dialog" data-sp-toggle="#dialog-sticky-trigger">
<div class="dialog-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="dialog-header">
<h2 class="dialog-title">Sticky Footer</h2>
<p class="dialog-description">
This dialog has a sticky footer that stays visible while the content
scrolls.
</p>
</div>
<div
class="dialog-content scrollbar-none max-h-[50vh] overflow-y-auto leading-normal"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
</div>
<div class="dialog-footer">
<button class="btn btn-outline" data-sp-dismiss>Close</button>
</div>
</div>
</dialog>Scrollable content
The same scrolling body without a footer.
<button id="dialog-scroll-trigger" class="btn btn-outline">
Scrollable Content
</button>
<dialog class="dialog" data-sp-toggle="#dialog-scroll-trigger">
<div class="dialog-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="dialog-header">
<h2 class="dialog-title">Scrollable Content</h2>
<p class="dialog-description">
This is a dialog with scrollable content.
</p>
</div>
<div
class="dialog-content scrollbar-none max-h-[50vh] overflow-y-auto leading-normal"
>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea
commodo consequat. Duis aute irure dolor in reprehenderit in voluptate
velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint
occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</p>
</div>
</div>
</dialog>Alert dialog
An alert dialog interrupts the user and requires a choice. Add data-sp-static so a backdrop click won't dismiss it (Escape still closes, so keyboard users are never stuck) and author role="alertdialog" on the element. Put autofocus on the least destructive action and skip the close button.
<button id="alert-trigger" class="btn btn-outline">Show Dialog</button>
<dialog
class="dialog"
role="alertdialog"
data-sp-toggle="#alert-trigger"
data-sp-static
>
<div class="dialog-panel">
<div class="dialog-header">
<h2 class="dialog-title">Are you absolutely sure?</h2>
<p class="dialog-description">
This will permanently delete your account and remove your data from our
servers.
</p>
</div>
<div class="dialog-footer">
<button class="btn btn-outline" data-sp-dismiss autofocus>Cancel</button>
<button class="btn" data-sp-dismiss>Continue</button>
</div>
</div>
</dialog>CSS variables
The panel's spacing rhythm is one component-local variable: the panel derives its vertical padding and section gap from it, and each section its horizontal padding. Override it per instance with an arbitrary property, or for the whole app with a plain CSS rule.
<div class="dialog-panel [--dialog-spacing:--spacing(4)]"></div>Options
Dialog
Set each option with its own data-sp-* attribute on the dialog element.
<dialog class="dialog" data-sp-toggle="#my-trigger" data-sp-static></dialog>JavaScript
Events
Lifecycle events fire on the dialog element; before* events are cancelable.
el.addEventListener("sp-beforeshow", (e) => {
if (!ready) e.preventDefault(); // veto the open
});Methods
Get the instance with sp.dialog(el), then call its methods:
const dialog = sp.dialog(document.querySelector("#my-dialog"));
dialog.show();