Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 2x 2x 2x 90x 90x 90x 2x 90x 90x 90x 90x 90x 90x 90x 90x 90x 90x 90x 90x 90x 3x 3x 3x 3x 3x 3x 3x 3x 3x | /**
* The guided tutorial's offer (ยง30): the buttons *About* and the landing page
* both draw, so the two say the same thing about the same place kept.
*
* One invited answer at a time, filled: *play* for a reader who has not begun,
* *resume* for one who has, *play again* for one who finished. Starting over
* is offered beside a resume, quietly, rather than as a second filled button,
* since a reader who left half way is far more often coming back than starting
* again.
*/
import type { TourProgress } from '../state/tour'
import { el } from './dom'
import { icon } from './icons'
/** Where the tutorial is played from. */
export type TutorialStart = 'start' | 'resume'
/** What the filled button says, from what was kept. */
export function tutorialLabel(progress: TourProgress | null): string {
if (progress !== null && !progress.finished) return `resume at step ${progress.index + 1} of ${progress.total}`
return progress?.finished === true ? 'play the tutorial again' : 'play the tutorial'
}
/** The filled button, and *start over* beside it while there is a place to resume from. */
export function tutorialButtons(
progress: TourProgress | null,
play: (from: TutorialStart) => void,
options: { class?: string } = {},
): HTMLElement[] {
const resumable = progress !== null && !progress.finished
const invited = el(
'button',
{ class: `btn btn-primary${options.class === undefined ? '' : ` ${options.class}`}`, type: 'button' },
icon('play', { size: 12 }),
el('span', { text: tutorialLabel(progress) }),
)
invited.addEventListener('click', () => play(resumable ? 'resume' : 'start'))
if (!resumable) return [invited]
const over = el('button', {
class: 'btn btn-quiet',
type: 'button',
text: 'start over',
title: 'Begin again at the first step, in a tab of its own',
})
over.addEventListener('click', () => play('start'))
return [invited, over]
}
|