Ending a Tour

A tour ends when the user finishes the last step, or leaves early with the close button, the Escape key or a click on the overlay. The examples below show how to step in before the tour closes, and how to find out which way it ended.

Confirm on Exit

You can use the onDestroyStarted hook to add a confirmation dialog or some other logic when the user tries to exit the tour. In the example below, we ask for confirmation only when the user leaves before finishing the tour.

Confirm on Exit

import { driver } from "driver.js";
import "driver.js/dist/driver.css";

const driverObj = driver({
  showProgress: true,
  steps: [
    { element: '#confirm-destroy-example', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\'s walk you through it.', side: "left", align: 'start' }},
    { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: "bottom", align: 'start' }},
    { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: "bottom", align: 'start' }},
    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }
  ],
  // onDestroyStarted is called when the user tries to exit the tour
  onDestroyStarted: (element, step, { reason }) => {
    if (reason === "done" || confirm("Are you sure?")) {
      driverObj.destroy();
    }
  },
});

driverObj.drive();

Note: By overriding the onDestroyStarted hook, you are responsible for calling driverObj.destroy() to exit the tour.

Prevent Exit

You can also prevent the user from exiting the tour using allowClose option. This option is useful when you want to force the user to complete the tour before they can exit.

In the example below, you won’t be able to exit the tour until you reach the last step.

Prevent Exit

import { driver } from "driver.js";
import "driver.js/dist/driver.css";

const driverObj = driver({
  showProgress: true,
  allowClose: false,
  steps: [
    { element: '#prevent-exit', popover: { title: 'Animated Tour Example', description: 'Here is the code example showing animated tour. Let\'s walk you through it.', side: "left", align: 'start' }},
    { element: 'code .line:nth-child(1)', popover: { title: 'Import the Library', description: 'It works the same in vanilla JavaScript as well as frameworks.', side: "bottom", align: 'start' }},
    { element: 'code .line:nth-child(2)', popover: { title: 'Importing CSS', description: 'Import the CSS which gives you the default styling for popover and overlay.', side: "bottom", align: 'start' }},
    { popover: { title: 'Happy Coding', description: 'And that is all, go ahead and start adding tours to your applications.' } }
  ],
});

driverObj.drive();

Finished or Closed

onDestroyStarted and onDestroyed receive reason in their options, telling you why the tour ended:

Use it to mark onboarding as complete only when the user actually finished it, or to log the step where users drop off. Finish the tour below, or leave it early, to see the reason.

Track Completion

import { driver } from "driver.js";
import "driver.js/dist/driver.css";

const driverObj = driver({
  steps: [
    // ...
  ],
  onDestroyed: (element, step, { reason, index }) => {
    if (reason === "done") {
      markOnboardingComplete();
    } else {
      trackDropOff({ reason, step: index });
    }
  },
});

driverObj.drive();

Note: A destroy() you call from a hook keeps the reason of the user action that started it. In the Confirm on Exit example above, onDestroyed gets "close", not "api".