Skip to content

Commit

Permalink
Fix: Addressed styling issues with invalid input(orientation/textPosi…
Browse files Browse the repository at this point in the history
…tion), currentActive step outofindex scenario, updated readme (#18)
  • Loading branch information
ReshmaJoshy authored Dec 22, 2023
1 parent 0b6a75a commit bfb645e
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 53 deletions.
68 changes: 46 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,21 @@

<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>

<div style="display: flex; align-items: center;">
<div>
<img src="./src/assets/vertical-stepper-example.png" alt="" width="155" height="252"/>
</div>
<div>
<img src="./src/assets/horizontal-stepper-example.png" alt="" width="518" height="118"/>
</div>
</div>
<table>
<tr>
<td style="text-align: center; border: 0;">
<img src="./src/assets/vertical-stepper-example.png" alt="" width="155" height="252" />
<br />
Vertical Stepper
</td>
<td style="text-align: center; border: 0;">
<img src="./src/assets/horizontal-stepper-example.png" alt="" width="518" height="118" />
<br />
Horizontal Stepper
</td>
</tr>
</table>

A fully customizable ready to use stepper UI package for React.
Try tweaking a stepper using this codesandbox link <a href="https://codesandbox.io/p/sandbox/react-stepper-zp2jrs?file=%2Fsrc%2FApp.js" >here</a>

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

## Style Customizations

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

```jsx
import React from "react";
import Stepper from "react-stepper";

function App() {
const stylesOverride = {
LabelTitle: (step, stepIndex) => ({ ...styles }),
ActiveLabelTitle: (step, stepIndex) => ({ ...styles }),
LabelDescription: (step, stepIndex) => ({ ...styles }),
ActiveLabelDescription: (step, stepIndex) => ({ ...styles }),
LineSeparator: (step, stepIndex) => ({ ...styles }),
InactiveLineSeparator: (step, stepIndex) => ({ ...styles }),
Node: (step, stepIndex) => ({ ...styles }),
ActiveNode: (step, stepIndex) => ({ ...styles }),
InActiveNode: (step, stepIndex) => ({ ...styles }),

const styles = {
LineSeparator: () => ({
backgroundColor: "#028A0F",
}),
ActiveNode: () => ({
backgroundColor: "#028A0F",
}),
CompletedNode: () => ({
backgroundColor: "#028A0F",
};

return (
<Stepper
steps={stepsArray}
currentStepIndex={currentStepIndex}
styles={stylesOverride}
styles={styles}
/>
);
}

export default App;
```
Additional customizations can be made by overriding the customizable styles listed below:
```jsx
const stylesOverride = {
LabelTitle: (step, stepIndex) => ({ ...styles }),
ActiveLabelTitle: (step, stepIndex) => ({ ...styles }),
LabelDescription: (step, stepIndex) => ({ ...styles }),
ActiveLabelDescription: (step, stepIndex) => ({ ...styles }),
LineSeparator: (step, stepIndex) => ({ ...styles }),
InactiveLineSeparator: (step, stepIndex) => ({ ...styles }),
Node: (step, stepIndex) => ({ ...styles }),
ActiveNode: (step, stepIndex) => ({ ...styles }),
InActiveNode: (step, stepIndex) => ({ ...styles }),
};
```
- `LabelTitle` - overrides the step label style
- `ActiveLabelTitle` - overrides the step label style of current active step
- `LabelDescription` - overrides the step description style
- `ActiveLabelDescription` - overrides the step description style of current active step
- `LineSeparator` - overrides default step connector line styles
- `LineSeparator` - overrides default completed step connector line styles
- `InactiveLineSeparator` - overrides styles of step connector line after current active step
- `Node` - overrides default styles of step indicator
- `ActiveNode` - overrides default styles of step indicator of current active step
- `InActiveNode` - overrides default styles of step indicator that is not completed and not active
- `CompletedNode` - overrides default styles of completed step indicator
1 change: 1 addition & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@ export enum Elements {
Node = "Node",
ActiveNode = "ActiveNode",
InActiveNode = "InActiveNode",
CompletedNode = "CompletedNode"
}
1 change: 1 addition & 0 deletions src/node/node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const Node: FC<INodeProps> = (props) => {
style={{
...((getStyles(Elements.Node)) || {}),
...((index === currentStepIndex && getStyles(Elements.ActiveNode)) || {}),
...((step.completed && getStyles(Elements.CompletedNode)) || {}),
...((!step.completed && currentStepIndex !== index
&& getStyles(Elements.InActiveNode)) || {})
}}
Expand Down
12 changes: 7 additions & 5 deletions src/stepper/step.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const Step: (props: IStepProps) => JSX.Element = ({
vertical stepper with label direction top/bottom) */
const isInlineLabelsAndSteps =
(isVertical &&
[LABEL_POSITION.TOP, LABEL_POSITION.BOTTOM].includes(labelPosition)) ||
![LABEL_POSITION.LEFT, LABEL_POSITION.RIGHT].includes(labelPosition)) ||
(!isVertical &&
[LABEL_POSITION.LEFT, LABEL_POSITION.RIGHT].includes(labelPosition));

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

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

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

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

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

return orientation === ORIENTATION.HORIZONTAL &&
return orientation !== ORIENTATION.VERTICAL &&
labelPosition === LABEL_POSITION.TOP ? (
<StepInfo
orientation={orientation}
Expand All @@ -79,6 +79,7 @@ const Step: (props: IStepProps) => JSX.Element = ({
nodeRef={nodeRef}
prevConnectorClassName={prevConnectorClassName}
nextConnectorClassName={nextConnectorClassName}
steps={steps}
/>
) : (
<div
Expand All @@ -104,6 +105,7 @@ const Step: (props: IStepProps) => JSX.Element = ({
nodeRef={nodeRef}
prevConnectorClassName={prevConnectorClassName}
nextConnectorClassName={nextConnectorClassName}
steps={steps}
/>
<StepContent
labelPosition={labelPosition}
Expand Down
4 changes: 2 additions & 2 deletions src/stepper/stepContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const StepContent: (props: IStepContentProps) => JSX.Element = ({
<div
className={middleConnectorClassName}
style={{
...(currentStepIndex > index
...(step.completed
? getStyles(styles, Elements.LineSeparator, step, index) || {}
: getStyles(
styles,
Expand All @@ -50,7 +50,7 @@ const StepContent: (props: IStepContentProps) => JSX.Element = ({
</div>
)}
<div className={isVertical ? "verticalContentWrapper" : ""}>
{(showDescriptionsForAllSteps || index === currentStepIndex) && (
{step.stepDescription && (showDescriptionsForAllSteps || index === currentStepIndex) && (
<div
className="description"
id={`step-description-${index}`}
Expand Down
48 changes: 30 additions & 18 deletions src/stepper/stepInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
styles,
nodeRef,
prevConnectorClassName,
nextConnectorClassName
nextConnectorClassName,
steps
}: IStepInfoProps) => (
<div
id="stepper-step"
Expand All @@ -33,29 +34,35 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
}
>
{!isInlineLabelsAndSteps && (
<div className={getLabelStyle(orientation, labelPosition)}>
<div className={getLabelStyle(orientation, labelPosition)} onClick={(): void => onStepClick && onStepClick(step, index)}>
<div
className="label"
id={`step-label-${index}`}
style={{
...(getStyles(styles, Elements.LabelTitle, step, index) || {}),
...(index === currentStepIndex &&
(getStyles(styles, Elements.ActiveLabelTitle, step, index) || {}))
(getStyles(styles, Elements.ActiveLabelTitle, step, index) ||
{}))
}}
>
{step.stepLabel}
</div>
{(showDescriptionsForAllSteps || index === currentStepIndex) &&
orientation === ORIENTATION.HORIZONTAL &&
{step.stepDescription && (showDescriptionsForAllSteps || index === currentStepIndex) &&
orientation !== ORIENTATION.VERTICAL &&
labelPosition === LABEL_POSITION.TOP && (
<div
className="description"
id={`step-horizontal-top-description-${index}`}
style={{
...(currentStepIndex === index
? getStyles(styles, Elements.ActiveLabelDescription, step, index) ||
{}
: getStyles(styles, Elements.LabelDescription, step, index) || {})
? getStyles(
styles,
Elements.ActiveLabelDescription,
step,
index
) || {}
: getStyles(styles, Elements.LabelDescription, step, index) ||
{})
}}
>
{step.stepDescription}
Expand All @@ -67,9 +74,10 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
<div
className={prevConnectorClassName}
style={{
...(currentStepIndex >= index
...(steps[index - 1]?.completed
? getStyles(styles, Elements.LineSeparator, step, index) || {}
: getStyles(styles, Elements.InactiveLineSeparator, step, index) || {})
: getStyles(styles, Elements.InactiveLineSeparator, step, index) ||
{})
}}
/>
<div
Expand All @@ -83,9 +91,7 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
step={step}
index={index}
currentStepIndex={currentStepIndex}
handleStepClick={(): void =>
onStepClick && onStepClick(step, index)
}
handleStepClick={(): void => onStepClick && onStepClick(step, index)}
showCursor={!!onStepClick}
renderNode={renderNode}
getStyles={(element: Elements): object =>
Expand All @@ -101,22 +107,28 @@ const StepInfo: (props: IStepInfoProps) => JSX.Element = ({
: ""
}`}
>
<div className={`label ${isVertical && "verticalStepperInlineLabel"}`} id={`step-inline-label-${index}`}
<div
className={`label ${isVertical && "verticalStepperInlineLabel"}`}
id={`step-inline-label-${index}`}
style={{
...(getStyles(styles, Elements.LabelTitle, step, index) || {}),
...(index === currentStepIndex &&
(getStyles(styles, Elements.ActiveLabelTitle, step, index) || {}))
}}>
(getStyles(styles, Elements.ActiveLabelTitle, step, index) ||
{}))
}}
onClick={(): void => onStepClick && onStepClick(step, index)}
>
{step.stepLabel}
</div>
</div>
)}
<div
className={nextConnectorClassName}
style={{
...(currentStepIndex > index
...(step.completed
? getStyles(styles, Elements.LineSeparator, step, index) || {}
: getStyles(styles, Elements.InactiveLineSeparator, step, index) || {})
: getStyles(styles, Elements.InactiveLineSeparator, step, index) ||
{})
}}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/stepper/stepperComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const Stepper = (props: IStepperProps): JSX.Element => {
isVertical ? "verticalStepper" : "horizontalStepper"
}`}
>
{steps.map((step, index) => Step({ stepperProps: props, step, index }))}
{steps.map((step, index) => <Step key={`${step.stepLabel}-${step.stepDescription}`} stepperProps={props} step={step} index={index} />)}
</ul>
{!isVertical && // For horizontal stepper, the content is displayed below the stepper with full width
stepContent &&
Expand Down
3 changes: 2 additions & 1 deletion src/stepper/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type IStepperProps = {
steps: IStep[];
currentStepIndex?: number;
orientation?: ORIENTATION.HORIZONTAL | ORIENTATION.VERTICAL;
styles?: { [key in Elements]: IStyleFunction };
styles?: { [key in Elements]?: IStyleFunction };
labelPosition?: LABEL_POSITION.LEFT | LABEL_POSITION.RIGHT | LABEL_POSITION.TOP | LABEL_POSITION.BOTTOM;
showDescriptionsForAllSteps?: boolean;
stepContent?(step: IStep, stepIndex: number): ReactElement;
Expand Down Expand Up @@ -43,6 +43,7 @@ export type IStepInfoProps = {
nodeRef: LegacyRef<HTMLDivElement> | undefined
prevConnectorClassName: string;
nextConnectorClassName: string;
steps: IStep[];
}

export type IStepContentProps = {
Expand Down
Loading

0 comments on commit bfb645e

Please sign in to comment.