prototype scenarios
Prototype Scenarios — side panel surfaced by /flows
Section titled “Prototype Scenarios — side panel surfaced by /flows”When a prototype captures multiple branching states (station mismatch, payment failure, battery conflict, etc.) that would be tedious to reach through linear in-device navigation, declare those states as scenarios on the flow entry in site/src/data/products.ts. The /flows page renders them as a side grid panel beside the iframe — the prototype itself stays a clean device-only shell per DESIGN.md §0.
Architecture
Section titled “Architecture”products.ts /flows page prototype iframe───────────── ─────────── ────────────────scenarios: [ renders grid on init: { slug, name, → [icon|label] tiles → params.get('scenario') icon, group }, ↓ click ↓ jumpTo(slug) ... iframe.src = ?scenario= set up state]The panel is NOT part of the prototype. The prototype receives state via the ?scenario=<slug> URL param. This keeps the device-only hard rule intact and makes scenarios reusable across multiple surfaces (e.g. an alternate “scenario explorer” tool could read the same data).
Declaring scenarios
Section titled “Declaring scenarios”In site/src/data/products.ts, add a scenarios array to the relevant flow:
{ slug: 'support-cases-v2', name: 'Support Cases (v2)', // ... kind: 'mobile', scenarios: [ { slug: 'dashboard', name: 'Dashboard', group: 'flows', icon: 'grid' }, { slug: 'station-mismatch', name: 'Station mismatch', group: 'scenarios', icon: 'alert' }, { slug: 'swap-complete', name: 'Swap complete', group: 'end-states', icon: 'check-circle' }, { slug: 'reset', name: 'Reset flow', reset: true }, ],}Fields on Scenario:
slug— must match the value the prototype’sjumpTo()function expects.name— display label under the tile. Keep short (≤ 18 chars).group— optional bucket:'flows' | 'scenarios' | 'end-states'. Renders a small group label above the cluster.icon— optional icon name from the curated set insite/src/pages/flows.astroSCENARIO_ICONS. Omit for a label-only tile.reset— marks the special reset action. Renders as a separate full-width dark button at the bottom (not in the grid).
Visual rules (the /flows panel)
Section titled “Visual rules (the /flows panel)”- Width: 360px on desktop, 280px under 1100px. The panel sits to the right of the centered iframe, with a 48px gap.
- Tiles: white surface, 1px
#EBEBEBborder, 14px radius, 14px × 10px padding. Three-column grid, 10px gap. Icon (36px circle) above 11.5px / 500 label. - Active tile (current scenario):
#dcfbe2background,#01E46Fborder, icon disc turns brand-green with white glyph. - Group label: 11px / 600 uppercase
#838383, 0.08em tracking. Sits above each cluster. - Reset button: full-width below the grid,
#202020background, white text, 12px radius. - Hover: subtle lift (
translateY(-1px)), softer shadow.
What the prototype must do
Section titled “What the prototype must do”The prototype itself owns the state setup. Implement a jumpTo(slug) function that:
- Resets transient state (active sheets, intermediate flags, timers)
- Sets
scenarioModeto the captured branch (e.g.'mismatch','payment','bat-release') - Calls
goto(<screenId>)for the right starting screen - Pre-applies any “after X” state (alerts hidden, status-cards approved, continue buttons revealed)
On init, read ?scenario=<slug> and call jumpTo(slug) if present. Reference implementation: products/rechaj-swap-app/prototypes/support-cases-v2.html.
Forbidden
Section titled “Forbidden”- An external scenarios panel inside the prototype HTML itself. Use the
scenariosarray →/flowsrendering path instead. The prototype must remain a device-only shell when opened standalone. - Icons or labels that drift from the data declaration. The grid panel is fully driven by the array — don’t hand-edit the rendered DOM.
- Adding scenarios that have no corresponding
jumpTo()branch. Clicking would noop and break trust.