Step modals
A standalone one-question-per-screen modal — no title bar, no step counter, a fixed narrow centred width, and a built-in animated stage that blurs/fades/height-morphs between screens. Independent of <koala-modal> by design; reach for it when a flow is a sequence of single decisions rather than one form.
Canonical
<div x-data="stepModalDemo()">
<button koala-btn="Primary" x-on:click="open = true">Confirm my details</button>
<koala-step-modal flag="open" aria-label="Confirm your details">
<koala-step-modal-content>
<div x-show="currentScreen === 'name'">…</div>
<div x-show="currentScreen === 'contact'">…</div>
</koala-step-modal-content>
<koala-step-modal-footer>
<button x-show="!isFirstScreen" x-on:click="goBack()">Back</button>
<button koala-btn="Primary" x-on:click="goNext()">Continue</button>
</koala-step-modal-footer>
</koala-step-modal>
</div>
Click through both screens to see the transition: the outgoing screen blurs and fades,
the stage height morphs to fit the incoming screen, then it fades/unblurs in. The engine
(transitionTo, wait) is
plain Alpine state the caller owns — see _QuoteOnboardingModal.cshtml
for the full reference implementation with branching screens.
Sub-components
2 helpers| Tag | Attributes | Notes |
|---|---|---|
| <koala-step-modal-content> | — | The animated stage. Renders the .koala-step-stage / .koala-step-panel wrapper the caller's transition engine reads via x-ref="stepStage" / x-ref="stepPanel". Everything inside blurs/fades/height-morphs on screen change. |
| <koala-step-modal-footer> | — | Static nav row (Back / Continue / Send). Sits outside the animated stage so button state never blurs mid-transition. |
Props
4 attributes| Attribute | Values | Notes |
|---|---|---|
| flag | string | Alpine variable controlling open/closed. Defaults to modalOpen. The parent x-data must declare it. |
| aria-label | string | Accessible label — there is no visible title bar to derive one from. |
| dismissable | bool | Defaults to true. Set false for a blocking overlay (drops ESC + backdrop-click). |
| teleport | bool | Teleport to <body> so an ancestor's overflow/transform can't clip the dialog. |
Do & don't
"Is this address right?" — Yes / No
A screen with name, phone, email, and a dropdown all at once.
Reduced motion
prefers-reduced-motion: reduce strips the blur (a filter
change) and the height morph entirely — both exceed DESIGN.md's opacity/<4px exemption — while
keeping the opacity cross-fade, which is exempt. The caller's wait()
helper should also skip its delays under reduced motion so screens swap immediately rather than pausing
for a transition that no longer plays.