Layout

Modal Wizard

A modal wizard guides users through a task by presenting a succession of actions to complete.
1
import {useSelector, useDispatch} from 'react-redux';
2
import {
3
Button,
4
Form,
5
IDispatch,
6
InputConnected,
7
InputSelectors,
8
PlasmaState,
9
Label,
10
ModalWizard,
11
openModal,
12
Radio,
13
RadioSelectConnected,
14
RadioSelectSelectors,
15
} from '@coveord/plasma-react';
16
17
const containsCoveo = (str: string) => str.trim().toLowerCase().includes('coveo');
18
19
const Demo = () => {
20
const selectedPath = useSelector((state: PlasmaState) =>
21
RadioSelectSelectors.getValue(state, {id: 'radio-step-1'})
22
);
23
const inputTwoValue = useSelector(
24
(state: PlasmaState) => InputSelectors.getValue(state, {id: 'input-step-2'}) || ''
25
);
26
const dispatch: IDispatch = useDispatch();
27
28
const validateStep = (currentStep: number, numberOfSteps: number) => {
29
if (currentStep === 0) {
30
return {
31
isValid: !!selectedPath,
32
message: !selectedPath && 'Select a path to continue.',
33
};
34
} else if (currentStep === 1) {
35
if (!inputTwoValue.trim()) {
36
return {isValid: false, message: 'The input must have some value to continue.'};
37
} else if (!containsCoveo(inputTwoValue)) {
38
return {
39
isValid: true,
40
message: 'The value you entered is fine for now, but might cause problems later.',
41
};
42
} else {
43
return {isValid: true};
44
}
45
} else if (currentStep === numberOfSteps - 1) {
46
return {
47
isValid: containsCoveo(inputTwoValue),
48
message: !containsCoveo(inputTwoValue) && 'The input at step 2 must contain "coveo" to finish.',
49
};
50
}
51
return {isValid: true};
52
};
53
54
return (
55
<>
56
<Button name="Open wizard" enabled primary onClick={() => dispatch(openModal('standard-wizard'))} />
57
<ModalWizard
58
id="standard-wizard"
59
title="Wizard 🧙‍♂️"
60
onFinish={(close) => {
61
alert('Congratulations! You completed the wizard');
62
close();
63
}}
64
validateStep={validateStep}
65
isDirty={!!selectedPath || !!inputTwoValue}
66
modalFooterChildren={(currentStep, numberOfSteps) =>
67
currentStep < numberOfSteps - 1 ? null : <div className="flex-auto">Last Step!</div>
68
}
69
>
70
<Form title="Step 1" mods={['mod-form-top-bottom-padding', 'mod-header-padding']}>
71
<RadioSelectConnected id="radio-step-1">
72
<Radio id="path1" name="wizardPath" value="redhorn">
73
<Label>Pass over the mountain</Label>
74
</Radio>
75
<Radio id="path2" name="wizardPath" value="moria">
76
<Label>Go under the mountain through Moria</Label>
77
</Radio>
78
</RadioSelectConnected>
79
</Form>
80
<Form title="Step 2" mods={['mod-form-top-bottom-padding', 'mod-header-padding']}>
81
<InputConnected
82
id="input-step-2"
83
autoComplete="off"
84
validateOnChange
85
validate={(value: string) => !!value.trim()}
86
labelTitle={<Label invalidMessage="Cannot be left empty">Enter something to continue</Label>}
87
/>
88
</Form>
89
{selectedPath === 'redhorn' && (
90
<Form title="Step 3" mods={['mod-form-top-bottom-padding', 'mod-header-padding']}>
91
Its longer, but we'll get there!
92
</Form>
93
)}
94
<Form
95
title={selectedPath === 'moria' ? 'Step 3' : 'Step 4'}
96
mods={['mod-form-top-bottom-padding', 'mod-header-padding']}
97
>
98
Enter "coveo" at step two to finish!
99
</Form>
100
</ModalWizard>
101
</>
102
);
103
};
104
export default Demo;

Props

NameTypeDefaultDescription
idrequiredstring
A unique identifier that will be used to identify the modal in the PlasmaState. Among other things this is the identifer that will be used to open the wizard.
cancelButtonLabelstring"Cancel"
The label of the cancel button
childrenReactNode
classesIClassName
closeCallback() => void
closeTimeoutnumber
contentClassesIClassName
Additionnal CSS class to add to the modal container
contentRef(el: HTMLDivElement) => void
docLinkILinkSvgProps
Props of the link to documentation
finishButtonLabelstring"Finish"
The label of the finish button
htmlIdstring
id for the html element
isDirtyboolean
Whether the wizard should warn about unsaved changes when the user unexpectedly closes the modal
isPromptbooleanfalse
Wheter this backdrop is for a prompt or not
modalBodyClassesIClassName
Additionnal CSS class to add to the body
modalFooterChildrenReactNode | DependsOnStep<ReactNode>
Determines what needs to be rendered in the modal footer. The content of the footer can be dependent on the current step by using a render function
modalFooterClassesIClassName
Additionnal CSS class to add to the footer
modalHeaderChildrenReactNode
React child to add to the header
modalHeaderClassesIClassName
Additionnal CSS class to add to the header
nextButtonLabelstring"Next"
The label of the next button
onCancel() => unknown
A callback function that is executed when the user clicks on the cancel button
onFinish(close: () => void) => unknown
A function that is executed when user completes all the steps.
  • closeA function that closes the modal when called.
onNext() => unknown
A callback function that is executed when the user clicks on the next button
onPrevious() => unknown
A callback function that is executed when the user clicks on the previous button
openOnMountboolean
Renders the Modal already opened.
previousButtonLabelstring"Previous"
The label of the previous button
titlestring | DependsOnStep<string>
The title of the modal. The title can be dependent on the current step if needed, to do so pass in a function that accepts the same params as the validateStep prop.
validateStepDependsOnStep<{ isValid: boolean; message?: string; }>() => ({isValid: true})
A function that determines whether the current step is valid or not
  • currentStepThe step at is currently displayed in the wizard
  • numberOfStepsThe total number of steps to reach completion of the wizard. Useful to know if the current step is the last step.
displayFordeprecatedstring[]
Do not use

Examples

Using validation ids
1
import {
2
Button,
3
Form,
4
IDispatch,
5
InputConnected,
6
ModalWizardWithValidations,
7
openModal,
8
SingleSelectConnected,
9
withDirtyInputHOC,
10
withDirtySingleSelectHOC,
11
withNonEmptySingleSelectHOC,
12
withNonEmptyValueInputValidationHOC,
13
} from '@coveord/plasma-react';
14
import {useDispatch} from 'react-redux';
15
16
const NonEmptyInput = withNonEmptyValueInputValidationHOC(withDirtyInputHOC(InputConnected));
17
const NonEmptySelect = withDirtySingleSelectHOC(withNonEmptySingleSelectHOC(SingleSelectConnected));
18
19
const Demo = () => {
20
const dispatch: IDispatch = useDispatch();
21
22
return (
23
<>
24
<Button name="Open wizard" enabled primary onClick={() => dispatch(openModal('validation-wizard'))} />
25
<ModalWizardWithValidations
26
id="validation-wizard"
27
title="Wizard 🧙‍♂️"
28
onFinish={(close) => {
29
alert('Congratulations! You completed the wizard');
30
close();
31
}}
32
validationIdsByStep={[['name-input'], ['favorite-animal-select']]}
33
>
34
<Form title="Step 1" mods={['mod-form-top-bottom-padding', 'mod-header-padding']}>
35
<NonEmptyInput
36
id="name-input"
37
labelTitle="Name"
38
autoComplete="off"
39
validateOnMount
40
validateOnChange
41
resetDirtyOnUnmount
42
resetErrorOnUnmount
43
/>
44
</Form>
45
<Form title="Step 2" mods={['mod-form-top-bottom-padding', 'mod-header-padding']}>
46
<NonEmptySelect
47
id="favorite-animal-select"
48
items={[
49
{value: 'tiger', displayValue: 'Tiger 🐅'},
50
{value: 'dog', displayValue: 'Dog 🐕', disabled: true},
51
{value: 'squid', displayValue: 'Squid 🦑'},
52
]}
53
/>
54
</Form>
55
</ModalWizardWithValidations>
56
</>
57
);
58
};
59
export default Demo;

No guidelines exist for ModalWizard yet.

Create guidelines