StepShell
AppWrapper card for a single step in a multi-step flow. Border and number circle change based on active / done / inactive state; the done + onEdit combination shows an Edit button alongside the summary.
Account details
jane@acme.com · Admin role
2
Billing address
Payment method
<%- include('modules/app/StepShell', {
number: 1, title: 'Account details', done: true, onEdit: '/checkout?step=1',
summary: '' + user.email + ' · ' + user.role + ' role
'
}) %>
<%- include('modules/app/StepShell', {
number: 2, title: 'Billing address', active: true,
children: addressFormHtml
}) %>
<%- include('modules/app/StepShell', { number: 3, title: 'Payment method' }) %>
2
Choose a plan
<%- include('modules/app/StepShell', {
number: 2,
title: 'Choose a plan',
active: true,
children: planSelectorHtml
}) %>
<%
var _number = typeof locals.number === 'number' ? locals.number : 1;
var _title = locals.title || '';
var _active = !!locals.active;
var _done = !!locals.done;
// `onEdit` (renamed from `editable` / `onEditHref`) gates the Edit button:
// truthy value (boolean or href string) + `_done` shows it; matches the
// NextJS `done && onEdit` predicate.
var _onEdit = locals.onEdit;
var _hasEdit = _done && !!_onEdit;
var _summary = locals.summary || '';
var _className = locals.className || '';
var _shellId = locals.id || ('step-shell-' + Math.random().toString(36).slice(2, 8));
var borderClass = _active ? 'border-primary shadow-sm' : 'border-border';
var circleClass = _done
? 'bg-success text-white'
: _active
? 'bg-primary text-primary-fg'
: 'bg-surface-overlay text-text-disabled';
var titleClass = _active
? 'text-text-primary'
: _done
? 'text-text-secondary'
: 'text-text-disabled';
%>
<% if (_done) { %><% } else { %><%= _number %><% } %>
<%- _title %>
<% if (_hasEdit) { %>
<%- include('../ui/Button', {
variant: 'ghost',
size: 'xs',
className: 'text-primary',
children: 'Edit',
element: (typeof _onEdit === 'string') ? 'a' : 'button',
href: (typeof _onEdit === 'string') ? _onEdit : undefined,
}) %>
<% } %>
<% if (_done && _summary) { %>
<%- _summary %>
<% } %>
<% if (_active && locals.children) { %>
<%- locals.children %>
<% } %>
<% if (_hasEdit && typeof _onEdit !== 'string') { %>
<% } %>