Skip to main content

Dialog

Centered modal overlay for alerts and forms.

Selectors

.dialog
Centered modal overlay with glass background and backdrop. Add to <dialog> element.
.dialog-close
Positioned close button (top-right corner).
data-modal
Prevents closing via backdrop click (requires js/cider.js).

Default

Save changes to "Untitled"?

Your changes will be lost if you don't save them.

HTML
<button onclick="openDialog(this.nextElementSibling)" class="btn-tinted">Close Document</button>

<dialog class="dialog">
  <header>
    <h2>Save changes to "Untitled"?</h2>
    <p>Your changes will be lost if you don't save them.</p>
  </header>
  <footer>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-tinted">Don't Save</button>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-gray">Cancel</button>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-filled">Save</button>
  </footer>
</dialog>

Destructive

Delete project?

This will permanently delete the project "My Portfolio" and all of its files. This action is irreversible.

HTML
<button onclick="openDialog(this.nextElementSibling)" class="btn-filled btn-destructive">Delete Project</button>

<dialog class="dialog">
  <header>
    <h2>Delete project?</h2>
    <p>This will permanently delete the project "My Portfolio" and all of its files. This action is irreversible.</p>
  </header>
  <footer>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-tinted">Cancel</button>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-filled btn-destructive">Delete Project</button>
  </footer>
</dialog>

With Icon

Sign out of your account?

You will need to enter your credentials again to sign back in.

HTML
<button onclick="openDialog(this.nextElementSibling)" class="btn-tinted">Sign Out</button>

<dialog class="dialog">
  <header>
    <div class="mx-auto mb-4 flex size-12 items-center justify-center rounded-full bg-secondary">
      <svg class="size-6 text-tertiary-foreground" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z"/></svg>
    </div>
    <h2 class="text-center">Sign out of your account?</h2>
    <p class="text-center">You will need to enter your credentials again to sign back in.</p>
  </header>
  <footer>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-tinted">Cancel</button>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-filled btn-destructive">Sign Out</button>
  </footer>
</dialog>

Form Dialog

Edit Profile

Make changes to your profile here.

HTML
<button onclick="openDialog(this.nextElementSibling)" class="btn-tinted">Edit Profile</button>

<dialog class="dialog">
  <header>
    <h2>Edit Profile</h2>
    <p>Make changes to your profile here.</p>
  </header>
  <section>
    <div class="space-y-4">
      <label class="space-y-2">Name
        <input type="text" value="John Doe" />
      </label>
      <label class="space-y-2">Email
        <input type="email" value="john@example.com" />
      </label>
    </div>
  </section>
  <footer>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-tinted">Cancel</button>
    <button class="btn-filled" onclick="closeDialog(this.closest('dialog'))">Save Changes</button>
  </footer>
</dialog>

Scrollable Content

Terms of Service

Please read the following terms carefully.

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.

Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.

Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis.

Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.

At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias.

Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae.

HTML
<button onclick="openDialog(this.nextElementSibling)" class="btn-tinted">Scrollable Dialog</button>

<dialog class="dialog">
  <header>
    <h2>Terms of Service</h2>
    <p>Please read the following terms carefully.</p>
  </header>
  <section>
    <div class="space-y-4 text-sm text-tertiary-foreground">
      <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.</p>
      <p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident.</p>
      <p>Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis.</p>
      <p>Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.</p>
      <p>At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias.</p>
      <p>Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae.</p>
    </div>
  </section>
  <footer>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-tinted">Decline</button>
    <button class="btn-filled" onclick="closeDialog(this.closest('dialog'))">Accept</button>
  </footer>
</dialog>

With Close Button

Share Link

Anyone with the link will be able to view this document.

HTML
<button onclick="openDialog(this.nextElementSibling)" class="btn-tinted">Share Link</button>

<dialog class="dialog">
  <button aria-label="Close" onclick="closeDialog(this.closest('dialog'))" class="dialog-close">
    <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
  </button>
  <header>
    <h2>Share Link</h2>
    <p>Anyone with the link will be able to view this document.</p>
  </header>
  <section>
    <div class="flex gap-2">
      <input type="text" value="https://example.com/doc/abc123" readonly class="flex-1" />
      <button class="btn-gray" onclick="navigator.clipboard && navigator.clipboard.writeText('https://example.com/doc/abc123')">Copy</button>
    </div>
  </section>
</dialog>

Custom Content

Invite Team Members

Add colleagues to collaborate on this project.

SC

Sarah Chen

sarah@example.com

Owner
JD

John Doe

john@example.com

HTML
<button onclick="openDialog(this.nextElementSibling)" class="btn-tinted">Invite Members</button>

<dialog class="dialog" style="max-width: 480px;">
  <header>
    <h2>Invite Team Members</h2>
    <p>Add colleagues to collaborate on this project.</p>
  </header>
  <section>
    <div class="space-y-4">
      <div class="flex gap-2">
        <input type="email" placeholder="email@example.com" class="flex-1" />
        <button class="btn-gray">Invite</button>
      </div>
      <div class="space-y-2">
        <div class="flex items-center justify-between rounded-lg border px-3 py-2">
          <div class="flex items-center gap-2.5">
            <div class="avatar size-8 text-xs bg-primary/10 text-primary">SC</div>
            <div>
              <p class="text-sm font-medium">Sarah Chen</p>
              <p class="text-xs text-tertiary-foreground">sarah@example.com</p>
            </div>
          </div>
          <span class="text-xs text-tertiary-foreground">Owner</span>
        </div>
        <div class="flex items-center justify-between rounded-lg border px-3 py-2">
          <div class="flex items-center gap-2.5">
            <div class="avatar size-8 text-xs bg-primary/10 text-primary">JD</div>
            <div>
              <p class="text-sm font-medium">John Doe</p>
              <p class="text-xs text-tertiary-foreground">john@example.com</p>
            </div>
          </div>
          <select class="h-auto w-auto py-1 pl-2 pr-8 text-xs rounded-lg" aria-label="User role">
            <option>Viewer</option>
            <option selected>Editor</option>
            <option>Admin</option>
          </select>
        </div>
      </div>
    </div>
  </section>
  <footer>
    <button onclick="closeDialog(this.closest('dialog'))" class="btn-tinted">Cancel</button>
    <button class="btn-filled" onclick="closeDialog(this.closest('dialog'))">Done</button>
  </footer>
</dialog>

Button Order

Place the primary action on the right, secondary in the middle, and cancel/dismiss on the left. Apple convention: the rightmost button is the default action.

Browser Support

Dialog uses corner-shape: squircle for Apple-style rounded corners. This requires Safari 18+ or Chrome 130+. Standard border-radius is applied as a fallback in older browsers.

Usage

Adds backdrop click to close with exit animation, focus trapping, scroll lock, and focus restoration. The native <dialog> element handles open/close — this script is optional.

<!-- npm -->
<script src="node_modules/ciderui/js/cider.js"></script>

<!-- CDN -->
<script src="https://cdn.jsdelivr.net/gh/newlix/ciderui@main/js/cider.js"></script>

API

openDialog(dialogElement)
Opens the dialog as a modal. Guards against re-opening an already-open or closing dialog.
closeDialog(dialogElement)
Closes the dialog with an exit animation, restoring focus and scroll position.

Both functions are available as globals and via CiderUI.dialog.open() / CiderUI.dialog.close().

Accessibility

  • Uses native <dialog> for built-in modal semantics.
  • Auto-sets aria-labelledby from the dialog's heading and aria-describedby from its description.
  • Focus is trapped inside the dialog while open; first focusable element receives focus on open.
  • Escape closes the dialog. Backdrop click also dismisses (unless data-modal is set).
  • Focus is restored to the triggering element on close.