React steps component for creating step-by-step user interfaces with customizable styling and interaction.
npx @tessl/cli install tessl/npm-rc-steps@5.0.0RC Steps is a React component library that provides a comprehensive steps UI component for creating step-by-step user interfaces. It supports both horizontal and vertical layouts, multiple step types, customizable icons and styling, and offers both controlled and uncontrolled usage patterns for multi-step workflows, wizards, and progress indicators.
npm install rc-stepsimport Steps, { Step, type StepsProps, type Status } from "rc-steps";For CommonJS:
const Steps = require("rc-steps");
const { Step } = Steps;Import CSS styles:
import "rc-steps/assets/index.css";import React, { useState } from "react";
import Steps from "rc-steps";
import "rc-steps/assets/index.css";
// Items-based approach (recommended)
function StepsExample() {
const [current, setCurrent] = useState(0);
const items = [
{
title: "Finished",
description: "This is a description",
},
{
title: "In Progress",
description: "This is a description",
},
{
title: "Waiting",
description: "This is a description",
},
];
return (
<Steps
current={current}
onChange={setCurrent}
items={items}
/>
);
}
// Traditional children approach
function StepsChildrenExample() {
return (
<Steps current={1}>
<Steps.Step title="First" description="Description 1" />
<Steps.Step title="Second" description="Description 2" />
<Steps.Step title="Third" description="Description 3" />
</Steps>
);
}RC Steps is built with the following key components:
Main container component that renders a sequence of steps with automatic status management and optional navigation.
interface StepsProps {
/** CSS class name prefix for styling */
prefixCls?: string;
/** Inline styles for the steps container */
style?: React.CSSProperties;
/** Additional CSS class names */
className?: string;
/** Child Step components (alternative to items prop) */
children?: React.ReactNode;
/** Layout direction of steps */
direction?: 'horizontal' | 'vertical';
/** Visual type of steps */
type?: 'default' | 'navigation';
/** Label placement relative to step icons */
labelPlacement?: 'horizontal' | 'vertical';
/** Icon CSS class prefix */
iconPrefix?: string;
/** Status of the current step */
status?: Status;
/** Size variant of steps */
size?: 'default' | 'small';
/** Index of currently active step (0-based) */
current?: number;
/** Progress dot configuration - boolean or custom render function */
progressDot?: ProgressDotRender | boolean;
/** Custom step icon renderer function */
stepIcon?: StepIconRender;
/** Starting index offset for step numbering */
initial?: number;
/** Custom icons for finish and error states */
icons?: Icons;
/** Array of step configurations (recommended approach) */
items?: StepProps[];
/** Callback fired when step is clicked */
onChange?: (current: number) => void;
}
declare class Steps extends React.Component<StepsProps> {
/** Reference to Step component for traditional usage */
static Step = Step;
/** Default prop values */
static defaultProps = {
type: 'default',
prefixCls: 'rc-steps',
iconPrefix: 'rc',
direction: 'horizontal',
labelPlacement: 'horizontal',
initial: 0,
current: 0,
status: 'process',
size: '',
progressDot: false,
};
}
export default Steps;
export { Step, type StepsProps, type StepProps, type Status, type Icons, type StepIconRender, type ProgressDotRender };Individual step component that can be used as child of Steps or configured via items array.
interface StepProps {
/** CSS class name prefix */
prefixCls?: string;
/** Additional CSS class names */
className?: string;
/** Inline styles for step item */
style?: React.CSSProperties;
/** Wrapper element styles */
wrapperStyle?: React.CSSProperties;
/** Icon CSS class prefix */
iconPrefix?: string;
/** Whether this step is currently active */
active?: boolean;
/** Whether this step is disabled for interaction */
disabled?: boolean;
/** Step index in the sequence (0-based) */
stepIndex?: number;
/** Display number for step (1-based) */
stepNumber?: number;
/** Status of this step */
status?: Status;
/** Main title/label for the step */
title?: React.ReactNode;
/** Secondary subtitle text */
subTitle?: React.ReactNode;
/** Detailed description text */
description?: React.ReactNode;
/** Custom content in the step tail area */
tailContent?: React.ReactNode;
/** Custom icon element or string icon name */
icon?: React.ReactNode;
/** Custom icons for finish/error states */
icons?: Icons;
/** Click event handler for step container */
onClick?: React.MouseEventHandler<HTMLDivElement>;
/** Step click handler with step index */
onStepClick?: (index: number) => void;
/** Progress dot configuration */
progressDot?: ProgressDotRender | boolean;
/** Custom step icon renderer */
stepIcon?: StepIconRender;
}
declare class Step extends React.Component<StepProps> {}
export { Step };Enable step navigation by providing onChange handler to Steps component.
// Clickable steps with navigation
<Steps
current={current}
onChange={(nextStep) => setCurrent(nextStep)}
items={items}
/>
// Navigation type for horizontal tab-like interface
<Steps
type="navigation"
current={current}
onChange={(nextStep) => setCurrent(nextStep)}
items={items}
/>
// Disable specific steps
const items = [
{ title: "Step 1" },
{ title: "Step 2", disabled: true },
{ title: "Step 3" },
];Customize step appearance with icons, progress dots, and custom renderers.
// Custom icons for finish/error states
const customIcons = {
finish: <CheckIcon />,
error: <ErrorIcon />,
};
<Steps icons={customIcons} items={items} />
// Progress dots instead of numbered steps
<Steps progressDot={true} items={items} />
// Custom progress dot renderer
<Steps
progressDot={(iconDot, {index, status, title}) => (
<span className={`custom-dot ${status}`}>
{status === 'finish' ? '✓' : index + 1}
</span>
)}
items={items}
/>
// Custom step icon renderer
<Steps
stepIcon={({index, status, title, node}) => (
<div className={`custom-icon ${status}`}>
{status === 'process' ? <SpinnerIcon /> : node}
</div>
)}
items={items}
/>
// Individual step icons
const items = [
{ title: "Upload", icon: <UploadIcon /> },
{ title: "Process", icon: "gear" }, // String icon name
{ title: "Complete", icon: <CheckIcon /> },
];Control visual layout and sizing of the steps component.
// Vertical layout
<Steps direction="vertical" items={items} />
// Small size variant
<Steps size="small" items={items} />
// Vertical label placement (for horizontal steps)
<Steps labelPlacement="vertical" items={items} />
// Custom styling
<Steps
className="my-steps"
style={{ backgroundColor: '#f5f5f5' }}
items={items}
/>Control individual step statuses explicitly or rely on automatic status calculation.
// Automatic status based on current prop
<Steps current={1} items={items} />
// Step 0: finish, Step 1: process, Step 2+: wait
// Error status on current step
<Steps current={1} status="error" items={items} />
// Step 0: finish, Step 1: error, Step 2+: wait
// Explicit step statuses
const items = [
{ title: "Step 1", status: "finish" },
{ title: "Step 2", status: "process" },
{ title: "Step 3", status: "error" },
{ title: "Step 4", status: "wait" },
];
<Steps items={items} />/** Step status values */
type Status = 'error' | 'process' | 'finish' | 'wait';
/** Custom icons for finish and error states */
interface Icons {
finish: React.ReactNode;
error: React.ReactNode;
}
/** Custom step icon renderer function */
type StepIconRender = (info: {
/** Step index (0-based) */
index: number;
/** Current step status */
status: Status;
/** Step title content */
title: React.ReactNode;
/** Step description content */
description: React.ReactNode;
/** Default icon node */
node: React.ReactNode;
}) => React.ReactNode;
/** Custom progress dot renderer function */
type ProgressDotRender = (
/** Default dot element */
iconDot,
info: {
/** Step index (0-based) */
index: number;
/** Current step status */
status: Status;
/** Step title content */
title: React.ReactNode;
/** Step description content */
description: React.ReactNode;
}
) => React.ReactNode;RC Steps uses CSS classes for styling with the default prefix rc-steps:
rc-steps - Base steps containerrc-steps-horizontal - Horizontal layoutrc-steps-vertical - Vertical layoutrc-steps-small - Small size variantrc-steps-label-horizontal - Horizontal label placementrc-steps-label-vertical - Vertical label placementrc-steps-dot - Progress dot moderc-steps-navigation - Navigation typerc-steps-item - Individual step containerrc-steps-item-wait - Waiting step statusrc-steps-item-process - Processing step statusrc-steps-item-finish - Finished step statusrc-steps-item-error - Error step statusrc-steps-item-active - Currently active steprc-steps-item-disabled - Disabled steprc-steps-item-custom - Step with custom iconrc-steps-item-container - Step clickable containerrc-steps-item-icon - Step icon containerrc-steps-item-tail - Step connector linerc-steps-item-content - Step text content arearc-steps-item-title - Step title textrc-steps-item-subtitle - Step subtitle textrc-steps-item-description - Step description textimport React, { useState } from "react";
import Steps from "rc-steps";
function WizardForm() {
const [current, setCurrent] = useState(0);
const steps = [
{ title: "Account", description: "Basic information" },
{ title: "Verification", description: "Verify your identity" },
{ title: "Payment", description: "Choose your plan" },
{ title: "Complete", description: "Setup finished" },
];
const next = () => setCurrent(current + 1);
const prev = () => setCurrent(current - 1);
return (
<div>
<Steps current={current} items={steps} />
<div className="steps-content">
{/* Form content based on current step */}
</div>
<div className="steps-action">
{current > 0 && <button onClick={prev}>Previous</button>}
{current < steps.length - 1 && <button onClick={next}>Next</button>}
{current === steps.length - 1 && <button>Done</button>}
</div>
</div>
);
}function ProcessStatus() {
const [status, setStatus] = useState<'process' | 'error' | 'finish'>('process');
const steps = [
{ title: "Submitted", description: "Application received" },
{ title: "Under Review", description: "Processing your request" },
{ title: "Approved", description: "Ready for next step" },
];
return (
<Steps
current={1}
status={status}
items={steps}
/>
);
}function NavigableSteps() {
const [current, setCurrent] = useState(0);
const items = [
{ title: "Step 1", description: "First step" },
{ title: "Step 2", description: "Second step" },
{ title: "Step 3", description: "Final step", disabled: current < 2 },
];
return (
<Steps
current={current}
onChange={(step) => {
// Custom navigation logic
if (step <= current + 1) {
setCurrent(step);
}
}}
items={items}
/>
);
}