A step that sets its own scene
A step that opens a closed section and waits for the address to load into it, so the postcode field can be lit, and closes the section again afterwards.
const story = { id: 'step-setup', steps: [ { id: 'intro', target: '[data-open]', message: 'The postcode field is inside this section, and the section is ' + 'closed. Press Next and watch who opens it.', }, { // A step with nothing to point at — DESIGN.md, **A step that waits**. // Leko waits for no handler, so the wait is written here instead. id: 'reading', message: 'Reading the address off the account…', awaits: 'address-loaded',
// DESIGN.md, **The wait starts the work it waits for, and that // placement is the rule**. onEnter: () => { at('[data-details]').hidden = false void loadAddress() },
// DESIGN.md, **Every `onEnter` gets its `onLeave`**. onLeave: (_step, next) => { if (next?.id !== 'postcode') at('[data-details]').hidden = true }, }, { id: 'postcode', // A selector, so this is genuinely resolved after the step above // rather than captured while the story was being built. target: 'input[name="postcode"]', message: 'The tour opened the section, waited, and then measured.',
// The half that closes it once the tour is past the field. Without it // the section stays open for the rest of the tour, and the user is // left with a page the tour rearranged. onLeave: () => { at('[data-details]').hidden = true }, }, { id: 'confirm', target: '[data-confirm]', message: 'And the section is closed again, because onLeave closed it.', }, ],} satisfies LekoStory// The application's own function, written where the application would write// it — DESIGN.md, **Signals and steps**.loadAddress = async () => { await new Promise((resolve) => setTimeout(resolve, 700)) at('input[name="postcode"]').setAttribute('value', '150-0001') leko.reached('address-loaded')}