Dialog

A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.

Edit profile

Make changes to your profile here. Click save when you're done.

Usage

Basecoat uses the native <dialog> element and showModal(). This differs from shadcn/ui's portalled Base UI implementation, but preserves native modality, focus handling, and inert page content without component JavaScript.

HTML

<button type="button" onclick="document.getElementById('demo-dialog-edit-profile').showModal()" class="btn-outline">Edit Profile</button>

<dialog id="demo-dialog-edit-profile" class="dialog" aria-labelledby="demo-dialog-edit-profile-title" aria-describedby="demo-dialog-edit-profile-description" onclick="if (event.target === this) this.close()">
  <div>
    <header>
      <h2 id="demo-dialog-edit-profile-title">Edit profile</h2>
      <p id="demo-dialog-edit-profile-description">Make changes to your profile here. Click save when you're done.</p>
    </header>

    <section>
      <form class="grid gap-4">
        <div class="grid gap-3">
          <label class="label" for="demo-dialog-edit-profile-name">Name</label>
          <input class="input" type="text" value="Pedro Duarte" id="demo-dialog-edit-profile-name" autofocus />
        </div>
        <div class="grid gap-3">
          <label class="label" for="demo-dialog-edit-profile-username">Username</label>
          <input class="input" type="text" value="@peduarte" id="demo-dialog-edit-profile-username" />
        </div>
      </form>
    </section>

    <footer>
      <button class="btn-outline" onclick="this.closest('dialog').close()">Cancel</button>
      <button class="btn" onclick="this.closest('dialog').close()">Save changes</button>
    </footer>

    <button type="button" class="btn-sm-icon-ghost" aria-label="Close dialog" onclick="this.closest('dialog').close()">
      <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-x-icon lucide-x">
        <path d="M18 6 6 18" />
        <path d="m6 6 12 12" />
      </svg>
    </button>
  </div>
</dialog>

HTML structure

The component has the following HTML structure:

<button type="button" onclick="dialog.showModal()"> Optional
Trigger button. Basecoat intentionally uses the native HTMLDialogElement.showModal() method.
<dialog class="dialog" id="{ DIALOG_ID }">
Native modal dialog. Add aria-labelledby="{ TITLE_ID }" and aria-describedby="{ DESCRIPTION_ID }" when title and description are present. The macro also adds backdrop-click close handling.
<div>
Dialog content surface.
<header> Optional
Dialog header.
<h2 id="{ TITLE_ID }">
Dialog title. Reference it from aria-labelledby.
<p id="{ DESCRIPTION_ID }"> Optional
Dialog description. Reference it from aria-describedby.
<section> Optional
Dialog body/content area. Add overflow utilities when the body should scroll.
<footer> Optional
Action area. It stacks actions on small screens and aligns them to the end on larger screens.
<button type="button" onclick="this.closest('dialog').close()"> Optional
Close button. You can also wrap a button in <form method="dialog">.

Jinja and Nunjucks

You can use the dialog() Nunjucks or Jinja macro for this component.

{% set footer %}
  <button class="btn-outline" onclick="this.closest('dialog').close()">Cancel</button>
  <button class="btn" onclick="this.closest('dialog').close()">Save changes</button>
{% endset %}
{% call dialog(
  id="dialog-edit-profile",
  title="Edit profile",
  description="Make changes to your profile here.",
  trigger="Edit Profile",
  trigger_attrs={"class": "btn-outline"},
  footer=footer
) %}
  <form class="grid gap-4">...</form>
{% endcall %}

Examples

Custom Close Button

Custom close button

The default close icon is hidden and the footer provides the close action.

Use close_button=false and add a close control where it fits your layout.

No Close Button

No close button

The dialog can still be closed with Escape or a custom action.

Native dialogs remain keyboard-accessible even without the default close icon.

Dialog content row 1. Add enough content to make the body scroll while the footer remains available.

Dialog content row 2. Add enough content to make the body scroll while the footer remains available.

Dialog content row 3. Add enough content to make the body scroll while the footer remains available.

Dialog content row 4. Add enough content to make the body scroll while the footer remains available.

Dialog content row 5. Add enough content to make the body scroll while the footer remains available.

Dialog content row 6. Add enough content to make the body scroll while the footer remains available.

Dialog content row 7. Add enough content to make the body scroll while the footer remains available.

Dialog content row 8. Add enough content to make the body scroll while the footer remains available.

Scrollable Content

Scrollable Content

Long content can scroll inside the dialog body.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 1.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 2.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 3.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 4.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 5.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 6.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 7.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 8.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 9.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh sit amet augue commodo ultrices. Row 10.

RTL

Dialog positioning and close button placement use logical properties. Set dir="rtl" on the dialog or a parent element.

تعديل الملف الشخصي

قم بتحديث بياناتك ثم احفظ التغييرات.

API Reference

.dialog
Native dialog root. It owns the backdrop through ::backdrop and the open state through the native open attribute.
.dialog > div
Dialog content surface. This maps to shadcn/ui's DialogContent.
.dialog > div > header
Header area. Direct h2 and p children are styled as title and description.
.dialog > div > section
Body/content area. Add utilities such as overflow-y-auto when you need scrolling.
.dialog > div > footer
Action area. Use Basecoat button classes for actions.
close_button=false
Macro option to hide the generated close icon.