Settings, the way they should feel.
Same component, different content. Here panels carry icon-prefixed rows, decorative toggles, and value displays — proving the stack stays out of your way and lets the content speak.
A wizard, walking forward.
Steppers are just stacks where you only call push. Each step
hits a "Continue" button to advance, or "Back" to retreat one level. The
Confirm step calls reset() to return to the start when you submit.
Create your account
Start with your name and email — we'll never share it.
Tell us about you
A few details so we can tailor the experience.
Pick your preferences
You can change these later.
Looks good?
Tune the feel of it.
Every part of the motion is exposed as a CSS custom property. Drag the sliders to change the slide distance, blur amount, horizontal scale, easing duration, and the opacity of inactive panels. Push and pop to feel the difference.
Listen in.
Every push, pop, and reset fires a bubbling, composed CustomEvent.
Push events are cancelable — call e.preventDefault() in a
panel-stack:push handler to abort navigation. Try clicking around the panel;
the log on the
right captures every event.
Or let the parent drive.
Set current to the handle you want and the stack works out the move on its
own — push, pop back through the ancestry, or reset to root. It writes the attribute
back after every navigation, including the ones you didn't start, so the value on the
element is always the truth. Unknown handles and cancelled pushes are restored.
panel-stack:change fires once the stack has settled — that's the one to
sync parent state from, since push and pop fire before the move.
current="ctl-root"
The whole API, on one screen.
Two elements, three methods, three events, eight CSS custom properties. That's everything.
Elements & attributes
<panel-stack>initialcurrent<stack-panel>handledata-action-stack-pushtarget attributetargetdata-action-stack-popdata-stack-focusMethods & getters
push(handle)pop()reset()currentcurrentHandlecurrentPaneldepthEvents
panel-stack:push{ fromHandle, toHandle }panel-stack:pop{ fromHandle, toHandle }panel-stack:reset{ rootHandle }panel-stack:change{ handle } · fires after the stack settlesCSS custom properties
--ps-transition-duration420ms--ps-transition-timingcubic-bezier(0.16, 0.87, 0.64, 1)--ps-blur-duration280ms--ps-perspective1200pxPer-state values
Each state (current, previous, next) has its
own translate, scale, blur, and opacity custom property. Override the ones for a
single state to break symmetry — e.g. make panels exit faster than they enter.
--ps-translate-{state}0% · calc(-100% - 50px) · calc(100% + 50px)--ps-scale-x-{state}1 · 1.1 · 1.1--ps-blur-{state}0px · 2px · 2px--ps-opacity-{state}1 · 0.3 · 0.3Browser support
Modern browsers with custom elements + the inert attribute. Works in
Chrome 102+, Firefox 112+, Safari 15.5+, Edge 102+. Honors
prefers-reduced-motion: reduce by suppressing the scale, blur,
and transition.