spotlight-tour

Onboarding tours with a camera effect

The page pulls back, and each element you want to show flies out to the front of the screen. Or the camera moves onto the real element and the user has to use it to move on. Plain JavaScript, no dependencies.

Open the demo app →

Kinds of steps

Each card is a real element. Try it runs a one-step tour on it.

Spotlight

The default. A copy of the element flies out and grows. Nothing to do but read.

{ target, title, text }
Revenue this month $48.2k▲ 12%

Real element

The camera moves onto the element in place. For things styled by their parents, like a table row.

{ target, title, text, mode: 'real' }
VoucherCaptured by
TR-1041Ana López
TR-1042Luis Pérez

Click

The user clicks the real element. Your app's own handler runs.

action: { type: 'click' }

Type

The step is done once the field isn't empty. Arrow keys move the caret, not the tour.

action: { type: 'input' }

Change

For selects, checkboxes, and radios: done when the value changes.

action: { type: 'change' }
Off

Until a result

Done when a condition holds, not on a raw event. The spotlight grows with the element.

action: { until: () => faq.open }
What counts as a seat?

Anyone who can log in. Viewers are free.

Intercept

The click counts, but the app never sees it. Teach the save button without saving.

action: { type: 'click', intercept: true }
Project “Apollo” is safe

Install

From npm, or from a CDN with a <script> tag.

npm install spotlight-tour
<script src="https://unpkg.com/spotlight-tour@0.4/dist/index.umd.js"></script>

Use it

Create the tour once, give it steps, and start it. Steps with action are interactive.

import SpotlightTour from 'spotlight-tour';

const tour = new SpotlightTour({
  steps: [
    { target: '#nav', title: 'Main navigation', text: 'Every section is here.' },
    {
      target: '#save',
      title: 'Save your work',
      text: 'Click it. Nothing is saved during the tour.',
      action: { type: 'click', intercept: true },
    },
  ],
});

tour.start();
  • Async steps. onEnter can return a promise (a route change); the tour waits and then looks for the element.
  • Missing elements are skipped after targetTimeout instead of leaving the user stuck.
  • Saving nothing. Use intercept on steps that save, and block writes in your HTTP client while tour.isActive.