Drawer

A panel that slides in from an edge and can be dragged shut.

Installation

uvx django_shadcn@latest add drawer

Usage

<c-drawer>
    <c-drawer.trigger>
        <c-button variant="outline">Open drawer</c-button>
    </c-drawer.trigger>
    <c-drawer.overlay />
    <c-drawer.content>
        <c-drawer.header>
            <c-drawer.title>Move to folder</c-drawer.title>
            <c-drawer.description>Pick where this should live.</c-drawer.description>
        </c-drawer.header>
        <c-drawer.footer>
            <c-button>Move</c-button>
            <c-drawer.close>
                <c-button variant="outline" class="w-full">Cancel</c-button>
            </c-drawer.close>
        </c-drawer.footer>
    </c-drawer.content>
</c-drawer>

The grab handle at the top follows your pointer. Let go past about four tenths of the panel's height and it closes; let go short of that and it springs back. Escape and a click on the overlay close it too.

The overlay is a separate element, so you can leave it out for a drawer that does not dim the page.

Examples

Direction

<c-drawer direction="right">...</c-drawer>
<c-drawer direction="top">...</c-drawer>
<c-drawer direction="left">...</c-drawer>

Without the overlay

<c-drawer>
    <c-drawer.trigger>...</c-drawer.trigger>
    <c-drawer.content>...</c-drawer.content>
</c-drawer>

Notes

Upstream builds on vaul, which adds momentum, snap points that let the panel rest at intermediate heights, and a scaling effect on the page behind. None of that is reproduced. What is here is the part people actually use: a panel from the edge, a handle, and drag to dismiss.

Dragging works on the bottom drawer only — the handle appears there and nowhere else, which is upstream's own arrangement. The other directions open and close by click, Escape and the overlay.

If you only need a panel from an edge, Sheet covers that with less machinery. Reach for the drawer when the drag matters.

The directional classes come from the registry, with data-vaul-drawer-direction renamed to data-direction — carrying a library name for a library we do not ship would be misleading.