EN
Getting started
32 · UI elements

Drawer

A panel that slides in from the side of the screen. Use it for content viewed without leaving the page, such as record details, a short form or the filters of a list page.

acun:drawer
01

Basic usage

The panel is opened by its unique name value: acun:drawer.trigger, the acun:drawer:open event or, in JavaScript, AcunUI.drawer.open('catalog-details'). The X in the header, the Esc key, a click on the backdrop and a click on a link inside the panel close it. When it opens, focus moves to the field with autofocus, or else to the first focusable element in the panel; Tab cycles inside the panel, and when it closes, focus returns to the button that opened it. While the panel is open, the page behind it does not scroll.

LIVE EXAMPLE
<acun:drawer.trigger name="catalog-details"><acun:button variant="white">Open the customer summary</acun:button></acun:drawer.trigger>

<acun:drawer name="catalog-details" title="Customer summary">
    <dl class="space-y-3 text-sm">
        <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">Orders</dt><dd>5</dd></div>
    </dl>
    <acun:slot:footer>
        <acun:drawer.close><acun:button variant="white">Close</acun:button></acun:drawer.close>
        <acun:button>Edit</acun:button>
    </acun:slot:footer>
</acun:drawer>
PropValues
nameUnique name
titleHeader line (with the X button)
footerSlot: footer
02

Side and width

side chooses which edge the panel opens from; the default is right. The width is set with size (md ≈ 448px, sm ≈ 320px) or with width, which takes a max-w-* class directly. On narrow screens the panel covers 85% of the screen.

LIVE EXAMPLE
<div class="flex flex-wrap gap-2" x-data>
    <acun:drawer.trigger name="catalog-left"><acun:button variant="white">From the left, sm</acun:button></acun:drawer.trigger>
    <acun:drawer.trigger name="catalog-wide"><acun:button variant="white">From the right, max-w-2xl</acun:button></acun:drawer.trigger>
</div>

<acun:drawer name="catalog-left" side="left" size="sm" title="Shortcuts">
    <p class="text-sm">A narrow panel that opens from the left.</p>
</acun:drawer>

<acun:drawer name="catalog-wide" width="max-w-2xl" title="Order history">
    <p class="text-sm">A wider panel for wide content such as tables.</p>
</acun:drawer>
PropValues
sideright | left
sizesm | md
widthmax-w-* class (replaces size)
03

Floating panel

floating shows the panel slightly inset from the screen edges, like a card with rounded corners. It suits short, self-contained content.

LIVE EXAMPLE
<acun:drawer.trigger name="catalog-floating"><acun:button variant="white">Open the floating panel</acun:button></acun:drawer.trigger>

<acun:drawer name="catalog-floating" floating title="Notifications">
    <ul class="space-y-3 text-sm">
        <li>12 orders were shipped from the Kadıköy warehouse.</li>
        <li>Ayşe Yılmaz added a new customer.</li>
    </ul>
</acun:drawer>
PropValues
floatingtrue | false
04

Custom header

The header slot replaces the standard header line; you can build a rich top area with an avatar or tabs. In this case the X button is not added: put a close button in yourself with close() and give the panel an aria-label.

LIVE EXAMPLE
<acun:drawer.trigger name="catalog-person"><acun:button variant="white">Show the support agent</acun:button></acun:drawer.trigger>

<acun:drawer name="catalog-person" aria-label="Support agent">
    <acun:slot:header>
        <div class="flex items-center gap-3 pb-4">
            <acun:avatar name="Ayşe Yılmaz" />
            <div class="min-w-0 flex-1">
                <p class="text-sm font-semibold text-gray-900 dark:text-zinc-100">Ayşe Yılmaz</p>
                <p class="text-xs text-gray-500 dark:text-zinc-400">Support agent · Business accounts</p>
            </div>
            <acun:drawer.close><acun:button variant="ghost" size="icon" aria-label="Close"><acun:icon name="x-mark" /></acun:button></acun:drawer.close>
        </div>
    </acun:slot:header>
    <p class="text-sm">Answered 112 support tickets this month.</p>
</acun:drawer>
PropValues
headerSlot: replaces the header line
aria-labelAccessible name when there is no title
05

Without a backdrop

:backdrop="false" removes the dimming; clicking outside the panel still closes it (that is set by closable-on-backdrop). :lock-scroll="false" lets the page behind scroll while the panel is open. Pass the values with a colon.

LIVE EXAMPLE
<acun:drawer.trigger name="catalog-plain"><acun:button variant="white">Open without a backdrop</acun:button></acun:drawer.trigger>

<acun:drawer name="catalog-plain" title="Help" :backdrop="false" :lock-scroll="false">
    <p class="text-sm">Help text at the side while the page stays visible.</p>
</acun:drawer>
PropValues
backdroptrue | false
lock-scrolltrue | false
06

Form panel

With :closable-on-backdrop="false", clicking the backdrop does not close the panel; this keeps a half-filled form from closing by accident. The panel still closes with X, Esc and the close button. When it opens, focus moves to the field with autofocus.

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

<acun:drawer name="catalog-form" :closable-on-backdrop="false">
    <acun:drawer.header title="Order note" description="#10482 · Ayşe Yılmaz" />
    <acun:drawer.body class="space-y-4">
        <acun:input name="subject" label="Subject" />
        <acun:textarea name="note" label="Note" rows="4" autofocus />
    </acun:drawer.body>
    <acun:drawer.footer>
        <acun:drawer.close><acun:button variant="white">Cancel</acun:button></acun:drawer.close>
        <acun:drawer.close><acun:button>Save</acun:button></acun:drawer.close>
    </acun:drawer.footer>
</acun:drawer>
PropValues
closable-on-backdroptrue | false
autofocusField to focus on open
07

Binding with Livewire

wire:model binds the panel to a Livewire property: the panel opens when the property is true and closes when it is false. When the user closes the panel (X, Esc, backdrop), the property becomes false as well; wire:model sends this with the next request, wire:model.live right away. This way you open the panel from the server without sending an event. It binds to Alpine data with x-model in the same way; give the variable a name different from the panel's own state names (rendered, entered, opened, model).

LIVE EXAMPLE
<acun:button wire:click="showDetails(4821)">Order details</acun:button>

<acun:drawer name="order-details" wire:model="detailsOpen">
    <acun:drawer.header :title="'Order #'.$orderNo" description="Kadıköy warehouse · 3 items" />
    <acun:drawer.body>
        <p class="text-sm">Recipient: Ayşe Yılmaz · Status: Processing</p>
    </acun:drawer.body>
    <acun:drawer.footer>
        <acun:drawer.close><acun:button variant="white">Close</acun:button></acun:drawer.close>
        <acun:button wire:click="markShipped">Ship order</acun:button>
    </acun:drawer.footer>
</acun:drawer>
PropValues
wire:model · wire:model.liveLivewire property (bool)
x-modelAlpine data (bool)
08

Livewire component

The component of the previous example. Setting the property to true is enough to open the panel.

PHP
use Livewire\Component;

class OrderDetails extends Component
{
    public bool $detailsOpen = false;

    public ?int $orderNo = null;

    public function showDetails(int $no): void
    {
        $this->orderNo = $no;
        $this->detailsOpen = true;
    }

    public function markShipped(): void
    {
        // … update the record
        $this->detailsOpen = false;
    }
}
09

Events

The panel listens for the acun:drawer:open, acun:drawer:close and acun:drawer:toggle events with { name }; when acun:drawer:close is sent without a name, all open panels close. In JavaScript the same commands are given with AcunUI.drawer.open('…'), AcunUI.drawer.close('…') and AcunUI.drawer.toggle('…'). The panel emits acun:drawer:opened when it opens and acun:drawer:closed the moment it starts closing, both with { name }. The original names (open-drawer, close-drawer, toggle-drawer and drawer-state-changed, which carries { name, open }) keep working as well. An open menu or dropdown inside the panel uses the Esc key first; the panel closes with the next Esc.

LIVE EXAMPLE
<div class="flex items-center gap-3" x-data="{ isOpen: false }"
    x-on:acun:drawer:opened.window="if ($event.detail.name === 'catalog-notes') isOpen = true"
    x-on:acun:drawer:closed.window="if ($event.detail.name === 'catalog-notes') isOpen = false">
    <acun:drawer.trigger name="catalog-notes" toggle><acun:button variant="white">Notes</acun:button></acun:drawer.trigger>
    <span class="text-sm" x-text="isOpen ? 'Panel open' : 'Panel closed'"></span>
</div>

<acun:drawer name="catalog-notes" title="Notes">
    <p class="text-sm">Notes taken during the customer call.</p>
</acun:drawer>
PropValues
acun:drawer:open · acun:drawer:close · acun:drawer:toggleEvents listened for ({ name })
AcunUI.drawer.open · close · toggleThe same commands from JavaScript (name)
acun:drawer:opened · acun:drawer:closedEmitted events ({ name })
10

Filters panel (docked)

docked is for the Filters panel of list pages: on desktop (1024px and up) it is pinned to the left edge and, in the ready-made layouts, pushes the content to the right while focus stays on the page; on narrower screens it becomes a drawer with a backdrop that takes focus and keeps it inside. In this mode the header line is not rendered (title only becomes the accessible name), and side, size, width, floating, backdrop and header are not used. compact tightens the spacing in the footer.

LIVE EXAMPLE
<acun:filter-button drawer="catalog-filters" :count="1" />

<acun:drawer name="catalog-filters" docked title="Filters" compact>
    <div class="space-y-4">
        <acun:input name="f_code" placeholder="Custom Code" />
        <acun:select name="f_status" :options="['' => 'All Statuses', '1' => 'Active', '0' => 'Inactive']" />
    </div>
    <acun:slot:footer>
        <acun:button variant="outline" size="sm" class="flex-1">Clear</acun:button>
        <acun:drawer.close><acun:button variant="outline-danger" size="sm" class="flex-1">Close</acun:button></acun:drawer.close>
    </acun:slot:footer>
</acun:drawer>
PropValues
dockedtrue | false
compacttrue | false (footer spacing)
11

Composable parts

acun:drawer.trigger opens the drawer (with toggle it opens and closes it; aria-expanded is updated automatically). The panel is built from the acun:drawer.header, acun:drawer.body and acun:drawer.footer parts; a button inside acun:drawer.close closes the panel.

LIVE EXAMPLE
<acun:drawer.trigger name="order-4821">
    <acun:button variant="white">Order details</acun:button>
</acun:drawer.trigger>

<acun:drawer name="order-4821">
    <acun:drawer.header title="Order #4821" description="Kadıköy warehouse · 3 items · Agent: Ayşe Yılmaz" />

    <acun:drawer.body class="space-y-4">
        <acun:input name="recipient" label="Recipient" value="Mehmet Kaya" />
        <acun:select name="status" label="Order status" :options="['processing' => 'Processing', 'shipped' => 'Shipped', 'delivered' => 'Delivered']" />
        <acun:textarea name="note" label="Agent note" rows="3" />
    </acun:drawer.body>

    <acun:drawer.footer>
        <acun:drawer.close>
            <acun:button variant="white">Cancel</acun:button>
        </acun:drawer.close>
        <acun:drawer.close>
            <acun:button x-on:click="$dispatch('toast', { type: 'success', message: 'Order updated.' })">Save</acun:button>
        </acun:drawer.close>
    </acun:drawer.footer>
</acun:drawer>
PropValues
acun:drawer.triggername, toggle
acun:drawer.headertitle, description
acun:drawer.body · footerBody and footer
acun:drawer.closeThe element inside closes the panel
API

Props and slots

The values the component accepts.

PropDefaultDescription
name — Required. The name used in the acun:drawer:open · acun:drawer:close · acun:drawer:toggle events and the AcunUI.drawer.open('…') call; acun:drawer:opened · acun:drawer:closed carry this name
titlenullHeader line (with X) and accessible name
siderightright · left
sizemdmd (max-w-md) · sm (max-w-xs)
widthnullmax-w-* class; when given, size is not used
floatingfalsePanel inset from the edges, with rounded corners
backdroptrueDims the background
lock-scrolltrueKeeps the page from scrolling while open
closable-on-backdroptrueCloses on a backdrop click
wire:model · x-model — Binds the open/closed state to a Livewire property or Alpine data
compactfalseTight spacing in the footer
dockedfalseFilters panel behavior of list pages
aria-labelnullAccessible name when there is no title; when empty, "Menu" (in the app language)
body-classflex-1 p-5 overflow-y-autoClasses of the body wrapper
drawer.trigger: name · toggle — Opens the panel; with toggle, closes it if open. aria-expanded is added to the button
drawer.header: title · descriptionnullHeader line and X
drawer.body · drawer.footer — Scrolling body and footer (follow the compact and docked settings)
drawer.close — Clicking the element inside closes the panel
Slots: default: panel content · header: replaces the header line (no X is added) · footer: footer. close() can be used inside the slots.
Acun UI · DrawerDetailed usage and examples