Examples
Basic
Click "Open drawer" to slide the panel in from the right. Click the X (or anywhere else) to close. Alpine tracks the expanded flag.
Main page content. Click the button to slide the drawer panel in from the right.
Panel title
Drawer panel content — details, edit form, related items.
Panel at end
The default position. On expand, focus moves to the panel header for keyboard and screen-reader users — mirrors PF's
onExpand focus management.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus pretium est a porttitor vehicula. Quisque vel commodo urna. Morbi mattis rutrum ante, id vehicula ex accumsan ut.
Panel at start
pf-m-panel-left — the panel slides in from the start (left) edge.
The panel slides in from the start (left) edge — pf-m-panel-left on the drawer root.
Panel on bottom
pf-m-panel-bottom — the panel slides up from the bottom. The drawer needs an explicit
height.
The panel slides up from the bottom — pf-m-panel-bottom on the drawer root. The drawer needs an explicit height for a bottom panel to be visible.
Basic inline
pf-m-inline — the panel takes space from the content instead of overlapping it.
pf-m-inline — the panel shares space with the content instead of overlapping it; no backdrop semantics.
Inline panel at end
Inline drawer with the default end position plus focus management on expand.
Inline drawer, panel at the end — pf-m-inline.
Inline panel at start
pf-m-inline pf-m-panel-left — inline drawer opening from the start edge.
Inline drawer with the panel at the start (left) — pf-m-inline pf-m-panel-left.
Stacked content body elements
Both the content and the panel can stack multiple
pf-v6-c-drawer__body elements; padding is opt-in per body (pf-m-padding
/ pf-m-no-padding).
Drawer panel title
Modified content padding
Content bodies have no padding by default — pf-m-padding adds it.
Content body with pf-m-padding — drawer content bodies have no padding by default.
Modified panel padding
Panel bodies are padded by default — pf-m-no-padding removes it.
The panel body opts out of its default padding with pf-m-no-padding.
Additional section above drawer content
A pf-v6-c-drawer__section outside __main stays full-width —
the panel never overlaps it.
A pf-v6-c-drawer__section sits outside __main — above
the content and panel.
Static
static=true — pf-m-static — panel is permanently visible, no
toggle.
pf-m-static — the panel is always shown, no toggle. Useful for split-pane layouts.
Static panel — always visible.
Breakpoint
Panel width via pf-m-width-33; all width modifiers accept
-on-lg-style breakpoint suffixes.
The panel width is set with pf-m-width-33 — width modifiers (25/33/50/66/75/100) also come in -on-lg / -on-xl forms.
Resizable at end
pf-m-resizable + a splitter. Drag (or focus the splitter and press the arrow keys) to
resize; the phaDrawerResizable Alpine factory updates the panel's flex-basis custom
property.
Drag the splitter (or focus it and use the arrow keys) to resize the panel. Minimum size 150px, default 500px.
Resizable at start
Resizable panel on the start (left) edge.
Resizable panel on the start side — the splitter sits on the panel's trailing edge.
Resizable on bottom
Bottom panel with a horizontal splitter — resize with drag or the up/down arrow keys.
Resizable bottom panel — the splitter is horizontal and arrow keys resize vertically.
Resizable on inline
Inline + resizable — content reflows while dragging.
Resizable panel in an inline drawer.
Panel with secondary background
pf-m-secondary on the panel, content, or section switches that region to the secondary
background color variant.
Toggle the checkboxes to flip each region between default and secondary background.
With focus trap
While open, Tab cycles inside the panel only (PHA.trapFocus); Escape closes it. The panel
gets role="dialog".
While the panel is open, Tab cycles only through the panel's focusable elements; Escape closes it.
Pill
pf-m-pill — the panel floats over the content as a detached, rounded pill.
pf-m-pill — the panel renders as a detached, rounded "pill" floating over the content.
Pill inline
Pill styling combined with pf-m-inline — the rounded panel shares space with the content.
Pill panel in an inline drawer — pf-m-pill pf-m-inline.
Documentation
Drawer props
The drawer is a template family: drawer is the root (it owns the
expanded Alpine state and the bound pf-m-expanded class)
and the structure comes from drawer-section /
drawer-main / drawer-content /
drawer-body / drawer-panel /
drawer-panel-main / drawer-head includes composed in main
blocks — no generic slot names to collide with outer templates.
| Name | Type | Description |
|---|---|---|
id
|
String | DOM id on the drawer root. |
inline / static / pill / panelLeft / panelBottom
|
Boolean |
The matching pf-m-* modifier; static also starts
expanded.
|
startExpanded
|
Boolean |
Start with the panel open without pf-m-static.
|
resizable + defaultSize / minSize
|
Boolean + px |
Uses the phaDrawerResizable Alpine factory; pair with
drawer-panel resizable=true for the splitter.
|
attrs
|
String (raw) | Raw attribute passthrough on the root (styles, Alpine directives). Shadowed inside the family's inserts. |
drawer-section / drawer-main / drawer-content / drawer-panel-main
|
Include | Structural wrappers — main-block content. |
drawer-body
|
Include |
Repeatable body section; padding /
noPadding modifiers.
|
drawer-panel
|
Include |
resizable (splitter wired to the factory, orientation follows
panelBottom), secondary,
panelWidth (e.g. "pf-m-width-33"), attrs.
|
drawer-head
|
Include |
Title row; main block is the title content. Renders the close button (wired to
expanded) unless noClose.
|
Usage
Pair with a trigger. The runtime template manages the expanded state via Alpine. Dispatch from an
outside trigger by setting expanded = true through a shared Alpine store or by
re-rendering the drawer with HTMX.
Resizable panels. Load
/web/js/alpine/components/drawer-resizable.js and use
x-data="phaDrawerResizable" with data-position,
data-default-size and data-min-size on the drawer root.
The splitter needs role="separator" and wires
@pointerdown="startResize" /
@keydown="keyResize".