Skip to content

Commit bfb645e

Browse files
authored
Fix: Addressed styling issues with invalid input(orientation/textPosition), currentActive step outofindex scenario, updated readme (#18)
1 parent 0b6a75a commit bfb645e

10 files changed

+167
-53
lines changed

README.md

+46-22
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,21 @@
22

33
<a href="https://www.npmjs.com/package/@keyvaluesystems/react-stepper"><img src="https://badgen.net/npm/v/@keyvaluesystems/react-stepper?color=blue" alt="npm version"></a> <a href="https://www.npmjs.com/package/@keyvaluesystems/react-stepper" ><img src="https://img.shields.io/npm/dw/@keyvaluesystems/react-stepper?label=Downloads" /></a> <a href="https://github.com/KeyValueSoftwareSystems/react-stepper"><img src="https://github.com/KeyValueSoftwareSystems/react-stepper/actions/workflows/update-and-publish.yml/badge.svg" alt="" /></a>
44

5-
<div style="display: flex; align-items: center;">
6-
<div>
7-
<img src="./src/assets/vertical-stepper-example.png" alt="" width="155" height="252"/>
8-
</div>
9-
<div>
10-
<img src="./src/assets/horizontal-stepper-example.png" alt="" width="518" height="118"/>
11-
</div>
12-
</div>
5+
<table>
6+
<tr>
7+
<td style="text-align: center; border: 0;">
8+
<img src="./src/assets/vertical-stepper-example.png" alt="" width="155" height="252" />
9+
<br />
10+
Vertical Stepper
11+
</td>
12+
<td style="text-align: center; border: 0;">
13+
<img src="./src/assets/horizontal-stepper-example.png" alt="" width="518" height="118" />
14+
<br />
15+
Horizontal Stepper
16+
</td>
17+
</tr>
18+
</table>
19+
1320
A fully customizable ready to use stepper UI package for React.
1421
Try tweaking a stepper using this codesandbox link <a href="https://codesandbox.io/p/sandbox/react-stepper-zp2jrs?file=%2Fsrc%2FApp.js" >here</a>
1522

@@ -147,43 +154,60 @@ Props that can be passed to the component are listed below:
147154

148155
## Style Customizations
149156

150-
All the default styles provided by this package can be overridden using the `style` prop
151-
the below code shows all the styles that can be overridden:
157+
All the default styles provided by this package can be overridden using the `styles` prop
158+
Below code shows how to override the default styles of completed steps, connector lines and current active step
152159

153160
```jsx
154161
import React from "react";
155162
import Stepper from "react-stepper";
156163

157164
function App() {
158-
const stylesOverride = {
159-
LabelTitle: (step, stepIndex) => ({ ...styles }),
160-
ActiveLabelTitle: (step, stepIndex) => ({ ...styles }),
161-
LabelDescription: (step, stepIndex) => ({ ...styles }),
162-
ActiveLabelDescription: (step, stepIndex) => ({ ...styles }),
163-
LineSeparator: (step, stepIndex) => ({ ...styles }),
164-
InactiveLineSeparator: (step, stepIndex) => ({ ...styles }),
165-
Node: (step, stepIndex) => ({ ...styles }),
166-
ActiveNode: (step, stepIndex) => ({ ...styles }),
167-
InActiveNode: (step, stepIndex) => ({ ...styles }),
165+
166+
const styles = {
167+
LineSeparator: () => ({
168+
backgroundColor: "#028A0F",
169+
}),
170+
ActiveNode: () => ({
171+
backgroundColor: "#028A0F",
172+
}),
173+
CompletedNode: () => ({
174+
backgroundColor: "#028A0F",
168175
};
176+
169177
return (
170178
<Stepper
171179
steps={stepsArray}
172180
currentStepIndex={currentStepIndex}
173-
styles={stylesOverride}
181+
styles={styles}
174182
/>
175183
);
176184
}
177185

178186
export default App;
179187
```
188+
Additional customizations can be made by overriding the customizable styles listed below:
189+
190+
```jsx
191+
const stylesOverride = {
192+
LabelTitle: (step, stepIndex) => ({ ...styles }),
193+
ActiveLabelTitle: (step, stepIndex) => ({ ...styles }),
194+
LabelDescription: (step, stepIndex) => ({ ...styles }),
195+
ActiveLabelDescription: (step, stepIndex) => ({ ...styles }),
196+
LineSeparator: (step, stepIndex) => ({ ...styles }),
197+
InactiveLineSeparator: (step, stepIndex) => ({ ...styles }),
198+
Node: (step, stepIndex) => ({ ...styles }),
199+
ActiveNode: (step, stepIndex) => ({ ...styles }),
200+
InActiveNode: (step, stepIndex) => ({ ...styles }),
201+
};
202+
```
180203
181204
- `LabelTitle` - overrides the step label style
182205
- `ActiveLabelTitle` - overrides the step label style of current active step
183206
- `LabelDescription` - overrides the step description style
184207
- `ActiveLabelDescription` - overrides the step description style of current active step
185-
- `LineSeparator` - overrides default step connector line styles
208+
- `LineSeparator` - overrides default completed step connector line styles
186209
- `InactiveLineSeparator` - overrides styles of step connector line after current active step
187210
- `Node` - overrides default styles of step indicator
188211
- `ActiveNode` - overrides default styles of step indicator of current active step
189212
- `InActiveNode` - overrides default styles of step indicator that is not completed and not active
213+
- `CompletedNode` - overrides default styles of completed step indicator

src/constants.ts

+1
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@ export enum Elements {
2121
Node = "Node",
2222
ActiveNode = "ActiveNode",
2323
InActiveNode = "InActiveNode",
24+
CompletedNode = "CompletedNode"
2425
}

src/node/node.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ const Node: FC<INodeProps> = (props) => {
2626
style={{
2727
...((getStyles(Elements.Node)) || {}),
2828
...((index === currentStepIndex && getStyles(Elements.ActiveNode)) || {}),
29+
...((step.completed && getStyles(Elements.CompletedNode)) || {}),
2930
...((!step.completed && currentStepIndex !== index
3031
&& getStyles(Elements.InActiveNode)) || {})
3132
}}

src/stepper/step.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const Step: (props: IStepProps) => JSX.Element = ({
3030
vertical stepper with label direction top/bottom) */
3131
const isInlineLabelsAndSteps =
3232
(isVertical &&
33-
[LABEL_POSITION.TOP, LABEL_POSITION.BOTTOM].includes(labelPosition)) ||
33+
![LABEL_POSITION.LEFT, LABEL_POSITION.RIGHT].includes(labelPosition)) ||
3434
(!isVertical &&
3535
[LABEL_POSITION.LEFT, LABEL_POSITION.RIGHT].includes(labelPosition));
3636

@@ -42,17 +42,17 @@ const Step: (props: IStepProps) => JSX.Element = ({
4242
const width = node.getBoundingClientRect().width;
4343
setNodeWidth(width);
4444
}
45-
}, [steps]);
45+
}, [steps, labelPosition, orientation]);
4646

4747
// prevConnector represents the connector line from the current step's node (nth node) to the preceding step's node (n-1 th node).
4848
const prevConnectorClassName = `stepConnector leftConnector ${
49-
currentStepIndex >= index ? "activeConnector" : ""
49+
steps[index - 1]?.completed ? "activeConnector" : ""
5050
} ${index === 0 ? "hiddenConnector" : ""}`;
5151

5252
// nextConnector represents the connector line from the current step's node (nth node) to the preceding step's node (n-1 th node).
5353

5454
const nextConnectorClassName = `stepConnector rightConnector ${
55-
currentStepIndex > index ? "activeConnector" : ""
55+
steps[index]?.completed ? "activeConnector" : ""
5656
} ${index === steps.length - 1 ? "hiddenConnector" : ""}`;
5757

5858
/* middleConnector connects the current step nextConnector to (n+1th) step prevConnector,
@@ -62,7 +62,7 @@ const Step: (props: IStepProps) => JSX.Element = ({
6262
currentStepIndex > index ? "activeConnector" : ""
6363
} ${index === steps.length - 1 ? "hiddenConnector" : ""}`;
6464

65-
return orientation === ORIENTATION.HORIZONTAL &&
65+
return orientation !== ORIENTATION.VERTICAL &&
6666
labelPosition === LABEL_POSITION.TOP ? (
6767
<StepInfo
6868
orientation={orientation}
@@ -79,6 +79,7 @@ const Step: (props: IStepProps) => JSX.Element = ({
7979
nodeRef={nodeRef}
8080
prevConnectorClassName={prevConnectorClassName}
8181
nextConnectorClassName={nextConnectorClassName}
82+
steps={steps}
8283
/>
8384
) : (
8485
<div
@@ -104,6 +105,7 @@ const Step: (props: IStepProps) => JSX.Element = ({
104105
nodeRef={nodeRef}
105106
prevConnectorClassName={prevConnectorClassName}
106107
nextConnectorClassName={nextConnectorClassName}
108+
steps={steps}
107109
/>
108110
<StepContent
109111
labelPosition={labelPosition}

src/stepper/stepContent.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const StepContent: (props: IStepContentProps) => JSX.Element = ({
3737
<div
3838
className={middleConnectorClassName}
3939
style={{
40-
...(currentStepIndex > index
40+
...(step.completed
4141
? getStyles(styles, Elements.LineSeparator, step, index) || {}
4242
: getStyles(
4343
styles,
@@ -50,7 +50,7 @@ const StepContent: (props: IStepContentProps) => JSX.Element = ({
5050
</div>
5151
)}
5252
<div className={isVertical ? "verticalContentWrapper" : ""}>
53-
{(showDescriptionsForAllSteps || index === currentStepIndex) && (
53+
{step.stepDescription && (showDescriptionsForAllSteps || index === currentStepIndex) && (
5454
<div
5555
className="description"
5656
id={`step-description-${index}`}

src/stepper/stepInfo.tsx

+30-18
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
2020
styles,
2121
nodeRef,
2222
prevConnectorClassName,
23-
nextConnectorClassName
23+
nextConnectorClassName,
24+
steps
2425
}: IStepInfoProps) => (
2526
<div
2627
id="stepper-step"
@@ -33,29 +34,35 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
3334
}
3435
>
3536
{!isInlineLabelsAndSteps && (
36-
<div className={getLabelStyle(orientation, labelPosition)}>
37+
<div className={getLabelStyle(orientation, labelPosition)} onClick={(): void => onStepClick && onStepClick(step, index)}>
3738
<div
3839
className="label"
3940
id={`step-label-${index}`}
4041
style={{
4142
...(getStyles(styles, Elements.LabelTitle, step, index) || {}),
4243
...(index === currentStepIndex &&
43-
(getStyles(styles, Elements.ActiveLabelTitle, step, index) || {}))
44+
(getStyles(styles, Elements.ActiveLabelTitle, step, index) ||
45+
{}))
4446
}}
4547
>
4648
{step.stepLabel}
4749
</div>
48-
{(showDescriptionsForAllSteps || index === currentStepIndex) &&
49-
orientation === ORIENTATION.HORIZONTAL &&
50+
{step.stepDescription && (showDescriptionsForAllSteps || index === currentStepIndex) &&
51+
orientation !== ORIENTATION.VERTICAL &&
5052
labelPosition === LABEL_POSITION.TOP && (
5153
<div
5254
className="description"
5355
id={`step-horizontal-top-description-${index}`}
5456
style={{
5557
...(currentStepIndex === index
56-
? getStyles(styles, Elements.ActiveLabelDescription, step, index) ||
57-
{}
58-
: getStyles(styles, Elements.LabelDescription, step, index) || {})
58+
? getStyles(
59+
styles,
60+
Elements.ActiveLabelDescription,
61+
step,
62+
index
63+
) || {}
64+
: getStyles(styles, Elements.LabelDescription, step, index) ||
65+
{})
5966
}}
6067
>
6168
{step.stepDescription}
@@ -67,9 +74,10 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
6774
<div
6875
className={prevConnectorClassName}
6976
style={{
70-
...(currentStepIndex >= index
77+
...(steps[index - 1]?.completed
7178
? getStyles(styles, Elements.LineSeparator, step, index) || {}
72-
: getStyles(styles, Elements.InactiveLineSeparator, step, index) || {})
79+
: getStyles(styles, Elements.InactiveLineSeparator, step, index) ||
80+
{})
7381
}}
7482
/>
7583
<div
@@ -83,9 +91,7 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
8391
step={step}
8492
index={index}
8593
currentStepIndex={currentStepIndex}
86-
handleStepClick={(): void =>
87-
onStepClick && onStepClick(step, index)
88-
}
94+
handleStepClick={(): void => onStepClick && onStepClick(step, index)}
8995
showCursor={!!onStepClick}
9096
renderNode={renderNode}
9197
getStyles={(element: Elements): object =>
@@ -101,22 +107,28 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
101107
: ""
102108
}`}
103109
>
104-
<div className={`label ${isVertical && "verticalStepperInlineLabel"}`} id={`step-inline-label-${index}`}
110+
<div
111+
className={`label ${isVertical && "verticalStepperInlineLabel"}`}
112+
id={`step-inline-label-${index}`}
105113
style={{
106114
...(getStyles(styles, Elements.LabelTitle, step, index) || {}),
107115
...(index === currentStepIndex &&
108-
(getStyles(styles, Elements.ActiveLabelTitle, step, index) || {}))
109-
}}>
116+
(getStyles(styles, Elements.ActiveLabelTitle, step, index) ||
117+
{}))
118+
}}
119+
onClick={(): void => onStepClick && onStepClick(step, index)}
120+
>
110121
{step.stepLabel}
111122
</div>
112123
</div>
113124
)}
114125
<div
115126
className={nextConnectorClassName}
116127
style={{
117-
...(currentStepIndex > index
128+
...(step.completed
118129
? getStyles(styles, Elements.LineSeparator, step, index) || {}
119-
: getStyles(styles, Elements.InactiveLineSeparator, step, index) || {})
130+
: getStyles(styles, Elements.InactiveLineSeparator, step, index) ||
131+
{})
120132
}}
121133
/>
122134
</div>

src/stepper/stepperComponent.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const Stepper = (props: IStepperProps): JSX.Element => {
2121
isVertical ? "verticalStepper" : "horizontalStepper"
2222
}`}
2323
>
24-
{steps.map((step, index) => Step({ stepperProps: props, step, index }))}
24+
{steps.map((step, index) => <Step key={`${step.stepLabel}-${step.stepDescription}`} stepperProps={props} step={step} index={index} />)}
2525
</ul>
2626
{!isVertical && // For horizontal stepper, the content is displayed below the stepper with full width
2727
stepContent &&

src/stepper/types.d.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export type IStepperProps = {
1212
steps: IStep[];
1313
currentStepIndex?: number;
1414
orientation?: ORIENTATION.HORIZONTAL | ORIENTATION.VERTICAL;
15-
styles?: { [key in Elements]: IStyleFunction };
15+
styles?: { [key in Elements]?: IStyleFunction };
1616
labelPosition?: LABEL_POSITION.LEFT | LABEL_POSITION.RIGHT | LABEL_POSITION.TOP | LABEL_POSITION.BOTTOM;
1717
showDescriptionsForAllSteps?: boolean;
1818
stepContent?(step: IStep, stepIndex: number): ReactElement;
@@ -43,6 +43,7 @@ export type IStepInfoProps = {
4343
nodeRef: LegacyRef<HTMLDivElement> | undefined
4444
prevConnectorClassName: string;
4545
nextConnectorClassName: string;
46+
steps: IStep[];
4647
}
4748

4849
export type IStepContentProps = {

0 commit comments

Comments
 (0)