Coder Social home page Coder Social logo

onboarder's Introduction

Onboarder

There are a lot of react steppers/wizards/onboarding libs out there. Onboarder is different:

  • Tiny
  • Non-linear - Jump between steps, lib predicts rest of the way and time taken
  • 0 dependencies - Build your UI or use our
  • Easy setup
  • Typed API

Install

npm install @guestbell/onboarder --save

or

yarn add @guestbell/onboarder

Demo

Complex UI or Simple example

Getting started

Following example will show you how to create wizard with:

  • Loop step (exit loop based on rules)
  • Step with form validation
  • Step with error message
  1. Put your imports in place
import Onboarder, { Steps, Structure } from "@guestbell/onboarder";
  1. Create state for your steps
type OnboarderState = {
  firstStep: never;
  loopStep: { 
    counter: number; 
    isDirty: boolean; 
    errorMessage?: string 
  };
  afterLoopStep: never;
  textStep: { message: string };
  finalStep: never;
};
  1. Create steps strongly typed with the help of generic Steps type. Each object key is a step
const steps: Steps<OnboarderState> = {
  firstStep: { Component: () => <>First step</> },
  loopStep: {
    Component: ({ setState, state }) => (
      <>
        <div>Loop step</div>
        {state.errorMessage && <div>Error: {state.errorMessage}</div>}
        <button
          onClick={() =>
            setState({ ...state, counter: state.counter + 1, isDirty: true })
          }
        >
          {state.counter.toString()}
        </button>
      </>
    ),
    initialState: {
      counter: 0,
      isDirty: false,
    },
    // Cleanup
    afterNext: ({ state, setState }) => {
      setState({ ...state, isDirty: false, errorMessage: undefined });
    },
    // On the flight validation that fires when you click next
    beforeNext: ({ state, setState }) => {
      if (state.counter < 2) {
        setState({
          ...state,
          errorMessage: "Increment to at least 2 because rules",
        });
        return false;
      }
      return true;
    },
  },
  afterLoopStep: {
    Component: ({ nextStep }) => (
      <>{nextStep === "loopStep" ? "We are looping" : "We're done looping."}</>
    ),
  },
  textStep: {
    Component: ({ setState, state }) => (
      <>
        <input
          value={state.message}
          onChange={(e) => setState({ ...state, message: e.target.value })}
        />
        <br />
        Message: {state.message}
      </>
    ),
    initialState: {
      message: "",
    },
  },
  finalStep: {
    Component: () => <>All done!!!</>,
  },
};
  1. Define structure - this tells the lib how to jump between steps
const structure: Structure<OnboarderState> = {
  firstStep: () => ({ loopStep: 1 }),
  loopStep: (state) => ({
    afterLoopStep: state.loopStep.isDirty ? 1 : -1,
  }),
  afterLoopStep: (state) => ({
    loopStep: state.loopStep?.counter < 3 ? 1 : -1,
    textStep: state.loopStep?.counter >= 3 ? 1 : -2,
  }),
  textStep: (state) => ({
    finalStep: (state.textStep?.message && 1) || -1,
  }),
};

Notice how the object has same (optional) keys like our steps. Each gets passed a global state, and returns an object with same (optional) keys like our steps. Values of this object work like this: a) Negative Number or zero means the step is allowed, but disabled based on a condition b) Positive Number means the step is allowed, actual number gives step priority, smaller number means higher priority c) Undefined or key missing means the step is never allowed 5. Put it all together

<Onboarder
  steps={steps}
  initialStep="firstStep"
  // array because multiple steps can be final
  finalSteps={['finalStep']}
  structure={structure}
  StepContainer={SimpleStepContainer}
/>
  1. Bonus: Add simple UI This example already works, but let's add some simple UI. You do this by providing a StepContainer prop to <Onboarder/>
import { StepContainerComponentProps } from "@guestbell/onboarder";

function SimpleStepContainer<TState extends {}>(
  props: React.PropsWithChildren<StepContainerComponentProps<TState>>
) {
  const {
    children,
    goToNextStep,
    hasNextStep,
    goToUndoStep,
    hasUndoStep,
    hasRedoStep,
    goToRedoStep,
    reset,
  } = props;
  return (
    <div>
      {children}
      <div style={{ marginTop: "1rem" }}>
        <button onClick={reset}>Reset</button>
        <button onClick={goToUndoStep} disabled={!hasUndoStep}>
          Previous
        </button>
        <button onClick={goToRedoStep} disabled={!hasRedoStep}>
          Next
        </button>
        <button onClick={goToNextStep} disabled={!hasNextStep}>
          Continue
        </button>
      </div>
    </div>
  );
}
  1. Done! You can see this example on github

API

Here

FAQ

How can I add my extra props to the step?

Notice that Steps has 2 generic parameters. First is the type of the state, you can use the second generic parameter to introduce extra props to your step.

How can I fire an action before going to next step?

Each step has a beforeNext async function. Use it to handle your logic. Return false if the navigation should be prevented.

How do I clean up step state after navigation?

Each step has a afterNext async function. Use it for cleanup.

Created and sponsored by

  • GuestBell - Customer centric online POS for Hotels and short terms stays.

Contributing

  1. Fork it!
  2. Create your feature branch: git checkout -b my-new-feature
  3. Commit your changes: git commit -am 'Add some feature'
  4. Push to the branch: git push origin my-new-feature
  5. Submit a pull request :D

License

MIT

onboarder's People

Contributors

peterkottas avatar

Stargazers

 Charlie Oliver avatar Veronica Brazdil avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.