A native Astro equivalent of @fpkit/acss DialogModal. Uses the HTML <dialog> element with showModal() for accessible modal behavior — backdrop, Escape key, and focus trap are all handled natively by the browser.

---
import DialogModal from '#components/astro/DialogModal.astro'
---

Or via the component barrel:

---
import { DialogModal } from '#components'
---
---
import DialogModal from '#components/astro/DialogModal.astro'
---
<DialogModal id="my-dialog" dialogTitle="My Dialog">
<p>Dialog body content goes here.</p>
</DialogModal>

This renders a trigger button and the modal dialog. The id links the button to its dialog — it must be unique per page.

PropTypeDefaultDescription
idstringrequiredUnique ID linking trigger button to dialog
dialogTitlestringrequiredTitle shown in the dialog header
size'sm' | 'md' | 'lg' | 'full'undefinedSize variant — sets data-size on <dialog>
position'center' | 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'undefinedPosition variant — sets data-position on <dialog>
btnLabelstring'Open Dialog'Trigger button label
btnClassstringundefinedExtra CSS classes on the trigger button
headingLevel'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6''h2'Heading element for the dialog title
confirmLabelstring'Confirm'Footer confirm button label
cancelLabelstring'Cancel'Footer cancel button label
hideFooterbooleanfalseHides the footer action buttons
<DialogModal id="dialog-sm" dialogTitle="Small Dialog" btnLabel="Open Small" size="sm">
<p>A compact dialog.</p>
</DialogModal>
<DialogModal id="dialog-lg" dialogTitle="Large Dialog" btnLabel="Open Large" size="lg">
<p>A larger dialog.</p>
</DialogModal>
<DialogModal id="dialog-full" dialogTitle="Full Screen" btnLabel="Open Full" size="full">
<p>Fills the viewport.</p>
</DialogModal>
<DialogModal id="dialog-top" dialogTitle="Top Sheet" btnLabel="Open Top" position="top">
<p>Slides in from the top.</p>
</DialogModal>
<DialogModal id="dialog-right" dialogTitle="Side Panel" btnLabel="Open Panel" position="right">
<p>Docked to the right edge.</p>
</DialogModal>

Use hideFooter when the dialog is informational and no confirm/cancel action is needed.

<DialogModal
id="dialog-info"
dialogTitle="Information"
btnLabel="Learn More"
hideFooter={true}
>
<p>This dialog has no action buttons.</p>
</DialogModal>

The confirm button dispatches a dialog:confirm CustomEvent on the dialog element before closing. Listen to it by targeting the dialog’s id.

---
import DialogModal from '#components/astro/DialogModal.astro'
---
<DialogModal
id="dialog-delete"
dialogTitle="Delete Item"
btnLabel="Delete"
confirmLabel="Yes, delete"
cancelLabel="Keep it"
>
<p>Are you sure you want to delete this item?</p>
</DialogModal>
<p id="delete-result" aria-live="polite"></p>
<script>
document.getElementById('dialog-delete')?.addEventListener('dialog:confirm', () => {
const result = document.getElementById('delete-result')
if (result) result.textContent = 'Item deleted.'
})
</script>

Match the dialog title to the document heading hierarchy to preserve accessibility.

<DialogModal
id="dialog-nested"
dialogTitle="Section Detail"
headingLevel="h3"
>
<p>Dialog used inside a section with an h2 heading.</p>
</DialogModal>

Multiple dialogs on the same page work independently — each is identified by its unique id.

<DialogModal id="dialog-a" dialogTitle="Dialog A" btnLabel="Open A">
<p>Content for dialog A.</p>
</DialogModal>
<DialogModal id="dialog-b" dialogTitle="Dialog B" btnLabel="Open B">
<p>Content for dialog B.</p>
</DialogModal>
  • Uses native <dialog> with showModal() — the browser provides backdrop, Escape key, and focus trap automatically.
  • aria-labelledby links the dialog to its title heading.
  • aria-describedby links the dialog to its content section.
  • The close button has aria-label="Close dialog" for screen readers.
  • Focus is restored to the trigger button when the dialog closes.
  • All buttons are explicitly type="button" to prevent accidental form submission.

No styles are included in this component. fpkit dialog CSS is globally included via Base.astro. The component uses standard fpkit class names and data-* attributes:

  • .dialog-header, .dialog-title, .dialog-content, .dialog-footer
  • data-size — size variant attribute read by fpkit CSS
  • data-position — position variant attribute read by fpkit CSS
  • data-btn="sm" — fpkit button attribute used on trigger and footer buttons