EN
Getting started
30 · UI elements

Modal

A window that opens on top of the page and dims what is behind it. Use it for short forms, detail views and situations where the user needs to focus on one task; only one modal stays open at a time.

acun:modal
01

Basic usage

Every modal has a unique name value. The window is opened by this name with acun:modal.trigger, the acun:modal:open event or, in JavaScript, AcunUI.modal.open('catalog-customer'). The X in the header, the Esc key and a click on the backdrop close the window. When it opens, focus moves to the first interactive element, the Tab key cycles inside the window, and when it closes, focus returns to the button that opened it.

LIVE EXAMPLE
<acun:modal.trigger name="catalog-customer"><acun:button>Open the customer summary</acun:button></acun:modal.trigger>

<acun:modal name="catalog-customer" title="Customer summary">
    <dl class="space-y-3 text-sm">
        <div class="flex justify-between"><dt class="text-gray-500 dark:text-zinc-400">Customer</dt><dd>Ayşe Yılmaz</dd></div>
        <div class="flex justify-between"><dt class="text-gray-500 dark:text-zinc-400">Membership</dt><dd>Premium</dd></div>
        <div class="flex justify-between"><dt class="text-gray-500 dark:text-zinc-400">Last order</dt><dd>September 12, 2026</dd></div>
    </dl>
</acun:modal>
PropValues
nameUnique name; events carry this name
titleHeader line (with the X button)
02

Widths

The maximum width of the window is chosen with max-width; the default is md. Use sm for confirmations and short messages, and xl or 2xl for two-column forms or tables. On narrow screens the window is always full width.

LIVE EXAMPLE
<div class="flex flex-wrap gap-2" x-data>
    <acun:modal.trigger name="catalog-width-sm"><acun:button variant="white">sm</acun:button></acun:modal.trigger>
    <acun:modal.trigger name="catalog-width-lg"><acun:button variant="white">lg</acun:button></acun:modal.trigger>
    <acun:modal.trigger name="catalog-width-2xl"><acun:button variant="white">2xl</acun:button></acun:modal.trigger>
</div>

<acun:modal name="catalog-width-sm" title="Narrow window" max-width="sm"><p class="text-sm">For a short confirmation or message.</p></acun:modal>
<acun:modal name="catalog-width-lg" title="Wide window" max-width="lg"><p class="text-sm">For single-column forms.</p></acun:modal>
<acun:modal name="catalog-width-2xl" title="Widest window" max-width="2xl"><p class="text-sm">For two-column forms and small tables.</p></acun:modal>
PropValues
max-widthsm | md | lg | xl | 2xl
04

Window without a title

When title is not given, the header line and the X button are not rendered; the content uses the whole window. In this case, give an aria-label so the screen reader can name the window (when empty, "Dialog" is read, in the app language).

LIVE EXAMPLE
<acun:modal.trigger name="catalog-done"><acun:button variant="white">Finish the import</acun:button></acun:modal.trigger>

<acun:modal name="catalog-done" max-width="sm" aria-label="Import complete">
    <div class="flex flex-col items-center gap-3 py-4 text-center">
        <acun:icon name="check-circle" size="12" stroke="1.4" class="text-emerald-600" />
        <p class="text-base font-semibold text-gray-900 dark:text-zinc-100">Import complete</p>
        <p class="text-sm text-gray-500 dark:text-zinc-400">148 products were added to the Electronics category.</p>
        <acun:modal.close><acun:button class="mt-2">Done</acun:button></acun:modal.close>
    </div>
</acun:modal>
PropValues
aria-labelAccessible name of the window when there is no title
05

Do not close on outside click

So that a long form is not lost by accident, turn off closing on backdrop click with :closable-on-backdrop="false"; X and Esc keep working. Pass the value with a colon: if you write closable-on-backdrop="false", the text "false" is passed and the feature stays on.

LIVE EXAMPLE
<acun:modal.trigger name="catalog-sticky"><acun:button variant="white">Open the ticket form</acun:button></acun:modal.trigger>

<acun:modal name="catalog-sticky" title="Support ticket" :closable-on-backdrop="false">
    <acun:textarea name="ticket_note" label="Ticket note" rows="4" />
    <acun:slot:footer>
        <acun:modal.close><acun:button variant="white">Close</acun:button></acun:modal.close>
    </acun:slot:footer>
</acun:modal>
PropValues
closable-on-backdroptrue | false
06

Asking before closing

When request-close-event is given, X, Esc and the backdrop do not close the window directly; they emit an event with this name. The code listening for the event (e.g. an unsaved changes check) decides and closes the window: close() if the listener is on the window, AcunUI.modal.close('catalog-note') if it is elsewhere. close() in the footer skips this check.

LIVE EXAMPLE
<acun:modal.trigger name="catalog-note"><acun:button variant="white">Add a note</acun:button></acun:modal.trigger>

<acun:modal
    name="catalog-note"
    title="Add a note"
    request-close-event="catalog-note-close-requested"
    x-on:catalog-note-close-requested.window="if (confirm('The note you wrote will not be saved. Close anyway?')) close()"
>
    <acun:textarea name="customer_note" label="Note" rows="3" />
</acun:modal>
PropValues
request-close-eventName of the event emitted on a close request
07

With Livewire

Send the acun:modal:open and acun:modal:close events from the server. close-action is the Livewire method called when the user closes the window (X, Esc, backdrop, close()); an acun:modal:close sent from the server does not call this method again. When the window opens, acun:modal:opened is emitted, and on every close acun:modal:closed, both with { name }. The original names (open-modal, close-modal and the emitted modal-closed) keep working as well.

PHP
// <acun:modal name="product-form" title="Product" close-action="resetForm"> … </acun:modal>

public function edit(int $productId): void
{
    $this->product = Product::findOrFail($productId);
    $this->dispatch('acun:modal:open', name: 'product-form');
}

public function save(): void
{
    $this->product->save();
    $this->dispatch('acun:modal:close', name: 'product-form');
}

public function resetForm(): void
{
    $this->reset('product');
}
PropValues
close-actionLivewire method called when the user closes the window
08

Composable parts

Wrap the button that opens the modal in acun:modal.trigger; no JavaScript is needed. Build the window from the acun:modal.header (title, description and X), acun:modal.body (scrolling body) and acun:modal.footer parts; a button inside acun:modal.close closes the window. The content must start with a part; to wrap the body and footer in a form, put the form after the header.

LIVE EXAMPLE
<acun:modal.trigger name="add-task">
    <acun:button>New task</acun:button>
</acun:modal.trigger>

<acun:modal name="add-task" max-width="lg">
    <acun:modal.header title="New task" description="Choose the branch and the assignee." />

    <acun:modal.body class="space-y-4">
        <acun:input name="task_name" label="Task name" placeholder="Kadıköy – stock count" />
        <acun:select name="branch" label="Branch" :options="['kadikoy' => 'Kadıköy', 'uskudar' => 'Üsküdar', 'atasehir' => 'Ataşehir']" placeholder="Choose a branch" />
        <acun:select name="assignee" label="Assignee" :options="['ahmet' => 'Ahmet Yılmaz', 'elif' => 'Elif Kaya']" placeholder="Choose a team member" />
    </acun:modal.body>

    <acun:modal.footer>
        <acun:modal.close>
            <acun:button variant="white">Cancel</acun:button>
        </acun:modal.close>
        <acun:modal.close>
            <acun:button x-on:click="$dispatch('toast', { type: 'success', message: 'Task saved.' })">Save</acun:button>
        </acun:modal.close>
    </acun:modal.footer>
</acun:modal>
PropValues
acun:modal.triggername (the modal to open)
acun:modal.headertitle, description; slot: header content
acun:modal.body · footerBody and footer
acun:modal.closeThe element inside closes the modal
09

Close button in a classic modal

acun:modal.close also works in the classic usage with title and the footer slot.

LIVE EXAMPLE
<acun:modal.trigger name="delivery-note">
    <acun:button variant="white">Delivery note</acun:button>
</acun:modal.trigger>

<acun:modal name="delivery-note" title="Delivery note">
    <p class="text-sm text-gray-600 dark:text-zinc-400">If the customer is not at the address, leave the package with the building attendant and take a photo.</p>
    <acun:slot:footer>
        <acun:modal.close><acun:button variant="white">Close</acun:button></acun:modal.close>
    </acun:slot:footer>
</acun:modal>
API

Props and slots

The values the component accepts.

PropDefaultDescription
name — Required. The name used in the acun:modal:open / acun:modal:close events and the AcunUI.modal.open('…') / close('…') calls; closing without a name closes all modals. acun:modal:opened is emitted on open and acun:modal:closed on close ({ name })
titlenullHeader line and X button; not rendered when empty
max-widthmdsm · md · lg · xl · 2xl
aria-labelnullAccessible name when there is no title; when empty, "Dialog" (in the app language)
closable-on-backdroptrueCloses on a backdrop click
close-actionnullLivewire method called when the user closes the window
request-close-eventnullX / Esc / backdrop emit this event instead of closing
modal.trigger: name — Required; opens the modal with this name on click (confirmation-dialog included)
modal.header: title · descriptionnullTitle, description and X; when title is not given, the slot is the title itself
modal.body · modal.footer — Scrolling body and right-aligned footer
modal.close — Clicking the element inside closes the modal
Slots: default: the window body (scrolls) or the parts (acun:modal.header, acun:modal.body, acun:modal.footer) · footer: right-aligned footer · acun:modal.trigger and acun:modal.close open and close it.
Acun UI · ModalDetailed usage and examples