Driver.js

repository·master·Indexed 12 days ago

https://github.com/nilbuild/driver.js

A lightweight (~5kb gzipped), dependency-free JavaScript library for creating product tours, feature introductions, and UI overlays. It provides tools for highlighting elements, creating step-by-step guided walkthroughs with animated transitions, and implementing non-linear product hints via pulsing beacons. Features include TypeScript support, full keyboard control, and hooks for asynchronous navigation and dynamic element handling using `waitForElement`.

Tokens
30.4K
Snippets
77
Records
90
Agent score
98%

What's inside Driver.js

  1. Overview of Driver.js

    master

    Driver.js is a lightweight (~5kb gzipped), dependency-free library designed for creating product tours, feature introductions, and various page overlays. Unlike traditional tour libraries, it is highly versatile and can be used for:

    • Highlighting elements: Focus user attention on specific page components.
    • Contextual help: Displaying popovers with a dimmed background (e.g., during form filling).
    • Focus shifting: Directing user attention to specific areas.
    • Simulating 'Turn off the Lights' widgets: Dimming the background to highlight content.
    • Modals: Using it as a simple modal implementation.
    • Product Tours: Step-by-step guided walkthroughs.

    Key features include full keyboard control, TypeScript support, and hooks to manipulate elements during highlight/deselection lifecycles.

  2. Understand the difference between closing and dismissing hints

    master

    Driver.js distinguishes between closing a popover and dismissing a hint:

    • Closing: Occurs when clicking the beacon again, clicking outside the popover, or pressing <kbd>Escape</kbd>. The popover disappears, but the beacon remains on the page and can be reopened.
    • Dismissing: Occurs when the user clicks the dismissal button (defaults to "Got it"). This removes the beacon entirely for the session and triggers the onDismiss hook.

    To take control of the dismissal button behavior, use the onButtonClick option.

  3. How Driver.js configuration works

    master

    Driver.js configuration can be applied at three levels:

    1. Globally: By passing a configuration object to the driver() call.
    2. Per Step: By defining specific options within an individual DriveStep object.
    3. On the fly: By using the setConfig method while the driver is running.

    Each call to driver() creates an independent instance. Configuration, steps, and state belong to that specific instance, meaning you can run multiple independent tours on the same page without them interfering with each other.

  4. Show tour progress with showProgress

    master

    You can display the current step progress in the bottom left corner of the screen by enabling the showProgress option. By default, this option is set to false.

    import { driver } from "driver.js";
    import "driver.js/dist/driver.css";
    
    const driverObj = driver({
      showProgress: true,
      showButtons: ['next', 'previous'],
      steps: [
        { element: '#step-1', popover: { title: 'Step 1', description: 'Description' } },
        { element: '#step-2', popover: { title: 'Step 2', description: 'Description' } },
      ]
    });
    
    driverObj.drive();
  5. Create an animated tour with Driver.js

    master

    To create an animated product tour, import driver and the default CSS, then initialize the driver with the animate: true option (or simply use the duration option which implies animation). Define an array of steps, where each step targets a DOM element and provides a popover containing a title and description. Call .drive() on the driver instance to start the tour.

    Each step's popover can be further customized with side (e.g., 'left', 'right', 'top', 'bottom') and align (e.g., 'start').

    import { driver } from "driver.js";
    import "driver.js/dist/driver.css";
    
    const driverObj = driver({
      animate: true,
      showProgress: true,
      showButtons: ['next', 'previous'],
      steps: [
        {
          element: '#tour-example',
          popover: { 
            title: 'Animated Tour Example',
            description: 'Here is the code example showing animated tour.', 
            side: 'left', 
            align: 'start' 
          }
        },
        {
          popover: { 
            title: 'Happy Coding',
            description: 'And that is all!' 
          } 
        }
      ]
    });
    
    driverObj.drive();
  6. Apply custom classes to the popover

    master

    You can customize the popover's appearance by applying a custom class via the popoverClass option. This can be set globally in the main driver configuration or specifically for an individual step.

    // Global configuration
    const driverObj = driver({
      popoverClass: "my-custom-popover-class",
    });
    
    // Step-specific configuration
    const driverObj2 = driver({
      steps: [
        {
          element: "#some-element",
          popover: {
            title: "Title",
            description: "Description",
            popoverClass: "my-custom-popover-class",
          },
        },
      ],
    });
  7. Create a multi-step product tour with driver()

    master

    To create a multi-step tour, import driver from driver.js and its corresponding CSS. Initialize the driver by passing a configuration object containing a steps array. Each step defines the element to highlight and a popover containing a title and description. Finally, call .drive() on the returned object to start the tour.

    Common configuration options include showProgress: true to display a progress indicator during the tour.

    import { driver } from "driver.js";
    import "driver.js/dist/driver.css";
    
    const driverObj = driver({
      showProgress: true,
      steps: [
        { element: '.page-header', popover: { title: 'Title', description: 'Description' } },
        { element: '.top-nav', popover: { title: 'Title', description: 'Description' } },
        { element: '.sidebar', popover: { title: 'Title', description: 'Description' } },
        { element: '.footer', popover: { title: 'Title', description: 'Description' } },
      ]
    });
    
    driverObj.drive();
  8. Prevent Tour Exit using allowClose

    master

    To force users to complete a tour before they can exit, set the allowClose option to false in the driver() configuration object. When allowClose is false, the user cannot close the tour (e.g., by clicking the overlay or using escape keys) until they reach and complete the final step of the tour.

    import { driver } from "driver.js";
    import "driver.js/dist/driver.css";
    
    const driverObj = driver({
      showProgress: true,
      allowClose: false,
      steps: [
        { element: '#prevent-exit', popover: { title: 'Step 1', description: 'Description' } },
        { popover: { title: 'Final Step', description: 'The tour ends here.' } }
      ],
    });
    
    driverObj.drive();
  9. Use Driver.js via CDN (Global Window Object)

    master

    When using the CDN version, the library is not available via imports. Instead, you must access the driver and hints functions through the window object using the specific namespaces window.driver.js.driver and window.driverHints.hints.

    // Accessing the driver
    const driver = window.driver.js.driver;
    const driverObj = driver();
    
    driverObj.highlight({
      element: "#some-element",
      popover: {
        title: "Title",
        description: "Description",
      },
    });
    
    // Accessing hints
    const hints = window.driverHints.hints;
  10. Use hints alongside a tour

    master

    Hints and tours can coexist. When a tour is active, beacons are hidden and any open hint popover is closed. Once the tour ends, beacons reappear.

    A common pattern is using a hint to launch a tour by overriding the onButtonClick handler in the hint's popover configuration.

    const tour = driver({ steps: [...] });
    
    const productHints = hints({
      hints: [
        {
          element: "#whats-new",
          id: "whats-new",
          popover: {
            title: "New dashboard",
            description: "Want a quick walkthrough?",
            buttonText: "Take the tour",
            onButtonClick: (element, hint, { hints: instance }) => {
              instance.close();
              tour.drive();
            },
          },
        },
      ],
    });
  11. Customize overlay color and opacity

    master

    You can change the appearance of the Driver.js backdrop by using the overlayColor and overlayOpacity options in the driver() configuration object.

    • overlayColor: Accepts any valid CSS color string (e.g., 'red', 'blue', '#ff0000', or RGB values).
    • overlayOpacity: Controls the dimming effect of the backdrop.

    These options can be applied globally when initializing the driver instance or specifically within tour steps.

    import { driver } from "driver.js";
    import "driver.js/dist/driver.css";
    
    const driverObj = driver({
      overlayColor: 'red',
      overlayOpacity: 0.3
    });
    
    driverObj.highlight({
      popover: {
        title: 'Custom Overlay',
        description: 'The overlay is now red with 0.3 opacity.'
      }
    });
  12. Persist hint dismissals using localStorage

    master

    Driver.js manages dismissals in memory for the current session but does not persist them to storage automatically. To remember that a user has dismissed a hint across page reloads, use the onDismiss hook to save the hint's id to localStorage and filter the hints array when initializing the instance.

    const dismissed = new Set(JSON.parse(localStorage.getItem("hints") ?? "[]"));
    
    const productHints = hints({
      hints: allHints.filter(hint => !dismissed.has(hint.id)),
      onDismiss: (element, hint) => {
        dismissed.add(hint.id);
        localStorage.setItem("hints", JSON.stringify([...dismissed]));
      },
    });
    
    productHints.show();