Wizard
Examples
Wizard example
This example shows a simple Wizard component with the following features:
- Three different tabs
- Navigation using Next and Previous buttons
- Validation of data before navigating away from the first page
- A cancel option that redirects the user to the second page
- A simple progress bar
The following sections explain the different steps to define a basic Wizard using the components from the @jutro/wizard-next package.
The Wizard implementation requires:
- Definition of the different Wizard pages that can be displayed
- Definition of the Wizard layout: how the wizard is displayed, including breakpoint alternatives
- Definition of the custom elements like the action bar and progress indicator
- Definition of the Wizard steps: routes and alternatives, for example where the user is directed after completing a step
- The composition of the Wizard by using all the previously defined elements
1. Define the wizard pages
Defining a wrapper component is the recommended approach for the Wizard pages definition. Each Wizard step must reference a component that either wraps or extends WizardPage.
The following example shows how to create the page components for the previous Wizard.
import { useState } from 'react';
import { WizardPage } from '@jutro/wizard-next';
import { Checkbox } from '@jutro/components';
import { useLocation } from 'react-router-dom';
const TheFirstPage = ({ id, wizardPageProps }) => {
const location = useLocation();
const [valid, setValid] = useState(false);
const [stateMessages, setStateMessages] = useState(null);
const firstStepCheckboxChanged = (e, value) => {
setValid(value);
};
const wizardPageOnNext = () => {
if (!valid) {
setStateMessages({
error: ['Select this checkbox to go to the next page'],
});
}
// if false is returned, the default next event does not continue
return valid;
};
return (
<WizardPage
id={id}
{...wizardPageProps}
onNext={wizardPageOnNext}
location={location}
title="First page">
<span>Here you can add your content</span>
<Checkbox
label="This is mandatory to continue"
required={true}
stateMessages={stateMessages}
onChange={firstStepCheckboxChanged}
/>
</WizardPage>
);
};
const AnotherWizardPage = ({ id, wizardPageProps }) => {
const location = useLocation();
return (
<WizardPage
id={id}
{...wizardPageProps}
location={location}
title="Second page">
<span>Another wizard page</span>
</WizardPage>
);
};
const LastWizardPage = ({ id, wizardPageProps }) => {
const location = useLocation();
return (
<WizardPage
id={id}
{...wizardPageProps}
location={location}
title="The last page">
<span>The last wizard page</span>
</WizardPage>
);
};
Apart from the page definition, the example has a validation mechanism implemented for the first page which, in case of invalid data, prevents the transition to the next page.
2. Define the layout
Define the Wizard page structure for the different breakpoints.
const layout = {
desktop: { colStart: 1, colSpan: 12 },
tablet: { colStart: 1, colSpan: 10 },
phone: { colStart: 1, colSpan: 6 },
};
3. Define any custom elements
In this example, we are using components from the base configuration. See the Customizing the progress bar and Customizing the action bar sections for custom implementation references.
4. Define the wizard steps
You must specify the corresponding route and the assigned WizardPage component for each step.
const steps = [
{
id: 'wizard.firstpage',
route: 'firstpage',
title: 'First page',
component: TheFirstPage,
},
{
id: 'wizard.secondpage',
route: 'secondpage',
title: 'Second page',
component: AnotherWizardPage,
},
{
id: 'wizard.lastpage',
route: 'lastpage',
title: 'Last page',
component: LastWizardPage,
},
];
5. Compose the wizard
Bring all the elements defined so far together to compose the wizard.
The Cancel option is added by defining a cancelPath property, while the Next and Previous buttons use the steps definition order by default.
import { Wizard } from '@jutro/wizard-next';
import { useLocation } from 'react-router-dom';
<Wizard
layout={layout}
baseRoute={'/'}
basePath={'/'}
location={useLocation}
cancelPath="secondpage"
steps={steps}
/>;
Customizing the progress bar
Use renderProgressBar to turn off the progress bar, or render a custom progress bar.
- To turn off the progress bar, set
renderProgressBartonullorfalse. - To customize the progress bar, set
renderProgressBarto a render prop.
This render prop expects a function that receives one parameter, an object with the basePath prop and an array of the steps which are both passed to the Wizard.
The following is an example of a custom progress bar made using the layout and steps defined in the previous examples:
import { useLocation } from 'react-router-dom';
import { Wizard } from '@jutro/wizard-next';
import { StepProgressBar } from '@jutro/components';
const customProgressBar = ({ basePath, steps }) => {
const { pathname } = useLocation(); // calc if the subroute a match
const stepRoutes = steps.map((step) => step?.route);
const currentStep = stepRoutes.indexOf(pathname.replace(`${basePath}/`, ''));
const barSteps = steps.map((step) => {
step.active = false;
return step;
});
if (currentStep >= 0) barSteps[currentStep].active = true;
return <StepProgressBar steps={barSteps} />;
};
<Wizard
layout={layout}
baseRoute={'/'}
basePath={'/'}
location={useLocation}
cancelPath="firstpage"
steps={steps}
renderProgressBar={customProgressBar}
/>;
For more information about render props, see the React docs.
Customizing the action bar
Use renderActionBar to disable the action bar, or render a custom action bar.
- To disable the action bar, set
renderActionBartonullorfalse. - To customize the action bar, set
renderActionBarto a render prop.
The render prop is a function that receives two parameters:
resolvedPropsForButtons- this includes route paths which are calculated by the Wizard based on the flow and the current step.actionBarLayout- the same prop passed into Wizard to set the layout of the action bar. If you are using a custom action bar, you can use this prop in any way you want, as it is passed directly through the Wizard to the render prop function.
An example of a custom action bar, using the steps and layout from previous examples would be:
export const WizardWithCustomActionBar = () => {
const location = useLocation();
const history = useHistory();
const customActionBar = (resolvedPropsForButtons, actionBarLayout) => {
const selectedFlexDirection =
actionBarLayout === 'column' ? 'column' : 'row';
return (
<div
style={{
border: 'solid 1px yellow',
display: 'flex',
flexDirection: selectedFlexDirection,
}}>
{resolvedPropsForButtons.map((propForButton) =>
('next' == propForButton.name || 'previous' == propForButton.name) &&
propForButton.to != undefined ? (
<Button
label={propForButton.name}
fullWidth={true}
onClick={(e, to: propForButton.to) => handleNavigation(e, to)}
/>
) : (
''
)
)}
</div>
);
};
const handleNavigation = (event, to) => {
history.replace(`//${to}`);
};
return (
<Wizard
layout={layout}
baseRoute={'/'}
basePath={'/'}
location={location}
steps={steps}
renderActionBar={customActionBar}
/>
);
};
We have removed the validation from this example, but you can add it in the handleNavigation function.
Usage
See Wizard Usage specifications in the patterns section.
Code
Import statement
import { * } from '@jutro/wizard-next';
Jutro provides the Wizard related features through the @jutro/wizard-next package. It contains the following components:
WizardWizardPageWizardProgressWizardActionBarWizardPrompt
The Wizard is the main component that puts all the pieces together - the progress bar, the buttons and actions associated with them, and the wizard content in the wizard pages. When using WizardProgress and WizardActionBar, you can customize their look and feel, use your own components in them, or remove them completely.
Wizard features
The main features of the Wizard are:
Progress indicator
Apart from the default progress indicator provided, it is possible to use a custom one. This enables you to create your own progress indicator to meet your project requirements, while fully utilizing the other Jutro Wizard features.
Action bar
The action bar manages the wizard actions. It supports onCancel, onFinish, onNext, and onPrevious events and the associated callbacks can be customized using JSX. Additionally, you can customize a knockout page for each action. Within each action, you can customize a different knockout page depending on the response.
Page transitions
Manages the page transitions, normally triggered by the user through the action bar buttons interaction. Supports next, previous, and jump (for example, a user is on step 5 and the jump action takes them to step 3).
Wizard component
Use this component to render a wizard. This component is the main wizard container. It renders routes for the specified steps. Each step must reference a component that either wraps or extends <WizardPage. Each step component will receive information from the wizard and navigation paths to be used in page rendering.
import { Wizard } from '@jutro/wizard-next';
const steps = [
{
key: 'one',
route: 'step1',
component: PageOne,
},
{
key: 'two',
route: 'step2',
component: PageTwo,
},
{
key: 'three',
route: 'step3',
component: PageThree,
},
];
<Wizard
baseRoute="/wizard/:zipCode"
basePath="/wizard/90210"
steps={steps}
cancelPath="/home"
finishPath="/home"
/>;
Wizard props
This is the list of properties of the Wizard component. In the next subsections you can find additional information of the layout and buttonProps properties and their expected types.
basePathrequired- Type
stringDescriptionBase path for the wizard; used when building step links.
baseRouterequired- Type
stringDescriptionBase route for the wizard; used when building step routes.
locationrequired- Type
{}DescriptionCurrent path location, provided by react-router. See react-router props.
actionBarLayout- Type
'default' | 'spaceEvenly'DescriptionThe type of layout applied to action bar items:
default- keeps items with visual separation,spaceEvenly- distributes items evenly in available grid space. bodyClassName- Type
stringDescriptionCSS class name for the body of this component.
buttonProps- Type
{ cancel:{}, previous: {}, next: {}, finish: {} }DescriptionOverrides for action buttons.
callbackMap- Type
{onStartWizard: func, onFinishWizard: func, onCancelWizard: func,}DescriptionCallback map for the resolver.
cancelPath- Type
stringDescriptionPath to navigate on 'cancel'; if none provided, the 'cancel' button will not be displayed.
className- Type
stringDescriptionCSS class name for this component.
componentMap- Type
{}DescriptionComponent map for page component resolver.
finishPath- Type
stringDescriptionPath to navigate on 'finish'; if none provided, the 'finish' button will not be displayed.
history- Type
{}DescriptionReact-Router history object. See react-router props.
initialStepPath- Type
stringDescriptionPath to the initial step (will be appended to 'basePath'); if not provided, the first step will be displayed.
knockoutPath- Type
stringDescriptionPath to navigate on fail of 'next'; if none provided, no default failTo will be added to the 'next' button.
layout- Type
{desktop: layoutShape, tablet: layoutShape, phoneWide: layoutShape, phone: layoutShape}DescriptionObject to override page layout.
match- Type
{}DescriptionReact-Router match object. See react-router props.
onCancel- Type
string | funcDescriptionCallback to invoke when the 'cancel' button is clicked; returns true, false or a promise.
onFinish- Type
string | funcDescriptionCallback to invoke when the 'finish' button is clicked; returns true, false or a promise.
onStart- Type
string | funcDescriptionCallback to trigger when the Wizard mounts.
onWizardEvent- Type
func(info, eventName)DescriptionThe function(info, eventName) called when a page loads (invoked by WizardPage).
renderActionBar- Type
func | booleanDescriptionCallback to render the action bar, or hide/show it.
renderNotFound- Type
funcDescriptionCallback to render 'not found' content; if not provided, nothing will be rendered if a path is not found.
renderProgressBar- Type
funcDescriptionCallback to render a progress bar, or hide/show it.
staticContext- Type
{}DescriptionReact-Router static context.
steps- Type
{ id: string, route: string, title: string, , component: React.Node }[]DescriptionArray of steps of the wizard.
subRoutes- Type
{ id: string, route: string, title: string, , component: React.Node }[]DescriptionArray of routes for subwizards. If a subroute matches the current location a subwizard is active otherwise the outer wizard is active.
Wizard layouts
The wizard uses a grid structure derived from the Layout component. You can also pass custom layout objects for desktops, tablets, and phones to customize the wizard layout.
return (
<WizardExampleContext.Provider value={exampleContext}>
<Wizard
baseRoute={route}
layout={{
desktop: {
columns: ['1fr'],
repeat: '4',
gap: 'large',
colStart: '2',
colSpan: '1',
},
tablet: {
repeat: '4',
...
},
phone: {
repeat: '4',
...
},
}}
basePath={path}
steps={steps}
.......
/>
</WizardExampleContext.Provider>
);
Layout prop
children- Type
ReactNode (preferably `GridItem`)DescriptionThe content to be displayed in the page.
className- Type
stringDescriptionCSS class name for this component.
id- Type
stringDescriptionUnique identifier for the component.
layout- Type
{desktop?: LayoutShape, tablet?: LayoutShape, phoneWide?: LayoutShape, phone?: LayoutShape,}colSpan- Type
number | stringDescriptionSpecifies how many columns an element will span across.
colStart- Type
number | stringDescriptionDefine column to start.
columns- Type
any[]DescriptionDefine explicit columns.
gap- Type
'auto-none' | 'small' | 'medium' | 'large'DescriptionThe gap size between rows and columns.
repeat- Type
'auto-fit' | 'auto-fill' | numberDescriptionAmount of columns to repeat.
DescriptionOverride the default device layout:
desktop,tablet,phoneWideandphone, all of typeLayoutShape.
LayoutShape props
The LayoutShape object is used in the layout property to define the layout of the wizard for each of the possible breakpoints.
colSpan- Type
string | numberDescriptionspecifies how many columns an element will span across.
colStart- Type
string | numberDescriptiondefine column to start from.
columns- Type
string[] | number[]Descriptiondefine explicit columns.
gap- Type
'none', 'small', 'medium', 'large'DescriptionGap between rows and columns.
repeat- Type
'auto-fit' | 'auto-fill' | number | stringDescriptionRepeat columns patterns.
buttonProps property
buttonProps are passed to the action bar buttons. This includes cancel, previous, next, and finish. They can be used to customize the look and feel or the behavior of the default Wizard (or WizardPage) buttons.
You can pass button props to both Wizard and WizardPage.
If you set buttonProps in the Wizard component, you override the default values of the action bar buttons for the whole wizard flow.
For example, the wizard will have a next button with fullWidth set to true:
<Wizard
buttonProps={{
next: {
fullWidth: true,
},
}}
/>
If you set buttonProps in a Wizard step, you override the values of the action bar buttons for that step.
Continuing the previous example, this step of the wizard flow would then have a next button with fullWidth set to false, overwriting the value set at the wizard level for this particular step.
<WizardPage
buttonProps={{
// overrides of default button props, these props will have priority over the buttonProps override from the wizard.
next: {
fullWidth: false,
},
}}
/>
buttonProps props
children- Type
React.Node | IntlMessageShape | { pathname?: IntlMessageShape; hash?: IntlMessageShape }DescriptionThe children elements to render inside of the Button.
className- Type
stringDescriptionCSS class name for this component.
disabled- Type
booleanDescriptionIf
truethis button is disabled. failToMessage- Type
stringDescriptionThe message shown when the promise is rejected; shown if 'failTo' is not provided.
fullWidth- Type
booleanDescriptionIf
true, the button expands to the available width. icon- Type
string | IconDescriptionAn Icon component to render on the component. The value must be an
Iconcomponent or the icon's name. For example,CheckIconor'gw-check'. iconClassName- Type
stringDescriptionCSS class name for the icon.
iconPosition- Type
left | rightDescriptionWhere the icon is placed relative to the text.
id- Type
stringDescriptionUnique identifier for the component.
message- TypeDescription
The message shown when executing the trigger/promise.
size- Type
small | mediumDescriptionAllows you to select the smaller or larger variant.
to- Type
IntlMessageShape | IntlRouterLocationDescriptionThe destination path when the promise is resolved; can be an object like
<Link to>. toMessage- Type
stringDescriptionThe message shown when the promise is resolved; shown if 'to' is not provided.
Wizard page component
The WizardPage component defines the content and events for a specific Wizard step.
import { WizardPage } from '@jutro/wizard-next';
import { useLocation } from 'react-router-dom';
const myWizardPage = () => {
const location = useLocation();
return (
<WizardPage
{
cancelPath="/"
finishPath="/offer"
knockoutPath="/knockoutPage"
} location={location}>
<span>Account wizard page</span>
</WizardPage>
);
};
WizardPage props
childrenrequired- Type
nodeDescriptionThe content to be displayed in the page.
idrequired- Type
stringDescriptionUnique identifier for the component.
locationrequired- Type
objectDescriptionThe location object with pathname of current url. Usually provided from the location.pathname prop passed from the router.
buttonProps- Type
objectDescriptionOverrides for action buttons.
className- Type
stringDescriptionCSS class name for this component.
headerClass- Type
stringDescriptionCSS class passed to wizard page header.
knockoutPath- Type
stringDescriptionPath to navigate on fail of 'next'; if none is provided, no default
failTowill be added to the 'next' button'. onLoad- Type
functionDescriptionThe callback to invoke when page is loaded; returns true, false or a promise.
onNext- Type
functionDescriptionThe callback to invoke when the 'next' button is clicked; returns true, false or a promise.
onPageEventInfo- Type
functionDescriptionThe callback to get page event info to send with a wizard event.
onPrevious- Type
functionDescriptionCallback to invoke when the 'back' button is clicked; returns true, false or a promise.
pageEventInfo- Type
function | objectDescriptionObject or callback to get page event info to send with a wizard event.
panelClassName- Type
stringDescriptionAdditional class name for the panel.
renderHeader- Type
functionDescriptionFunction which renders a custom panel header element.
renderPanel- Type
functionDescriptionThe callback to the render panel method; if null then renders without a panel.
renderSubTitle- Type
functionDescriptionFunction to render a custom subTitle.
renderTitle- Type
functionDescriptionFunction to render a custom title.
resolveCallbackMap- Type
objectDescriptionCallback map for the resolver.
subTitle- Description
Default panel subtitle expression.
title- Description
Default panel title expression.
WizardPage considerations and references
-
Wizard page callbacks:
onNext,onLoad, andonPrevious. You can also show prompts when the user tries to go back to a previous page or wants to cancel the wizard. -
See the Button props section for details on the
buttonPropsplacementOptions. -
For more details about render props, see the Customizing the action bar and Customizing the progress bar sections.
Wizard progress bar component
There is a default progress indicator that you can customize or you can provide a custom component through the render function property.
The default progress indicator is managed through the WizardProgress component. It relies on the SimpleProgressBar component.
All the WizardProgress component logic is based on the information provided by the Wizard where it is embedded. For example, the list of steps is extracted from the Wizard Context.
See the Customizing the progress bar section for further details.
WizardProgress props
basePath- Type
stringDescriptionPath to be used when composing the steps urls.
location- Type
'none' | 'small' | 'medium' | 'large'DescriptionTo look for matching subroutes.
progressBarClassNamedeprecated- Type
stringDescriptionClass to override progress bar step styles.
Wizard action bar
The WizardActionBar component provides the default functionality to display and handle the different options available in the Wizard. It generates and renders the WizardButton from actions passed using props. It combines the action with default properties for each button; the default properties are overwritten when provided in actions.
Below is an example defining what happens when the user clicks the Cancel or Next button:
import { WizardActionBar } from '@jutro/wizard-next';
const actions = [
{name: 'cancel', to: '/'},
{name: 'next', to: '/wizard/test/step2'}
]
<WizardActionBar actions={actions}/>
WizardActionBar props
actionsrequired- Type
[]DescriptionThe list of actions to be rendered in the <WizardActionBar>.
className- Type
stringDescriptionCSS class name for this component.
layout- Type
'default' | 'spaceEvenly' | 'center'DescriptionType of layout applied to action bar items:
default- keeps items with visual separation,spaceEvenly- distributes items evenly in available grid space,center- center button horizontally, will vertically stack multiple buttons.
Wizard prompt
Provides a convenient prompting mechanism for the context of a wizard. It allows separate conditions and prompts for 'previous' and 'cancel' windows.
import { <WizardPrompt } from '@jutro/wizard-next';
<WizardPrompt
cancelPrompt={{when: wizardChanged, message: 'Want to cancel?'}}
previousPrompt={{when: dataChanged, message: 'Want to go back?'}}
/>
WizardPrompt props
basePath- Type
stringDescriptionPath to be used when composing the steps urls.
previousPrompt- Type
{when: boolean, title: string, message: string }DescriptionProperties for the 'previous' prompt; contains 'when', 'title' and 'message'.
cancelPromptdeprecated- Type
{when: boolean, title: string, message: string }DescriptionProperties for the 'cancel' prompt; contains 'when', 'title' and 'message'.
Wizard custom behaviors
Prevent navigation
If the function passed to the onCancel, onNext, or onPrevious properties returns false, the action is stopped, and the user is not redirected to the corresponding path, staying on the current step.
Changelog
10.9.0
-
A new opt-in feature was introduced that disables automatic event publishing for the Wizard component. You can enable this feature by adding
JUTRO_DISABLE_AUTO_EVENTS_PUBLISHING=trueto the.envfile in the root of your Jutro application. When this is enabled, legacy components no longer publish events by default. For more information on events and how to set up new events, see the Events documentation.
10.2.0
- Deprecated the
progressBarClassNameproperty from theWizardProgresscomponent.
10.0.0
- Decommissioned
ScrollToErrorcomponent that was exposed through the@jutro/wizard-nextpackage. - Deprecated the usage of metadata to define the
Wizardcomposition and set up.