Drawer

A panel that slides in from any edge of the screen for secondary content, forms or details.

Traps focus and locks body scroll while open; requires the Alpine.js focus plugin.

Basic Usage

The default slot holds the trigger; open it from any element inside with @click="drawerOpen = true". Put the body in the content slot and any actions in the footer slot.

<c-ui.drawer title="Account details" description="Update your profile and preferences.">
    <c-ui.button @click="drawerOpen = true">Open drawer</c-ui.button>
    <c-slot name="content">
        Drawer body content goes here.
    </c-slot>
    <c-slot name="footer">
        <div class="flex justify-end gap-2">
            <c-ui.button @click="drawerOpen = false">Cancel</c-ui.button>
            <c-ui.button variant="primary" @click="drawerOpen = false">Save</c-ui.button>
        </div>
    </c-slot>
</c-ui.drawer>
{% cotton ui.drawer title="Account details" description="Update your profile and preferences." %}
    {% cotton ui.button @click="drawerOpen = true" %}Open drawer{% endcotton %}
    {% cotton:slot content %}
        Drawer body content goes here.
    {% endcotton:slot %}
    {% cotton:slot footer %}
        <div class="flex justify-end gap-2">
            {% cotton ui.button @click="drawerOpen = false" %}Cancel{% endcotton %}
            {% cotton ui.button variant="primary" @click="drawerOpen = false" %}Save{% endcotton %}
        </div>
    {% endcotton:slot %}
{% endcotton %}

Sides

side opens the drawer from right (default), left, top or bottom.

<c-ui.drawer title="Filters" side="left">
    <c-ui.button @click="drawerOpen = true">Filters</c-ui.button>
    <c-slot name="content">...</c-slot>
</c-ui.drawer>
{% cotton ui.drawer title="Filters" side="left" %}
    {% cotton ui.button @click="drawerOpen = true" %}Filters{% endcotton %}
    {% cotton:slot content %}...{% endcotton:slot %}
{% endcotton %}

Sizing

size sets the panel width from sm to 2xl (for top/bottom drawers it sets the height instead). For a one-off, pass max_size with any CSS length, it applies an inline max-width/height, so it works without a matching Tailwind class.

{# named scale #}
<c-ui.drawer size="lg"> ... </c-ui.drawer>

{# one-off custom width (any CSS length) #}
<c-ui.drawer max_size="16rem"> ... </c-ui.drawer>
{# named scale #}
{% cotton ui.drawer size="lg" %} ... {% endcotton %}

{# one-off custom width (any CSS length) #}
{% cotton ui.drawer max_size="16rem" %} ... {% endcotton %}

Reference

Props

Name Description Type Options Default
title Heading shown at the top of the panel. str
description Sub-text under the title. str
side Edge the drawer slides in from. str
rightlefttopbottom
right
size Panel width (left/right) or height (top/bottom). str
smmdlgxl2xl
md
max_size Custom panel size as a CSS length (e.g. 34rem), applied inline. Overrides size. str
:dismissible Allow closing by clicking the overlay or pressing Escape. bool
TrueFalse
True
:close_button Show the close (X) button in the header. bool
TrueFalse
True
:open Open on load. The open state is exposed via x-modelable for x-model binding. bool
TrueFalse
False

Slots

Name Description Type Options Default
default Holds the trigger. Use @click=&quot;drawerOpen = true&quot; to open. slot
content The panel body (scrolls). slot
footer Pinned footer for actions. slot