A bar that pins, and a table head that pins inside a panel
One filter button lit twice, once before its bar pins to the top of the screen and once after, and a table head pinned inside a scrolling panel; the hole stays on each across the pin.
/** Far enough past the bar's pin that nothing of the hero is left on screen. */const pastThePin = (): void => { const hero = at('.sticky-case .sticky-hero').getBoundingClientRect() window.scrollTo({ top: hero.bottom + window.scrollY + 240, behavior: 'instant' })}
const story = { id: 'sticky-header', // The page and the panel both start where the first step needs them, // however the last run left them. onEnter() { window.scrollTo({ top: 0, behavior: 'instant' }) at('.sticky-case [data-panel]').scrollTo({ top: 0, behavior: 'instant' }) }, steps: [ { id: 'riding', target: { elements: '[data-only-mine]', interactive: true }, message: 'The hero is still above the bar, so the bar is riding the page ' + 'and this hole is cut in the page. Scroll down until the bar ' + 'stops at the top of the screen: the hole comes with it across ' + 'the pin and stays on the button, and once there is no room above ' + 'the bar this message moves below it. Scroll back up and press ' + 'Only mine.', }, { id: 'pinned', target: { elements: '[data-only-mine]', interactive: true }, // The application takes the page past the pin before the step is // drawn, and the step is then drawn against where the page ended up // — DESIGN.md, **The target is resolved after `onEnter` returns**. A // scroll of Leko's own could not do this: it brings a target to the // middle of the port, and the middle of the port is never past a // pin. DESIGN.md, **"Past the pin" is not a second destination**. onEnter: pastThePin, message: 'The same button, drawn with the bar already pinned — so this ' + 'hole was cut on the viewport, the way a fixed target’s is. ' + 'Scroll back up past the hero, which is the other side of the ' + 'pin from where this was drawn: the hole rides down with the bar. ' + 'Press Only mine again.', }, { id: 'in-a-panel', target: { elements: '[data-sort]', interactive: true }, scroll: true, onEnter() { at('.sticky-case [data-panel]').scrollTo({ top: 260, behavior: 'instant' }) }, message: 'This head is held against the top of the panel, not the screen, ' + 'so its hole is glued to the panel’s scrollport. Scroll the rows ' + 'inside the panel both ways — up past the pin, where the head ' + 'rides its own rows again, as well as down — and then the page ' + 'itself. The hole stays on the head through all of it. Press ' + 'Status to sort.', }, ],} satisfies LekoStory