Browse Components
Dialog
Focused overlays for information, decisions, and forms.
Basic
A focused message with a clear close action.
View Code
<button
class="btn secondary"
type="button"
data-dialog-open="welcome"
aria-haspopup="dialog"
aria-controls="welcome"
>
Simple Dialog
</button>
<dialog
class="dialog"
id="welcome"
aria-labelledby="welcome-title"
aria-describedby="welcome-description"
data-dialog-dismiss
>
<header class="dialog-header">
<h2 id="welcome-title">
A little room to focus.
</h2>
</header>
<div class="dialog-body stack">
<p id="welcome-description">
Keep a focused task in view while the rest of the page takes a step back.
</p>
<p class="muted">
This example also closes when you click the backdrop.
</p>
</div>
<footer class="dialog-footer">
<button class="btn" type="button" data-dialog-close autofocus>
Got It
</button>
</footer>
</dialog>Confirmation
Focus starts on Keep Draft. Backdrop clicks do not dismiss a decision; Escape cancels. No data is discarded.
View Code
<button
class="btn secondary"
type="button"
data-dialog-open="confirm"
aria-haspopup="dialog"
aria-controls="confirm"
>
Confirmation
</button>
<dialog
class="dialog"
id="confirm"
role="alertdialog"
aria-labelledby="confirm-title"
aria-describedby="confirm-description"
>
<header class="dialog-header">
<h2 id="confirm-title">
Discard this draft?
</h2>
</header>
<div class="dialog-body">
<p id="confirm-description">
This is a confirmation preview. No draft will be discarded. In your app, explain the consequence before asking someone to continue.
</p>
</div>
<form method="dialog">
<footer class="dialog-footer">
<button class="btn secondary" value="cancel" autofocus>
Keep Draft
</button>
<button class="btn" value="discard">
Discard Draft
</button>
</footer>
</form>
</dialog>Form
Native validation keeps invalid input open. Cancel bypasses validation; backdrop clicks do not discard input. This example does not save data.
View Code
<button
class="btn secondary"
type="button"
data-dialog-open="profile"
aria-haspopup="dialog"
aria-controls="profile"
>
Form Dialog
</button>
<dialog
class="dialog"
id="profile"
aria-labelledby="profile-title"
aria-describedby="profile-description"
>
<header class="dialog-header">
<h2 id="profile-title">
Make yourself at home.
</h2>
</header>
<form method="dialog">
<div class="dialog-body stack">
<p id="profile-description" class="muted">
Try native validation. This demo closes without saving your changes.
</p>
<label class="stack">
Display name
<input
class="input"
name="display-name"
autocomplete="nickname"
required
placeholder="Your name"
autofocus
>
</label>
<label class="stack">
Email address
<input
class="input"
type="email"
name="email"
autocomplete="email"
required
placeholder="[email protected]"
>
</label>
</div>
<footer class="dialog-footer">
<button class="btn secondary" type="button" data-dialog-close>
Cancel
</button>
<button class="btn" value="done">
Done
</button>
</footer>
</form>
</dialog>Scrolling content
A wider layout with a scrolling body and visible actions.
View Code
<button
class="btn secondary"
type="button"
data-dialog-open="guide"
aria-haspopup="dialog"
aria-controls="guide"
>
Scrolling Content
</button>
<dialog
class="dialog dialog-wide"
id="guide"
aria-labelledby="guide-title"
data-dialog-dismiss
>
<header class="dialog-header">
<h2 id="guide-title" tabindex="-1" autofocus>
Space for the whole story.
</h2>
</header>
<div class="dialog-body stack" tabindex="0" aria-label="Example reading content">
<p>
The body scrolls while the heading and actions stay visible.
</p>
<h3>
One task at a time
</h3>
<p>
Keep the purpose clear. Use a page for a separate destination.
</p>
<h3>
A clear next step
</h3>
<p>
Choose specific labels. Give people a way to cancel.
</p>
<h3>
Every screen
</h3>
<p>
Try a narrow window or larger text. Actions stay within reach.
</p>
<h3>
Keyboard access
</h3>
<p>
Use Tab to move, Escape to close, and return to your starting point.
</p>
</div>
<footer class="dialog-footer">
<button class="btn" type="button" data-dialog-close>
Close
</button>
</footer>
</dialog>Right-to-left
Hebrew content with dir=rtl and lang=he. Layout and actions follow the reading direction.
View Code
<div dir="rtl" lang="he">
<button class="btn secondary" type="button" data-dialog-open="hebrew">
פתיחת חלון
</button>
<dialog
class="dialog"
id="hebrew"
dir="rtl"
lang="he"
aria-labelledby="hebrew-title"
data-dialog-dismiss
>
<header class="dialog-header">
<h2 id="hebrew-title">
ברוכים הבאים
</h2>
</header>
<div class="dialog-body">
<p>
זוהי דוגמה לחלון בעברית, מימין לשמאל.
</p>
</div>
<footer class="dialog-footer">
<button class="btn" type="button" data-dialog-close autofocus>
סגירה
</button>
</footer>
</dialog>
</div>Installation
Download these files into the matching paths in your project, or use Create to assemble a kit. Include each dependency once. Do not also load app.css.
<link rel="stylesheet" href="/library/assets/base.css">
<link rel="stylesheet" href="/library/assets/button.css">
<link rel="stylesheet" href="/library/assets/field.css">
<link rel="stylesheet" href="/library/assets/dialog.css">
<script defer src="/library/assets/dialog.js"></script>14,213 bytes CSS including base · 2,172 bytes runtime JavaScript
Usage
Open a focused task
Use dialog.dialog with a visible title linked by aria-labelledby. Connect an opener with data-dialog-open and the dialog’s ID.
Offer a clear way out
Include a close or cancel button. Escape closes the dialog and focus returns to the opener. Use autofocus deliberately, favoring the safe action.
Own the result
Include the dialog script once. Your app handles validation, saving, and errors. Closing a dialog does not mean data was saved.
Building with AI? The AI Manifest has these notes and the full contract. See the AI Guide.
Framework integrations
Use this shared component standalone or through the tested React, Next.js, Vue, Nuxt, Angular, Svelte, and Astro integration paths. Keep application state in your framework; adapters handle native behavior and cleanup.
View Integration APIs and Working Examples. For dialogs, choose either the adapter controller or the standalone initializer, never both on the same element.