Wizard
<mo-wizard> | MOWizard
Wizards are a series of steps that guide users through a process.
Wizard is a disruptive modal component that guides users to achieve a goal through a series of steps in a defined order that require some user input. Long and complex tasks are divided into smaller parts and steps to simplify a process.
<mo-wizard orientation="horizontal"> <mo-wizard-step label="Select case type"></mo-wizard-step> <mo-wizard-step label="Check details"></mo-wizard-step> <mo-wizard-step label="Fill in the form"></mo-wizard-step> </mo-wizard>
import { MOWizard, MOWizardStep } from '@modes-web-components/dist/react'; const App = () => { return ( <MOWizard orientation="horizontal"> <MOWizardStep label="Select case type"></MOWizardStep> <MOWizardStep label="Check details"></MOWizardStep> <MOWizardStep label="Fill in the form"></MOWizardStep> </MOWizard> ); };
Examples
Vertical
By default the wizard steps are aligned in horizontal order. Use the attribute vertical
to
change the order to vertical instead.
<mo-wizard orientation="vertical"> <mo-wizard-step label="Select case type"></mo-wizard-step> <mo-wizard-step label="Check details"> <mo-chip size="small" variant="neutral" pill slot="chips">Product overview</mo-chip> <mo-chip size="small" variant="neutral" pill slot="chips">Claim</mo-chip> <mo-chip size="small" variant="neutral" pill slot="chips">New</mo-chip> </mo-wizard-step> <mo-wizard-step label="Fill in the form"></mo-wizard-step> </mo-wizard>
import { MOWizard, MOWizardStep } from '@modes-web-components/dist/react'; const App = () => { return ( <MOWizard orientation="vertical"> <MOWizardStep label="Select case type"></MOWizardStep> <MOWizardStep label="Check details"> <MOChip size="small" variant="neutral" pill slot="chips"> Product overview </MOChip> <MOChip size="small" variant="neutral" pill slot="chips"> Claim </MOChip> <MOChip size="small" variant="neutral" pill slot="chips"> New </MOChip> </MOWizardStep> <MOWizardStep label="Fill in the form"></MOWizardStep> </MOWizard> ); };
Non-linear
A non-linear wizard allows the user to freely navigate between the different steps, i.e., inactive steps are not set to disabled by default.
<mo-wizard nonLinear orientation="horizontal"> <mo-wizard-step label="Select case type"></mo-wizard-step> <mo-wizard-step label="Check details"></mo-wizard-step> <mo-wizard-step label="Fill in the form"></mo-wizard-step> </mo-wizard>
import { MOWizard, MOWizardStep } from '@modes-web-components/dist/react'; const App = () => { return ( <MOWizard nonLinear orientation="horizontal"> <MOWizardStep label="Select case type"></MOWizardStep> <MOWizardStep label="Check details"></MOWizardStep> <MOWizardStep label="Fill in the form"></MOWizardStep> </MOWizard> ); };
You can try out the keyboard navigation on this example. Use tab and the arrow keys to navigate between steps, and enter to select a step.
With chips
Use the chips
slot to assign chips to each mo-wizard-step
. Chips should be used to
categorize and organize the steps.
<mo-wizard orientation="horizontal"> <mo-wizard-step label="Select case type"> <mo-chip size="small" variant="neutral" pill slot="chips">Product overview</mo-chip> <mo-chip size="small" variant="neutral" pill slot="chips">Claim</mo-chip> </mo-wizard-step> <mo-wizard-step label="Check details"></mo-wizard-step> <mo-wizard-step label="Fill in the form"> <mo-chip size="small" variant="neutral" pill slot="chips">New</mo-chip> </mo-wizard-step> </mo-wizard>
import { MOWizard, MOWizardStep } from '@modes-web-components/dist/react'; const App = () => { return ( <MOWizard orientation="horizontal"> <MOWizardStep label="Select case type"> <MOChip size="small" variant="neutral" pill slot="chips"> Product overview </MOChip> <MOChip size="small" variant="neutral" pill slot="chips"> Claim </MOChip> </MOWizardStep> <MOWizardStep label="Check details"></MOWizardStep> <MOWizardStep label="Fill in the form"> <MOChip size="small" variant="neutral" pill slot="chips"> New </MOChip> </MOWizardStep> </MOWizard> ); };
With sub steps
Use the default
slot to assign sub-steps to each mo-wizard-step
. Sub steps should
be used to break down the step in to smaller pieces.
Vertical
<mo-wizard orientation="vertical"> <mo-wizard-step label="Select case type"> <mo-wizard-sub-step label="Sub step #1"> <mo-badge variant="neutral" size="small" pill slot="badges">Sub badge #1</mo-badge> <mo-badge variant="neutral" size="small" pill slot="badges">Sub badge #2</mo-badge> </mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #2"></mo-wizard-sub-step> </mo-wizard-step> <mo-wizard-step label="Check details"> <mo-wizard-sub-step label="Sub step #1"></mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #2"></mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #3"></mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #4"></mo-wizard-sub-step> </mo-wizard-step> <mo-wizard-step label="Fill in the form"> <mo-chip size="small" variant="neutral" pill slot="chips">New</mo-chip> </mo-wizard-step> </mo-wizard>
import { MOWizard, MOWizardStep } from '@modes-web-components/dist/react'; const App = () => { return ( <MOWizard orientation="vertical"> <MOWizardStep label="Select case type"> <MOWizardSubStep label="Sub step #1"> <MOBadge variant="neutral" size="small" pill slot="badges"> Sub badge #1 </MOBadge> <MOBadge variant="neutral" size="small" pill slot="badges"> Sub badge #2 </MOBadge> </MOWizardSubStep> <mo-wizard-sub-step label="Sub step #2"></mo-wizard-sub-step> </MOWizardStep> <MOWizardStep label="Check details"> <MOWizardSubStep label="Sub step #1"></MOWizardSubStep> <MOWizardSubStep label="Sub step #2"></MOWizardSubStep> <MOWizardSubStep label="Sub step #3"></MOWizardSubStep> <MOWizardSubStep label="Sub step #4"></MOWizardSubStep> </MOWizardStep> <MOWizardStep label="Fill in the form"> <MOChip size="small" variant="neutral" pill slot="chips"> New </MOChip> </MOWizardStep> </MOWizard> ); };
Horizontal
<mo-wizard orientation="horizontal"> <mo-wizard-step label="Select case type"> <mo-wizard-sub-step label="Sub step #1"></mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #2"></mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #3"></mo-wizard-sub-step> </mo-wizard-step> <mo-wizard-step label="Check details"> <mo-wizard-sub-step label="Sub step #1"></mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #2"></mo-wizard-sub-step> </mo-wizard-step> <mo-wizard-step label="Fill in the form"> <mo-chip size="small" variant="neutral" pill slot="chips">New</mo-chip> </mo-wizard-step> </mo-wizard>
import { MOWizard, MOWizardStep } from '@modes-web-components/dist/react'; const App = () => { return ( <MOWizard orientation="horizontal"> <MOWizardStep label="Select case type"> <MOWizardSubStep label="Sub step #1"> <MOWizardSubStep label="Sub step #1"></MOWizardSubStep> <MOWizardSubStep label="Sub step #2"></MOWizardSubStep> <MOWizardSubStep label="Sub step #3"></MOWizardSubStep> </MOWizardSubStep> <mo-wizard-sub-step label="Sub step #2"></mo-wizard-sub-step> </MOWizardStep> <MOWizardStep label="Check details"> <MOWizardSubStep label="Sub step #1"></MOWizardSubStep> <MOWizardSubStep label="Sub step #2"></MOWizardSubStep> </MOWizardStep> <MOWizardStep label="Fill in the form"> <MOChip size="small" variant="neutral" pill slot="chips"> New </MOChip> </MOWizardStep> </MOWizard> ); };
Change step programmatically
Setting the attribute activeStep
or calling the functions increment
and
decrement
programmatically will automatically update the index of the wizard. Make sure you are
setting the activeStep
to a value between 0 and the number of slides. See example below on ways
to access these attributes and states.
<mo-card style="width: 100%;"> <mo-wizard slot="header" id="programmatic" orientation="horizontal"> <mo-wizard-step label="Fill in the form"></mo-wizard-step> <mo-wizard-step label="Select case type"></mo-wizard-step> <mo-wizard-step label="Check details"></mo-wizard-step> </mo-wizard> <div style="display: flex; flex-direction: column; gap: 8px; padding: 1rem;"> <mo-input label="Name"></mo-input> <mo-input label="Surname"></mo-input> <mo-input label="Address"></mo-input> </div> <div slot="footer" style="display: flex; padding-top: 16px; width: 100%; justify-content: space-between; align-items: center;" > <mo-button id="prev">Previous</mo-button> <mo-button id="next">Next</mo-button> </div> </mo-card> <script> const wizard = document.querySelector('#programmatic'); const prev = document.querySelector('#prev'); prev.disabled = wizard.activeStep === 0; const next = document.querySelector('#next'); prev.addEventListener('click', () => { wizard.decrement(); }); next.addEventListener('click', () => { wizard.increment(); }); wizard.addEventListener('mo-change', () => { prev.disabled = wizard.activeStep === 0; next.disabled = wizard.activeStep === wizard.steps.length - 1; }); </script>
import { MOWizard, MOWizardStep, MOCard, MOInput, MOButton } from '@modes-web-components/dist/react'; import { useRef } from 'react'; const wizardRef = useRef(null); const prevRef = useRef(null); const nextRef = useRef(null); const next = () => { wizardRef.increment(); }; const prev = () => { wizardRef.decrement(); }; const changeHandler = () => { prevRef.disabled = wizardRef.activeStep === 0; nextRef.disabled = wizardRef.activeStep === wizardRef.steps.length - 1; }; const App = () => { return ( <MOCard style={{ width: '100%' }}> <MOWizard onMoChange={changeHandler} slot="header" ref={wizardRef} orientation="horizontal"> <MOWizardStep label="Fill in the form"></MOWizardStep> <MOWizardStep label="Select case type"></MOWizardStep> <MOWizardStep label="Check details"></MOWizardStep> </MOWizard> <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', padding: '1rem' }}> <MOInput label="Name"></MOInput> <MOInput label="Surname"></MOInput> <MOInput label="Address"></MOInput> </div> <div slot="footer" style={{ display: 'flex', paddingTop: '16px', width: '100%', justifyContent: 'space-between', alignItems: 'center' }} > <MOButton disabled={wizardRef.activeStep === 0} ref={prevRef} onClick={() => prev()}> Previous </MOButton> <MOButton ref={nextRef} onClick={() => next()}> Next </MOButton> </div> </MOCard> ); };
Mobile
When the parent container’s width is less than 320px
, the mo-wizard
will collapse
into a dropdown element.
<mo-card style="width: 300px"> <mo-wizard slot="header" id="mobile-wizard" orientation="horizontal"> <mo-wizard-step label="Fill in the form"></mo-wizard-step> <mo-wizard-step label="Select case type"> <mo-wizard-sub-step label="Sub step #1"></mo-wizard-sub-step> <mo-wizard-sub-step label="Sub step #2"></mo-wizard-sub-step> </mo-wizard-step> <mo-wizard-step label="Check details"></mo-wizard-step> </mo-wizard> <div style="display: flex; flex-direction: column; gap: 12px;"> <mo-input label="Name"></mo-input> <mo-input label="Surname"></mo-input> <mo-input label="Address"></mo-input> </div> <div slot="footer" style="display: flex; padding-top: 16px; width: 100%; justify-content: space-between; align-items: center;" > <mo-button id="prev-mobile">Previous</mo-button> <mo-button id="next-mobile">Next</mo-button> </div> </mo-card> <script> const wizard = document.querySelector('#mobile-wizard'); const prev = document.querySelector('#prev-mobile'); prev.disabled = wizard.activeStep === 0; const next = document.querySelector('#next-mobile'); prev.addEventListener('click', () => { wizard.decrement(); }); next.addEventListener('click', () => { wizard.increment(); }); wizard.addEventListener('mo-change', () => { prev.disabled = wizard.activeStep === 0; next.disabled = wizard.activeStep === wizard.steps.length - 1; }); </script>
import { MOWizard, MOWizardStep, MOCard, MOInput, MOButton } from '@modes-web-components/dist/react'; import { useRef } from 'react'; const wizardRef = useRef(null); const prevRef = useRef(null); const nextRef = useRef(null); const next = () => { wizardRef.increment(); }; const prev = () => { wizardRef.decrement(); }; const changeHandler = () => { prevRef.disabled = wizardRef.activeStep === 0; nextRef.disabled = wizardRef.activeStep === wizardRef.steps.length - 1; }; const App = () => { return ( <MOCard style={{ width: '300px' }}> <MOWizard onMoChange={changeHandler} slot="header" ref={wizardRef} orientation="horizontal"> <MOWizardStep label="Fill in the form"></MOWizardStep> <MOWizardStep label="Select case type"></MOWizardStep> <MOWizardStep label="Check details"></MOWizardStep> </MOWizard> <div style={{ display: 'flex', flexDirection: 'column', gap: '8px', padding: '1rem' }}> <MOInput label="Name"></MOInput> <MOInput label="Surname"></MOInput> <MOInput label="Address"></MOInput> </div> <div slot="footer" style={{ display: 'flex', paddingTop: '16px', width: '100%', justifyContent: 'space-between', alignItems: 'center' }} > <MOButton disabled={wizardRef.activeStep === 0} ref={prevRef} onClick={() => prev()}> Previous </MOButton> <MOButton ref={nextRef} onClick={() => next()}> Next </MOButton> </div> </MOCard> ); };
Importing
If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.
To import this component using a bundler:
import '@metsooutotec/modes-web-components/dist/components/wizard/wizard.js';
To import this component as a React component:
import MOWizard from '@metsooutotec/modes-web-components/dist/react/wizard/';
To import this component using a script tag:
<script type="module" src="https://modes-web.metso.com/dist/components/cdn/components/wizard/wizard.js"></script>
Slots
Name | Description |
---|---|
(default) | The default slot. Use this to slot in mo-wizard-step elements. |
Learn more about using slots.
Properties
Name | Description | Reflects | Type | Default |
---|---|---|---|---|
steps
|
Query all child mo-wizard-step elements. |
MOWizardStep[]
|
- | |
body
|
Query for main wizard body, to show/hide it on mobile. |
HTMLDivElement
|
- | |
activeStep
|
Index of the currently active step. |
number
|
0
|
|
orientation
|
The component orientation (layout flow direction). |
'horizontal' | 'vertical'
|
'horizontal'
|
|
nonLinear
|
Non-linear wizards allow the user to enter a multi-step flow at any point. |
|
boolean
|
false
|
activeLabel
|
tracks active label to give to mobile header |
string
|
''
|
|
nextLabel
|
tracks next label to give to mobile header |
string
|
''
|
|
totalSteps
|
length of the array of steps slotted in |
number
|
0
|
|
open
|
open state of the mobile dropdown |
boolean
|
false
|
|
prevWidth
|
prevWidth to check if width changed in resize event |
number
|
0
|
|
updateComplete |
A read-only promise that resolves when the component has finished updating. |
Learn more about attributes and properties.
Events
Name | React Event | Description | Event Detail |
---|---|---|---|
mo-change |
onMoChange |
Emitted when the active step changes. | - |
mo-show |
onMoShow |
Emitted when the mobile dropdown is shown. | - |
mo-hide |
onMoHide |
Emitted when the mobile dropdown is hidden. | - |
Learn more about events.
Methods
Name | Description | Arguments |
---|---|---|
increment() |
increment active step by 1 | - |
decrement() |
decrement active step by 1 | - |
updateActiveStep() |
watch for changes in the activeStep, and update the steps in the default slot accordingly | - |
handleClick() |
toggle open state of the dropdown on mobile container sizes | - |
handleOpenChange() |
when the open state changes, play animation for the queried body | - |
Learn more about methods.
Parts
Name | Description |
---|---|
base |
The component’s internal wrapper. |
Learn more about customizing CSS parts.