The RhStepper component is a user interface element that displays a linear sequence of steps that a user can progress through.
Once installed, you can import the RhStepper component into your React application:
import {RhStepper} from "@rhythm-ui/react"
Then, you can use the RhStepper component in your JSX code:
function Default() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper activeStep={activeStep} onClick={StepButtonHandler}> <RhStepperStep /> <RhStepperStep /> <RhStepperStep /> <RhStepperStep /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
Name | Type | Default | Description |
---|---|---|---|
activeStep | number | 0 | ActiveStep prop takes the value as an integer that denotes the step number for all the steps from 0 to the length of steps. |
showCompletedActionIcon | boolean | false | ShowCompletedActionIcon prop takes the value as a boolean. If true, completed steps will show the completed icon based on the icon given by the user in the error icon or success icon prop. |
layout | "horizontal" | "vertical" | horizontal | Layout prop takes the value as 'horizontal' or 'vertical' |
nonLinear | boolean | true | NonLinear prop takes the value as a boolean. If true, then the user can not jump from one step to another without completing the current step. |
autoNumbering | boolean | AutoNumbering prop takes the value as a boolean. If true, it will show the steps count on each step. | |
circleSize | string | 30px | CircleSize prop takes the value as a string that should be the size of a circle with unit px. |
stepConnectorDistance | string | 2em | StepConnectorDistance prop takes values as string that accepts pixel value to make connector length small or large. |
enableConnectorColor | boolean | true | EnableConnectorColor prop takes the value as a boolean. If true, the connector color will be visible. |
errorIcon | React.ReactNode | <RhIcon icon='heroicons:x-mark' /> | ErrorIcon takes the value as JSX. This will be shown after step completion with isError = true for <step /> component. |
successIcon | React.ReactNode | <RhIcon icon='heroicons:check' /> | SuccessIcon takes the value as JSX. This will be shown after step completion with isError = false for <step /> component. By default isError is false for <step /> component. |
The autoNumbering prop If set to true, step numbers will be automatically generated and displayed.
function AutoNumbering() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper autoNumbering circleSize="25px" enableConnectorColor={false} activeStep={activeStep} onClick={StepButtonHandler} > <RhStepperStep /> <RhStepperStep /> <RhStepperStep /> <RhStepperStep /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
If the enableConnectorColor prop is true then the connector between steps can have a different color than the default.
function Connector() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper autoNumbering circleSize="25px" enableConnectorColor={true} activeStep={activeStep} onClick={StepButtonHandler} > <RhStepperStep /> <RhStepperStep /> <RhStepperStep /> <RhStepperStep /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
The label prop of RhStepperStep will display the label on each step.
function Label() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper autoNumbering circleSize="25px" enableConnectorColor={true} activeStep={activeStep} onClick={StepButtonHandler} > <RhStepperStep label="Step1" /> <RhStepperStep label="Step2" /> <RhStepperStep label="Step3" /> <RhStepperStep label="Step4" /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
The NonLinear prop takes the value as a boolean. If true, then the user can not jump from one step to another without completing the current step.
function NonLinear() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper autoNumbering nonLinear={false} circleSize="25px" enableConnectorColor={true} activeStep={activeStep} onClick={StepButtonHandler} > <RhStepperStep label="Step1" /> <RhStepperStep label="Step2" /> <RhStepperStep label="Step3" /> <RhStepperStep label="Step4" /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
An optional icon is to be displayed within the step.
function Icon() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper autoNumbering nonLinear={false} circleSize="25px" enableConnectorColor={true} activeStep={activeStep} onClick={StepButtonHandler} > <RhStepperStep icon={<RhIcon icon="clarity:login-line" />} label="Login Details" /> <RhStepperStep icon={<RhIcon icon="bx:user" />} label="User Profile" /> <RhStepperStep icon={<RhIcon icon="clarity:group-solid" />} label="Membership" /> <RhStepperStep icon={<RhIcon icon="uiw:verification" />} label="Verification" /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
The successIcon and showCompletedActionIcon props will display an icon on a completed step icon.
function Success() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper autoNumbering showCompletedActionIcon successIcon={<RhIcon className="text-lg" icon="heroicons:check" />} circleSize="25px" enableConnectorColor={true} activeStep={activeStep} onClick={StepButtonHandler} > <RhStepperStep icon={<RhIcon icon="clarity:login-line" />} label="Login Details" /> <RhStepperStep icon={<RhIcon icon="bx:user" />} label="User Profile" /> <RhStepperStep icon={<RhIcon icon="clarity:group-solid" />} label="Membership" /> <RhStepperStep icon={<RhIcon icon="uiw:verification" />} label="Verification" /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
The errorIcon is displayed on a step with an error.
function Failure() { const [activeStep, setActiveStep] = useState(4); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper activeStep={4} autoNumbering circleSize="35px" errorIcon={<RhIcon className="text-lg" icon="heroicons:x-mark" />} onClick={() => {}} showCompletedActionIcon successIcon={<RhIcon className="text-lg" icon="heroicons:check" />} > <RhStepperStep icon={<RhIcon icon="clarity:login-line" />} label="Login Details" /> <RhStepperStep icon={<RhIcon icon="bx:user" />} label="User Profile" /> <RhStepperStep icon={<RhIcon icon="clarity:group-solid" />} isError label="Membership" /> <RhStepperStep icon={<RhIcon icon="uiw:verification" />} label="Verification" /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
The isDisable prop provides flexibility to disable or enable certain steps in the sequence based on user interactions or system conditions.
function Disable() { const [activeStep, setActiveStep] = useState(0); const STEP_SIZE = 4; const incrementStep = () => { setActiveStep((prev) => { if (prev <= STEP_SIZE - 1) { return prev + 1; } else return prev; }); }; const decrementStep = () => { setActiveStep((prev) => { if (prev > 0) { return prev - 1; } else return prev; }); }; const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <RhStepper activeStep={4} autoNumbering circleSize="35px" errorIcon={<RhIcon className="text-lg" icon="heroicons:x-mark" />} onClick={() => {}} showCompletedActionIcon successIcon={<RhIcon className="text-lg" icon="heroicons:check" />} > <RhStepperStep icon={<RhIcon icon="clarity:login-line" />} label="Login Details" /> <RhStepperStep icon={<RhIcon icon="bx:user" />} isDisable label="User Profile" /> <RhStepperStep icon={<RhIcon icon="clarity:group-solid" />} isDisable label="Membership" /> <RhStepperStep icon={<RhIcon icon="uiw:verification" />} label="Verification" /> </RhStepper> <div className="flex justify-evenly"> <RhButton onClick={decrementStep}>Previous</RhButton> <RhButton onClick={incrementStep}>Next</RhButton> </div> </div> ); }
The layout prop of the stepper can be either horizontal or vertical.
function verticalTemplate() { const [activeStep, setActiveStep] = useState(0); const [status, setStatus] = useState(""); const StepButtonHandler = (id) => { setActiveStep(id); }; return ( <div className="flex flex-col gap-8"> <div className="h-screen"> <RhStepper activeStep={activeStep} onClick={StepButtonHandler} status={status} layout="vertical" > <RhStepperStep label="Login Details" icon={<RhIcon icon="clarity:login-line" />} /> <RhStepperStep label="User Profile" icon={<RhIcon icon="bx:user" />} /> <RhStepperStep label="Membership" icon={<RhIcon icon="clarity:group-solid" />} /> <RhStepperStep label="Verification" icon={<RhIcon icon="uiw:verification" />} /> </RhStepper> </div> </div> ); }