Skip to content

Overlay and cursor

Overlay

installDemoOverlay(context, persona, device) before newPage(). The package already does this inside runDemoWalk / withDemoPages.

The banner is a fixed HUD — a rounded card inset from the bottom and sides so the app shows around it. It does not wrap the consumer app or rewrite html / body layout. Their 100vh, position: fixed, and modals keep the window as the containing block.

padding-bottom on <html> (and scroll-padding-bottom on <body>) is the bar height so page copy can scroll out from under it. --e2e-demo-bar-height and data-e2e-demo-reserve are that same value.

The bar sits above page chrome (z-index just under the teaching cursor). If it covers a control you need, set E2E_DEMO_OVERLAY=0.

Pass { device: 'desktop' | 'tablet' | 'mobile' } to runDemoWalk so the chip and viewport match. This site’s walk runs all three on stills.

The card shows:

  • Persona chip (colors from config)
  • Device chip (DESKTOP / TABLET / MOBILE)
  • Chapter title and SPA route
  • Current-action note (demoAnnounce)

Caption state lives in sessionStorage (e2e.demo.caption) so a full-page navigation restores the last chapter. The persona chip is e2e.demo.personademoFocus writes it from the bound walk.page[id] so stills on the shared-page fast path keep the chip in sync with the chapter. Isolated E2E_DEMO=1 windows already have one overlay per actor.

Test ids: e2e-demo-overlay, e2e-demo-persona, e2e-demo-device, e2e-demo-banner, e2e-demo-banner-title, e2e-demo-banner-route, e2e-demo-banner-note.

Cursor

A SVG pointer (e2e-demo-cursor) is installed on every runDemoWalk, including the fast CI path. It stays hidden until aimed at a control (demoClick, fillField, demoPoint).

On stills, each teaching beat uses one gold ring (e2e-demo-cursor-ring):

  1. Aim the pointer
  2. Hold the ring (storyboard shot captures here)
  3. Release — fade that same ring when E2E_DEMO=1 and video is off, snap-remove on CI
  4. Click, type, or leave (demoPoint has no click)

On video the pulse plays then the click: pointer arrives, ring scales out and fades, click lands when that pulse is done, then a short pause. Video does not hold a static ring or take a still. Stills freeze CSS so the storyboard is the held ring.

The overlay is on by default for stills and video. Set E2E_DEMO_OVERLAY=0 to hide the bar. demoFocus still writes the chapter and the persona chip into the bar when it is shown; pacing dwells stay on E2E_DEMO=1 only.

Why init scripts are not minified

Playwright calls Function#toString() and evals that source in the page. The paint functions take a serializable args object only. Closing over getDemoWalkConfig() would break after the lift into the browser.

Released under the MIT License.