Boarding.js

repository·main·Indexed 40 days ago

https://github.com/josias-r/boarding.js

A zero-dependency vanilla JavaScript engine for creating user onboarding tours, feature introductions, and UI overlays. It allows developers to highlight specific elements and attach customizable popovers to guide users through an application. Key features include multi-step guided tours via defineSteps(), asynchronous action handling with preventMove() and continue(), and flexible popover positioning and alignment.

Tokens
12.1K
Snippets
42
Records
48
Agent score
100%

What's inside Boarding.js

  1. Handle asynchronous actions during tours

    main

    If you need to perform an asynchronous task (like fetching data or waiting for an animation) before moving to the next step, use preventMove() inside lifecycle hooks like prepareElement, onNext, or onPrevious. This pauses the tour. Once your task is complete, call continue() to resume the movement. If your logic might never reach a completion state, use clearMovePrevented() to clean up the paused state.

    // Inside a step definition or event handler
    stepDefinition.onNext = async (element) => {
      boarding.preventMove(); // Pause the tour
      
      await performAsyncWork();
      
      boarding.continue(); // Resume the tour
    };
  2. Handle asynchronous actions between tour steps

    main

    If you need to perform an asynchronous action (like waiting for an element to mount or an animation to finish) before moving to the next step, use the onNext or onPrevious callbacks.

    1. Call boarding.preventMove() inside the callback to halt the transition.
    2. Perform your async task.
    3. Call boarding.continue() to resume the tour transition.
    const boarding = new Boarding();
    
    boarding.defineSteps([
      {
        element: "#first-element-introduction",
        popover: {
          title: "Title on Popover",
          description: "Body of the popover",
          preferredSide: "left",
        },
      },
      {
        element: "#second-element-introduction",
        popover: {
          title: "Title on Popover",
          description: "Body of the popover",
          preferredSide: "top",
        },
        onNext: () => {
          // Prevent moving to the next step
          boarding.preventMove();
    
          // Perform some action or create the element to move to
          // And then move to that element
          setTimeout(() => {
            boarding.continue();
          }, 4000);
        },
      },
      {
        element: "#third-element-introduction",
        popover: {
          title: "Title on Popover",
          description: "Body of the popover",
          preferredSide: "right",
        },
      },
    ]);
    
    boarding.start();
  3. Create a multi-step feature introduction

    main

    To create a guided tour or feature introduction, use defineSteps() to register an array of step objects, then call start() to begin the tour. Each step defines an element to highlight and an optional popover containing information.

    const boarding = new Boarding();
    
    // Define the steps for introduction
    boarding.defineSteps([
      {
        element: "#first-element-introduction",
        popover: {
          className: "first-step-popover-class",
          title: "Title on Popover",
          description: "Body of the popover",
          preferredSide: "left",
        },
      },
      {
        element: "#second-element-introduction",
        popover: {
          title: "Title on Popover",
          description: "Body of the popover",
          preferredSide: "top",
        },
      },
      {
        element: "#third-element-introduction",
        popover: {
          title: "Title on Popover",
          description: "Body of the popover",
          preferredSide: "right",
        },
      },
    ]);
    
    // Start the introduction
    boarding.start();
  4. Import Boarding.js in a module bundler

    main

    If you are using a module bundler (like Webpack, Vite, or Rollup), import the Boarding class and the necessary CSS files directly into your JavaScript entry point.

    import { Boarding } from "boarding.js";
    import "boarding.js/styles/main.css";
    // optionally include the base theme
    import "boarding.js/styles/themes/basic.css";
  5. Create a multi-step guide with defineSteps() and start()

    main

    To create a sequential tour, use defineSteps() to register an array of step definitions, then call start() to begin the tour. You can control the flow using next() and previous().

    const boarding = new Boarding(boardingOptions);
    
    boarding.defineSteps([
      stepDefinition1,
      stepDefinition2,
      stepDefinition3,
      stepDefinition4,
    ]);
    
    boarding.start(); // Starts driving through the defined steps
    
    // Navigation methods:
    boarding.next();
    boarding.previous();
    boarding.hasNextStep();
    boarding.hasPreviousStep();
  6. Install Boarding.js

    main

    You can install Boarding.js via npm or yarn, or import it directly from a CDN. If using a module bundler, ensure you also import the required CSS files for the library to render correctly.

    yarn add boarding.js
    npm install boarding.js
    <script type="module">
      import { Boarding } from "https://unpkg.com/boarding.js/dist/main.js";
    </script>
    <link rel="stylesheet" href="https://unpkg.com/boarding.js/styles/main.css" />
    <!-- optionally include the base theme -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/boarding.js/styles/themes/basic.css"
    />
  7. Understand BoardingExitReason

    main

    The BoardingExitReason type defines the possible reasons why an overlay might be reset or cleared. This is passed to the onReset callback in OverlayTopLevelOptions.

    • cancel: The user or system cancelled the current tour/boarding process.
    • finish: The boarding process completed successfully.
  8. Handle asynchronous actions with preventMove and continue

    main

    If a step requires an asynchronous action (like waiting for an API call or a UI transition) before moving to the next step, use the preventMove() and continue() pattern.

    1. Inside a step's lifecycle hook (like onNext or prepareElement), call boarding.preventMove().
    2. Perform your async task.
    3. Call boarding.continue() to resume the movement (next, previous, start, or highlight) that was interrupted.
    // Inside a step definition
    const step = {
      element: '#target',
      onNext: async () => {
        boarding.preventMove();
        
        // Perform async work
        await performAsyncSetup();
        
        // Resume the tour
        boarding.continue();
      }
    };
  9. Customize popover appearance and behavior

    main

    The popover configuration within a step allows for fine-grained control over how the information is presented:

    • title: The heading of the popover (supports HTML).
    • description: The body text of the popover (supports HTML).
    • preferredSide: Where the popover should appear ('top', 'bottom', 'left', or 'right').
    • alignment: The alignment of the popover ('center', 'start', or 'end').
    • showButtons: Boolean to show/hide navigation buttons.
    • nextBtnText: Custom text for the next button.
    • className: A custom CSS class for the popover container.
  10. Define a step for a tour or single highlight

    main

    A step definition describes what element to highlight and what content to show in the popover. You can pass a step definition directly to highlight() for a single-element tour, or use them within defineSteps() to create a multi-step guide. Step-level options (like doneBtnText or onNext) will override the global Boarding configuration.

    const stepDefinition = {
      element: "#some-item", // Query selector string or Node to be highlighted
      popover: {
        className: "popover-class", // Additional className for this specific popover
        title: "Title", // Title on the popover
        description: "Description", // Body of the popover
        showButtons: false, // Do not show control buttons in footer
        doneBtnText: "Done",
        closeBtnText: "Close",
        nextBtnText: "Next",
        prevBtnText: "Previous",
        preferredSide: "top", // Preferred side for popover rendering
        alignment: "start", // Alignment on the preferred side
        onPopoverRender: (el) => {
          // Make changes to the actual popoverElements once they get rendered.
        },
      },
      prepareElement: () => {}, // Called *before* moving to this step
      onNext: (Element) => {}, // Overwrite original onX eventhandlers for this step
    };
  11. Configure Boarding.js global options

    main

    When initializing a new Boarding instance, you can provide a configuration object to define global behaviors such as animation, overlay appearance, button text, and lifecycle event handlers. These settings apply to all steps unless overridden in a specific step definition.

    const boarding = new Boarding({
      className: "scoped-class", // className to wrap boarding.js popover
      animate: true, // Whether to animate or not
      opacity: 0.75, // Overlay opacity (0 means only popovers and without overlay)
      padding: 10, // Distance of element from around the edges
      allowClose: true, // Whether the click on overlay should close or not
      overlayClickNext: false, // Whether the click on overlay should move next
      overlayColor: "rgb(0,0,0)", // Fill color for the overlay
      doneBtnText: "Done", // Text on the final button
      closeBtnText: "Close", // Text to the close button for this step
      nextBtnText: "Next", // Next button text for this step
      prevBtnText: "Previous", // Previous button text for this step
      showButtons: false, // Do not show control buttons in footer
      keyboardControl: true, // Allow controlling through keyboard (escape to close, arrow keys to move)
      scrollIntoViewOptions: {
        behaviour: "smooth",
      }, // Options for scrollIntoView(). Set to "no-scroll" to disable.
      onBeforeHighlighted: (HighlightElement) => {},
      onHighlighted: (HighlightElement) => {},
      onDeselected: (HighlightElement) => {},
      onReset: (HighlightElement) => {},
      onStart: (HighlightElement) => {},
      onNext: (HighlightElement) => {},
      onPrevious: (HighlightElement) => {},
      strictClickHandling: true, // "block-all", true (isolate to highlighted element), or false
      onPopoverRender: (el) => {
        // Make changes to the actual popoverElements once they get rendered.
      },
    });
  12. Initialize Boarding with BoardingOptions

    main

    To use Boarding.js, instantiate the Boarding class with an optional BoardingOptions object. This object allows you to configure global behaviors for the onboarding session, such as animation, overlay styling, and interaction rules.

    Key configuration options include:

    • strictClickHandling: Determines if only the highlighted element can be clicked. Values can be 'block-all' (blocks all clicks), a boolean (allows only the element), or undefined (default).
    • animate: Boolean to enable/disable overlay animations.
    • padding: Spacing around the highlighted element.
    • radius: Rounded corners for the cutout.
    • allowClose: Whether clicking outside the element or pressing Escape closes the session.
    • overlayClickNext: Whether clicking outside the element triggers the next() action.
    • keyboardControl: Enables/disables arrow key navigation.
    • onReset: Callback triggered when the session ends.
    import Boarding from './lib/boarding';
    
    const boarding = new Boarding({
      strictClickHandling: 'block-all',
      animate: true,
      padding: 10,
      radius: 5,
      allowClose: true,
      overlayClickNext: false,
      onReset: (reason) => console.log('Session ended:', reason)
    });