New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@fbaconversio/onborda

Package Overview
Dependencies
Maintainers
0
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@fbaconversio/onborda

The ultimate product tour library for Next.js

1.3.6
latest
Source
npm
Version published
Weekly downloads
42
-90.05%
Maintainers
0
Weekly downloads
 
Created
Source

Onborda - Next.js onboarding flow

NB: This is a fork of alexc-harrap's own fork of Onborda (https://github.com/Libresoft-UK/onborda/tree/main).

Onborda is a lightweight onboarding flow that utilises framer-motion for animations and tailwindcss for styling. Fully customisable pointers (tooltips) that can easily be used with shadcn/ui for modern web applications.

Getting started

# npm
npm i @fbaconversio/onborda
# pnpm
pnpm add @fbaconversio/onborda
# yarn
yarn add @fbaconversio/onborda
# bun
bun i @fbaconversio/onborda

Global layout.tsx

<OnbordaProvider tours={tours}>
  <Onborda
    cardComponent={CustomCardComponent}
    tourComponent={CustomTourComponent}
  >
    {children}
  </Onborda>
</OnbordaProvider>

Components & page.tsx

Optionally target anything in your app using the elements id attribute to overlay a backdrop and highlight the target element. If no selector or customQuerySelector is provided, the overlay will cover the entire page and the step will display as a traditional modal.

<div id="onborda-step1">Onboard Step</div>

Tailwind config

Tailwind CSS will need to scan the node module in order to include the classes used. See configuring source paths for more information about this topic.

Note _You only require this if you're not using a custom component.

const config: Config = {
  content: [
    "./node_modules/@fbaconversio/onborda/dist/**/*.{js,ts,jsx,tsx}", // Add this
  ],
};

Card Component

If you require greater control over the card design or simply wish to create a totally custom component then you can do so easily. The following props can be used to customise your card component.

PropTypeDescription
stepStepThe current Step object from your steps array, including content, title, etc.
tourTourThe current Tour object from your tours array, including title, description, etc.
toursTour[]All the current Tour object from your tours array, including title, description, etc.
currentStepnumberThe index of the current step in the steps array.
totalStepsnumberThe total number of steps in the onboarding process.
setStep(step: number | string) => void;A function to set the current step in the onboarding process.
nextStep() => voidA function to advance to the next step in the onboarding process.
prevStep() => voidA function to go back to the previous step in the onboarding process.
closeOnborda() => voidA function to close the onboarding process.
setOnbordaVisible(visible: boolean) => voidA function to set the visibility of the onboarding overlay.
arrowJSX.ElementAn SVG object, the orientation is controlled by the steps side prop
completedStepsnumber[]An array of completed step indexes/ids.
pendingRouteChangebooleanA boolean to determine if a route change is pending. Only set if the step has a selector set.
"use client";
import type { CardComponentProps } from "onborda";

export const CustomCardComponent = ({
  step,
  currentStep,
  totalSteps,
  setStep,
  nextStep,
  prevStep,
  closeOnborda,
  arrow,
  completedSteps,
  pendingRouteChange,
}: CardComponentProps) => {
  return (
    <div>
      <h1>
        {step.icon} {step.title}{" "}
        {completedSteps.contains(currentStep) ? <></> : <></>}
      </h1>
      <h2>
        {currentStep} of {totalSteps}
      </h2>
      <div>{step.content}</div>
      <button
        onClick={prevStep}
        disabled={pendingRouteChange || currentStep == 0}
      >
        Previous
      </button>
      <button
        onClick={nextStep}
        disabled={pendingRouteChange || currentStep === totalSteps - 1}
      >
        Next
      </button>
      <button onClick={closeOnborda} disabled={pendingRouteChange}>
        Finish
      </button>
      <button onClick={() => setStep(0)}>Restart</button>
      {arrow}
    </div>
  );
};

Tour Component

If you require greater control over the tour design or simply wish to create a totally custom component then you can do so easily.

PropTypeDescription
tourTourThe current Tour object from your tours array.
currentTourstringThe current tour name.
currentStepnumberThe index of the current step in the steps array.
completedStepsnumber[]An array of completed step indexes/ids.
setStep(step: number | string) => void;A function to set the current step in the onboarding process.
closeOnborda() => voidA function to close the onboarding process.
"use client";
import type { TourComponentProps } from "onborda";

export const CustomTourComponent = ({
  tour,
  currentTour,
  currentStep,
  setStep,
  completedSteps,
  closeOnborda,
}: TourComponentProps) => {
  return (
    <div className={"absolute bottom-3 left-3 w-60 p-0"}>
      {" "}
      {/* Tailwind CSS classes to position TourCard in bottom left of screen */}
      <h1>{currentTour}</h1>
      <h2>
        {currentStep} of {tour.steps.length}
      </h2>
      <h2>
        {completedSteps.length} of {tour.steps.length} completed
      </h2>
      <ul>
        {tour.steps.map((step, index) => (
          <li key={index} onClick={() => setStep(index)}>
            {step.title} {completedSteps.contans(index) ? <></> : <></>}
          </li>
        ))}
      </ul>
      <button
        onClick={closeOnborda}
        disabled={
          tour?.dismissible ? false : completedSteps.length < tour.steps.length
        }
      >
        {tour?.customCloseText || "Close"}
      </button>
    </div>
  );
};

Tour object

PropTypeDescription
tourstringThe name of the tour.
stepsStep[]An array of Step objects defining each step of the tour.
titlestringOptional. The title of the tour.
scrollContainerstringOptional. If the tour is in a scroll container, set the CSS selector of the scroll container. If not set, scroll will be calculated based on the viewport.
descriptionstringOptional. The description of the tour.
dismissiblebooleanOptional. Determines whether the user can dismiss the tour.
onComplete() => voidOptional. A function that is called when the tour is completed.
initialCompletedStepsState() => Promise<boolean[]>Optional. A client or server function that returns a promise that resolves to an array of booleans for each step. If true, the step is marked as completed on tour init.
[key: string]anyOptional. Any additional properties you wish to add. Will be available in the useOnborda hook as well as the TourCard component.
const tour: Tour = {
  tour: "firstyour",
  steps: [Step],
};

Step object

PropTypeDescription
contentReact.ReactNodeThe main content or body of the step.
idstringOptional. A unique identifier for the step. If set, step can be acitavted using setStep(step.id). Otherwise steps[] index is used.
titlestringOptional. The title of your step
iconReact.ReactNode, string, nullOptional. An icon or element to display alongside the step title.
selectorstringOptional. A string used to target an Element by id that this step refers to. Takes precedence over customQuerySelector.
customQuerySelector()=>Element | nullOptional. A client function that returns the element to target that this step refers to. Proceeded by selector.
Useful for targeting complex elements, like those from UI libraries.
clickElementOnNextstringOptional. CSS selector for an element to click automatically when proceeding to the next step.
clickElementOnPrevstringOptional. CSS selector for an element to click automatically when going back to the previous step.
clickElementOnUnsetstringOptional. CSS selector for an element to click automatically when the current step is unset using setStep().
clickElementOnSetstringOptional. CSS selector for an element to click automatically when this step is activated using setStep().
sideExtendedSide or Partial<Record<Breakpoint, ExtendedSide>>Optional. Determines where the tooltip should appear relative to the target element. Can be configured for different breakpoints (see example below).
showControlsbooleanOptional. Determines whether control buttons (next, prev) should be shown if using the default card.
scrollContainerOverridestringOptional. Override the scroll container for the step with a custom CSS selector. If not set, scroll will be calculated based on the viewport. Only used if tour.scrollContainer is set.
pointerPaddingnumberOptional. The padding around the pointer (keyhole) highlighting the target element.
pointerRadiusnumberOptional. The border-radius of the pointer (keyhole) highlighting the target element.
routestringOptional. The route to navigate to using next/navigation when this step is set.
interactablebooleanOptional. Determines whether the user can interact with the target element.
isCompleteConditions(element: Element) => booleanOptional. A client function that returns a boolean. If true, the step is marked as completed. Called when the user interacts with the target element.
onComplete() => voidOptional. A client function that is called when the step is marked as completed. Called if isCompleteConditions returns true.
observerSelectorstringOptional. A querySelector string used to target an Element/s that this step refers to. Each element found will have a MutationObserver attached with a callback to isCompleteConditions.
[key: string]anyOptional. Any additional properties you wish to add. Will be available in the useOnborda hook as well as the Card component.
nextRoutestringDeprecated. Optional. The route to navigate to using next/navigation when moving to the next step.
prevRoutestringDeprecated. Optional. The route to navigate to using next/navigation when moving to the previous step.

[!IMPORTANT] The nextRoute and prevRoute properties have been deprecated. Please use the route property instead.

[!TIP] Each Element found by observerSelector will have a data-onborda-observed attribute set to true when the observer is attached. This can be used to target the observed elements in your Tailwind classes for styling. EG data-[onborda-observed=true]:outline-warning will add a yellow outline to the observed elements.

Responsive side positioning example
const step: Step = {
  // Basic properties
  title: "Responsive Positioning Example",
  content: <>This card will position differently based on screen size</>,
  selector: "#target-element",

  // Responsive positioning
  side: {
    default: "top", // Default position for all breakpoints
    xs: "bottom", // Override for xs screens (< 480px)
    md: "left", // Override for md screens (≥ 768px)
    lg: "right", // Override for lg screens (≥ 1024px)
    xl: "customSide", // Use a custom side position for xl screens (≥ 1280px)
  },
};

Onborda Props

PropertyTypeDescription
childrenReact.ReactNodeYour website or application content.
shadowRgbstringOptional. The RGB values for the shadow color surrounding the target area. Defaults to black "0,0,0".
shadowOpacitystringOptional. The opacity value for the shadow surrounding the target area. Defaults to "0.2"
cardTransitionTransitionTransitions between steps are of the type Transition from framer-motion, see the transition docs for more info. Example: {{ type: "spring" }}.
cardComponentReact.ReactNodeThe React component to use as the card for each step.
tourComponentReact.ReactNodeThe React component to use as a list of steps for the current tour.
breakpointsPartial<Record<Breakpoint, number>> & { [key: string]: number }Optional. Override default breakpoints or add custom breakpoints for responsive positioning. Defaults to: { xs: 480, sm: 640, md: 768, lg: 1024, xl: 1280, "2xl": 1536, "3xl": 1920 }. Values represent min-width in pixels.
extendSides{ [key: string]: React.CSSProperties }Optional. Define custom side positions with specific CSS properties that can be referenced in a step's side property.
debugbooleanOptional. Console logs the current step and the target element. Defaults to false.
observerTimeoutnumberOptional. The timeout in milliseconds for the observer to wait for the target element to be available. Defaults to 5000. Observer is used to wait for the target element to be available before proceeding to the next step e.g. when the target element is on a different route.
showOnbordabooleanDeprecated Optional. Controls the visibility of the onboarding overlay, eg. if the user is a first time visitor. Defaults to false.
stepsArray[]Deprecated An array of Step objects defining each step of the onboarding process.

[!IMPORTANT] The steps property has been deprecated. Please use the OnbordaProvider.tours property instead. The showOnborda property has been deprecated. Please use the OnbordaProvider.defaultIsOnbordaVisible property instead.

<Onborda
  shadowRgb="55,48,163"
  shadowOpacity="0.8"
  cardComponent={CustomCard}
  tourComponent={CustomTour}
  cardTransition={{ duration: 2, type: "tween" }}
  breakpoints={{
    xs: 480,
    sm: 640,
    md: 768,
    lg: 1024,
    xl: 1280,
    "2xl": 1536,
    "3xl": 1920,
    custom: 2200, // Custom breakpoint
  }}
  extendSides={{
    // Define custom positioning styles
    customSide: {
      transform: "translate(-50%, 0)",
      left: "50%",
      bottom: "100%",
      marginBottom: "25px",
    },
    anotherCustomSide: {
      transform: "translate(0, -50%)",
      top: "50%",
      left: "100%",
      marginLeft: "25px",
    },
  }}
>
  {children}
</Onborda>

OnbordaProvider Props

PropertyTypeDescription
childrenReact.ReactNodeYour website or application content.
toursTour[]An array of Tour objects defining each tour of the onboarding process.
activeTourstringOptional. The id of the active tour. If set, Onborda will start tour automatically.
defaultIsOnbordaVisiblebooleanOptional. Controls the visibility of the onboarding overlay on mount. Defaults to false.
<OnbordaProvider tours={tours}>{children}</OnbordaProvider>

UseOnborda Context

The useOnborda hook provides a set of functions to control the onboarding process from any child within the OnboardaProvider. The hook returns an object with the following properties:

PropertyTypeDescription
toursTour[]An array of Tour objects defining each tour of the onboarding process.
startOnborda(tourName: string, visible?: boolean, step?: number | string) => voidA function to start the onboarding process. [visible] defaults to OnbordaProvider.defaultIsOnbordaVisible. [step] defaults to the first incomplete step.
closeOnborda() => voidA function to close the onboarding process.
curreentTourstringThe name of the current tour.
currentStepnumberThe index of the current step in the steps array.
setCurrentStep(step: number | string) => void;A function to set the current step in the onboarding process.
currentTourStepsStep[]The steps array for the current tour.
completedStepsSet<number>An array of completed step indexes/ids.
setCompletedStepsReact.Dispatch<React.SetStateAction<Set<number>>>A function to set the completed steps array.
isOnbordaVisiblebooleanA boolean to determine if the onboarding overlay is visible.
setOnbordaVisibleReact.Dispatch<React.SetStateAction<boolean>>A function to set the visibility of the onboarding overlay.
isStepChangingbooleanA boolean indicating if a step change is in progress. Useful to prevent multiple clicks while transitions are happening.
setIsStepChanging(isStepChanging: boolean) => voidA function to manually control the step changing state.
const {
  tours,
  startOnborda,
  closeOnborda,
  currentTour,
  currentStep,
  setCurrentStep,
  currentTourSteps,
  completedSteps,
  setCompletedSteps,
  isOnbordaVisible,
  setOnbordaVisible,
  isStepChanging,
  setIsStepChanging,
} = useOnborda();

Example tours array with new features

import { FirstTourInitialState } from "@app/lib/initialTourStates"; // Optional initial state from server action
const tours: Tour[] = [
  {
    tour: "firsttour",
    title: "First Tour",
    description: "This is the first tour",
    dismissible: false, // User can't dismiss the tour until all steps are completed
    customProperty: "This is a custom property passed to the Tour card",
    initialCompletedStepsState: FirstTourInitialState, // Optional server action called on tour init to get completed steps boolean array
    steps: [
      {
        icon: <>👋</>,
        title: "Tour 1, Step 1",
        content: <>First tour, first step</>,
        selector: "#tour1-step1",
        side: {
          default: "top",
          sm: "right",
          lg: "bottom",
        },
        clickElementOnNext: "#next-button", // When user clicks "Next", this element will also be clicked
        showControls: true,
        pointerPadding: 10,
        pointerRadius: 10,
        route: "/foo",
        customProperty: "This is a custom property passed to the Step card",
      },
      {
        icon: <>👋</>,
        title: "Tour 1, Step 2",
        content: (
          <>First tour, second step. To proceed please provide a value</>
        ),
        selector: "#tour1-step2-input", // target the input
        isCompleteConditions: (element) =>
          (element as HTMLInputElement)?.value?.trim() !== "", // check if the step is completed when element is interacted with
        interactable: true, // allow user to interact with the input
        side: "right",
        showControls: true,
        pointerPadding: 10,
        pointerRadius: 10,
        route: "/bar",
        clickElementOnSet: "#focus-input", // When this step is set using the setStep() function, click this element (e.g., focus an input)
      },
      {
        icon: <>👋</>,
        title: "Tour 1, Step 3",
        content: <>Thanks for settings the value</>,
        selector: "#tour1-step3",
        side: {
          default: "customSide", // Use custom positioning defined in extendSides
          lg: "bottom", // Override for larger devices
        },
        showControls: true,
        pointerPadding: 10,
        pointerRadius: 10,
        route: "/bar",
        clickElementOnUnset: "#save-button", // When leaving this step using the setStep() function, click the #save-button
      },
    ],
  },
];

Contribution

To setup the project locally, clone the repository and run the following commands:

# Install dependencies
npm install

To test the local library in a local Next.js project, run the following command in this project to setup npm link

# Create a symlink to the package
npm link

Then in your Next.js project run the following command to link the package. This will create a symlink in your Next.js project to the local package.

# Link the package
npm link onborda

To unlink the package, run the following command in your Next.js project

# Unlink the package
npm unlink onborda

If you already have the published package installed in your project, the symlink will take precedence over the published package. Ensure to push changes to this package before pushing changes to your project.

Now you can make changes to the package and see them reflected in your Next.js project. The package must be built after every change to see the changes in your Next.js project.

# Build the package
npm run build

To save rebuilding the package after every change, you can run the following command in this project to watch for changes and rebuild the package, which will in turn update the symlink in your Next.js project.

# Watch for changes and rebuild the package
npm run dev
# Cancel the watch process
^c

Keywords

react-onboarding

FAQs

Package last updated on 01 Mar 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts