Skip to content

Flows & Steps

A flow is a state machine that defines your tour. Each state contains an array of steps — the individual tooltips, spotlights, and actions your users see.

Flow Definition

ts
const flow = gf.createFlow({
  id: 'onboarding',
  initial: 'setup',
  context: { completedSteps: 0 },
  states: {
    setup: {
      steps: [
        { id: 'profile', content: { title: 'Set up your profile' }, target: '#profile-form' },
        { id: 'avatar', content: { title: 'Add a photo' }, target: '#avatar-upload' },
      ],
      on: { NEXT: 'features' },
      onExit: (ctx) => { ctx.completedSteps++ },
    },
    features: {
      steps: [
        { id: 'dashboard', content: { title: 'Your dashboard' }, target: '#dashboard' },
      ],
      final: true,
    },
  },
})

Step Configuration

Each step describes a single tooltip or action in the tour.

FieldTypeDescription
idstringUnique step identifier
targetstring | Element | nullCSS selector or DOM element to anchor to
contentStepContent | () => StepContentTitle, body, or raw HTML
placementPopoverPlacementTooltip position relative to target
showIf(ctx) => booleanConditionally skip this step
clickThroughbooleanAllow clicks to pass through the spotlight
scrollIntoViewbooleanAuto-scroll target into view (default true)
actionsStepAction[]Override default next/prev/skip buttons

StepContent

ts
interface StepContent {
  title?: string
  body?: string
  html?: string  // raw HTML (use with caution)
}

Content can also be a function (sync or async) that returns StepContent, enabling dynamic content:

ts
{
  id: 'user-greeting',
  content: async () => ({
    title: `Welcome back, ${await fetchUserName()}!`,
    body: 'Let\'s pick up where you left off.',
  }),
  target: '#header',
}

Placements

Available PopoverPlacement values:

top top-start top-end bottom bottom-start bottom-end left left-start left-end right right-start right-end center

Conditional Steps

Use showIf to conditionally include or skip steps based on context:

ts
{
  id: 'admin-panel',
  content: { title: 'Admin Settings' },
  target: '#admin',
  showIf: (ctx) => ctx.roles?.includes('admin') ?? false,
}

Custom Actions

Override the default navigation buttons:

ts
{
  id: 'feedback',
  content: { title: 'How was the tour?' },
  target: '#feedback',
  actions: [
    { label: 'Great!', action: 'end' },
    { label: 'Show me more', action: 'next' },
    { label: 'Skip', action: 'skip' },
  ],
}

Released under the MIT License.