Build your own JavaScript onboarding wizard

One of the goals of the development team whilst building the JavaScript onboarding wizard in Yoast SEO 3.6 was to make it generic. We love the open source community, so we made the wizard freely available for everyone. That means you can use our wizard component for your own needs! I’ll give a short explanation on how to do this, and you can find our full readme on GitHub.

The wizard uses a configuration built in the JSON datatype. The steps, fields, and custom components are set via this configuration file. The wizard uses PUT requests, containing JSON data about the fields, to send the data from the steps to your back-end that handles the settings.

Onboarding wizard settings

The onboarding wizard in Yoast SEO 3.6

Loading the wizard onto your page

The wizard is a JavaScript library you can install using NPM; we also use Sass for our stylesheets. So for the wizard to work, you need to have the following things installed and working in your project.

If you have these prerequisites installed you have to install the following node modules using:

npm install --s  <module name>

To load the styling for the wizard, add the following line into a SCSS file. This file has to be loaded on the page for the wizard.

@import "../../node_modules/yoast-components/css/all.scss";

The wizard can now be instantiated and rendered into a div element on your page. Below is some example code that shows you how to do this. The example renders the wizard in a div element with an id called wizard.

 import React from "react";
 import ReactDOM from "react-dom";
 import { OnboardingWizard } from "yoast-components";

 // Required to make the wizard work with touch screens.
 import injectTapEventPlugin from "react-tap-event-plugin";

 injectTapEventPlugin();

 class App extends React.Component {
     render() {
         return <OnboardingWizard { ...config }/>;
     }
 }

 ReactDOM.render( <App/>, document.getElementById( "wizard" ) );

Configuring the wizard

A wizard has a variable amount of steps. Each step can contain a set of predefined fields, through which the user can configure settings. A user can traverse through these steps by using the available navigation controls (a stepper and buttons). Whenever a user switches steps, the fields in the current step are saved to the server.

General configuration

The general configuration for the wizard is loaded from the config object that is supplied to the OnboardingWizard React element. The following config attributes can / should be specified:

  • Required attributes:
    • fields, object, The field definitions.
    • steps, object, The step definitions.
    • endpoint, string, The endpoint URL used to save the data submitted by the user.
    • finishUrl, string, The finish URL for the wizard to redirect the user to after completing/closing the wizard.
  • Optional attributes:
    • customComponents, object, Here you can inject custom components (fields) to be used within steps.

Fields

The input, text and possible custom component elements are defined as fields in the wizard. The fields have to be defined first, after that they can be assigned to be rendered in the different steps.

Specification

Fields have the following attributes:

  • name, string, the name of the field.
    • component, string, references the component that should be used to render the field in the component tree.
    • properties, object, contains properties that will be passed to the component when it’s rendered. This is specific for the component that is used.
    • requires, object, (optional) can be used to make sure a field is only rendered when another field has a certain value.
      • field, string, the field name for the other field.
      • value, string, the value this field has to have.
    • data, mixed, the value of the field. This can be used to set the initial state of the field.

Available components

Currently, we’ve implemented three different field components from which you can choose:

  • Choice renders a choice interface, like a group of radio buttons or a select button. Currently, the only ones available are radio buttons.
    • Properties:
      • label: The label for the input element to be rendered.
      • explanation, string, (optional) An extra explanation that is shown underneath the choice field.
      • choices: a JSON string with choices where the key represents the value and the value is an object with choice properties:
        • label, string, The label of the choice.
        • screenReaderText, string, (optional) can be used to provide a little extra context per choice for people using screenreaders.
  • Input renders a textarea.
    • properties:
      • label: The label for the input element to be rendered.
      • placeholder: placeholder text.
      • pattern: a regular expression that can be used to validate the string format. (not MVP)
      • explanation, string, (optional) An extra explanation that is shown underneath the input field.
  • HTML takes a piece of HTML and renders it. You can use this to render some paragraph of text in the steps. Purely meant for adding copy to the wizard in a generic way, not functionality.
    • properties:
      • html: The HTML to be rendered.

Custom components

It is possible to inject custom component fields into the Wizard. The custom components have to be React elements that the wizard can render. They should be implemented beforehand and they can be required and injected when instantiating by the wizard. Below is an example of how to add your custom components to the wizard’s config.

import CustomComponent1 from "/example/path/CustomComponent1";
 import CustomComponent2 from "/example/path/CustomComponent2";

 let config = {
   fields: {},
   steps: {},
   endpoint: "",
   finishUrl: "",
   customComponents: {
     CustomComponent1,
     CustomComponent2
   }
 };

 class App extends React.Component {
     render() {
         return <OnboardingWizard { ...config }/>;
     }
 };

Fields definition example:

"fields": {
   "introduction": {
     "component": "HTML",
     "properties": {
       "html": "<p>Welcome to the onboarding wizard!</p>"
     }
   },
   "favoriteColor": {
     "component": "Choice",
     "properties": {
       "label": "What is your favorite color?",
       "choices": {
         "green": {
           "label": "Green"
         },
         "purple": {
           "label": "Purple"
         },
       },
     },
     "data": "",
     "default": "purple"
   },
   "lastName": {
     "component": "Input",
     "properties": {
       "label": "What is your last name?",
     },
     "data": "{last_name}"
   },
   "shadesOfGreen": {
     "componentName": "Choice",
     "properties": {
       "label": "What shade of green do you like most?",
       "choices": {
         "darkGreen": {
           "label": "Dark green"
         },
         "lightGreen": {
           "label": "Light green"
         },
       },
     },
     "requires": {
       "field": "favoriteColor",
       "value": "green",
     },
     "data": "",
     "default": "darkGreen"
     }
 }

Setting the initial field data

The wizard loads the data for each field from its config. The data attribute for each field contains the initial state for that field. When the value of the field is changed, it’s stored in the wizard’s state and saved to the server when the user switches steps.

Steps

The fields are assigned to and rendered in steps in the wizard. When the fields are defined the steps can use them to supply information to and ask information from the users.

Specification

A Step has the following attributes:

  • id, string, identifier
    • title, string, the title of the step.
    • fields, array, list of strings referencing fields by key.

As an example lets use the fields specified above. In the config you could define the steps like this:

Steps definition example:

"steps": {
   "credentials": {
     "title": "Credentials",
     "fields" : ["lastName"]
   },
   "personalPreferences": {
     "title": "Personal preferences",
     "fields" : ["favoriteColor", "shadesOfGreen"]
   }
 }

Translations

The wizard doesn’t have a lot of copy of its own, but the strings in it are translatable. This is done in a similar way to i18n Calypso – localize.

Translations can be added to the config in the following way:

import { setTranslations } from "yoast-components/utils/i18n";

 let translations = {
   "domain": "your-textdomain",
   "locale_data": {
     "your-textdomain": {
       "Next": ["Volgende"],
       "Previous": ["Vorige"],
       "Close": ["Sluiten"]
     }
   }
 }

 setTranslations( translations );

Persisting data

The wizard uses API requests to send data to the endpoint. This endpoint is set via the configuration that’s provided to the wizard. The wizard uses jQuery for sending requests, but if it is not available, it will use a module called fetch.

For example, a step that is built up like this:

"publishingEntity": {
   "title": "Personal Data",
   "fields" : ["nameField", "lastnameField", "addressField"]
 }

The wizard will send a request containing the following parameters to the configured endpoint:

{
   "nameField": "John", 
   "lastnameField": "Doe", 
   "addressField": "Silicon valley 1", 
 }

The configured endpoint has to process this request to store the field values.

blogpost_-_onboarding_wizard_stepper

The stepper component makes it possible to traverse through the wizard

More information

We hope you’ve enjoyed this short introduction of the JavaScript onboarding wizard. This is only a small tasting of the possibilities of this library. You can find extra information in the full readme on GitHub.

Coming up next!