Skip to content

Commit 0fc71b3

Browse files
committed
New COntrol ProgressStepsIndicator
1 parent ead7115 commit 0fc71b3

File tree

12 files changed

+312
-27
lines changed

12 files changed

+312
-27
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Progress Steps Indicator
2+
3+
This control shows a progress of steps.
4+
5+
Here is an example of the control in action:
6+
7+
![ProgressStepsIndicator](../assets/ProgressStepsIndicator.png)
8+
9+
10+
11+
## How to use this control in your solutions
12+
13+
- Check that you installed the `@pnp/spfx-controls-react` dependency. Check out the [getting started](../../#getting-started) page for more information about installing the dependency.
14+
- In your component file, import the `Accordion` control as follows:
15+
16+
```TypeScript
17+
import { ProgressStepsIndicator } from '"@pnp/spfx-controls-react/lib/ProgressStepsIndicator';
18+
19+
const progressSteps: IStep[] = [
20+
{ id: 0, title: "Step 1", description: "Step 1 Description" },
21+
{ id: 1, title: "Step 2", description: "Step 2 Description" },
22+
{ id: 3, title: "Step 3", description: "Step 3 Description" },
23+
{ id: 4, title: "Step 4", description: "Step 4 Description" },
24+
{ id: 5, title: "Step 5", description: "Step 5 Description" },
25+
{ id: 6, title: "Step 6", description: "Step 6 Description" },
26+
];
27+
```
28+
29+
- Use the `ProgressStepsIndicator` control in your code as follows:
30+
31+
```TypeScript
32+
{
33+
<ProgressStepsIndicator steps={progressSteps} currentStep={0} themeVariant={props.themeVariant} />
34+
}
35+
```
36+
37+
38+
## Implementation
39+
40+
The `ProgressStepsIndicator` control can be configured with the following properties:
41+
42+
| Property | Type | Required | Description | Default |
43+
| ---- | ---- | ---- | ---- | ---- |
44+
| steps | ISteps[] | yes | Perogress Steps | |
45+
| currentStep | number | yes | index of current step | default is 0|
46+
| themeVariant | IReadonlyTheme | undefined | no | Theme | |
47+
48+
The `IStep Interface` definition:
49+
50+
```TypeScript
51+
Interface IStep {
52+
id?:number;
53+
title:string;
54+
description:string;
55+
}
56+
```
57+
58+
59+
60+
61+
![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/ProgressStepsIndicator)

package-lock.json

Lines changed: 24 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/ProgressStepsIndicator.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './controls/ProgressStepsIndicator';
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { IReadonlyTheme } from '@microsoft/sp-component-base';
2+
3+
import { IStep } from './IStep';
4+
5+
export interface IProgressStepsIndicatorProps {
6+
steps?:IStep[];
7+
currentStep?:number;
8+
themeVariant?: IReadonlyTheme | undefined;
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface IStep {
2+
id?:number;
3+
title:string;
4+
description:string;
5+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import * as React from 'react';
2+
3+
import * as strings from 'ControlStrings';
4+
import {
5+
Customizer,
6+
Icon,
7+
Label,
8+
MessageBar,
9+
MessageBarType,
10+
Stack,
11+
} from 'office-ui-fabric-react';
12+
13+
import { IProgressStepsIndicatorProps } from './IProgressStepsIndicatorProps';
14+
import {
15+
getProgressStepsIndicatorStyles,
16+
} from './ProgressStepsIndicatorStyles';
17+
18+
export const ProgressStepsIndicator: React.FunctionComponent<IProgressStepsIndicatorProps> = (
19+
props: IProgressStepsIndicatorProps
20+
) => {
21+
const [renderSteps, setRenderSteps] = React.useState<JSX.Element[]>([]);
22+
const [renderStepsTitle, setRenderStepsTitle] = React.useState<JSX.Element[]>([]);
23+
const { steps, currentStep, themeVariant } = props;
24+
const {
25+
labelStepTitleCurrentStyle,
26+
labelStepTitleStyle,
27+
labelStepStyles,
28+
stackStepsStyles,
29+
componentClasses,
30+
} = getProgressStepsIndicatorStyles(themeVariant, currentStep, steps.length);
31+
32+
React.useEffect(() => {
33+
(() => {
34+
const _renderSteps: JSX.Element[] = [];
35+
const _renderStepTitle: JSX.Element[] = [];
36+
37+
const _currentStep: number = currentStep ? currentStep : 0;
38+
if (steps && steps.length) {
39+
steps.map((step, i) => {
40+
if (_currentStep > i) {
41+
_renderSteps.push(
42+
<Stack key={`${i}`} horizontal>
43+
<div className={componentClasses.bulletCompleted}>
44+
<Icon iconName={"CheckMark"} />
45+
</div>
46+
</Stack>
47+
);
48+
49+
_renderStepTitle.push(
50+
<Label key={`${i}`} styles={labelStepTitleStyle}>
51+
{step.title}
52+
</Label>
53+
);
54+
}
55+
56+
if (_currentStep === i) {
57+
_renderSteps.push(
58+
<Stack key={`${i}`} horizontal>
59+
<div key={`${i}`} className={componentClasses.bulletCurrent}>
60+
<Label styles={labelStepStyles}>{i + 1}</Label>
61+
</div>
62+
</Stack>
63+
);
64+
_renderStepTitle.push(
65+
<Label key={`${i}`} styles={labelStepTitleCurrentStyle}>
66+
{step.title}
67+
</Label>
68+
);
69+
}
70+
if (_currentStep < i) {
71+
_renderSteps.push(
72+
<div key={`${i}`} className={componentClasses.bullet}>
73+
<Label styles={labelStepStyles}>{i + 1}</Label>
74+
</div>
75+
);
76+
_renderStepTitle.push(
77+
<Label key={`${i}`} styles={labelStepTitleStyle}>
78+
{step.title}
79+
</Label>
80+
);
81+
}
82+
});
83+
}
84+
setRenderSteps(_renderSteps);
85+
setRenderStepsTitle(_renderStepTitle);
86+
})();
87+
}, [steps, currentStep]);
88+
89+
if (steps && steps.length === 0) {
90+
return <MessageBar messageBarType={MessageBarType.info}>{strings.ProgressStepsIndicatorNoSteps}</MessageBar>;
91+
}
92+
93+
return (
94+
<Customizer settings={{ theme: props.themeVariant }}>
95+
<Stack styles={stackStepsStyles}>
96+
<div className={componentClasses.line} />
97+
<Stack horizontal horizontalAlign="space-between">
98+
{renderSteps}
99+
</Stack>
100+
</Stack>
101+
<Stack horizontal horizontalAlign="space-between" styles={{ root: { marginTop: "7px !important" } }}>
102+
{renderStepsTitle}
103+
</Stack>
104+
</Customizer>
105+
);
106+
};
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/* eslint-disable @typescript-eslint/explicit-function-return-type */
2+
import {
3+
ILabelStyles,
4+
IStackStyles,
5+
IStyle,
6+
mergeStyleSets,
7+
} from 'office-ui-fabric-react';
8+
9+
import { IReadonlyTheme } from '@microsoft/sp-component-base';
10+
11+
export const getProgressStepsIndicatorStyles = (themeVariant: IReadonlyTheme, currentStep?:number, totalSteps?:number ) => {
12+
13+
const labelStepTitleCurrentStyle: ILabelStyles = {
14+
root: {
15+
fontWeight: 700,
16+
width: 150,
17+
textAlign: "center",
18+
},
19+
};
20+
21+
const labelStepTitleStyle: ILabelStyles = {
22+
root: {
23+
width: 150,
24+
textAlign: "center",
25+
},
26+
};
27+
28+
const labelStepStyles: ILabelStyles = {
29+
root: {
30+
fontWeight: 400,
31+
},
32+
};
33+
34+
const stackStepsStyles: IStackStyles = {
35+
root: { marginLeft: 50, marginRight: 50 },
36+
};
37+
38+
const componentClasses = mergeStyleSets({
39+
bulletCurrent: {
40+
borderStyle: "solid",
41+
borderWidth: 2,
42+
borderColor: themeVariant?.palette?.themePrimary,
43+
width: 34,
44+
height: 34,
45+
borderRadius: "50%",
46+
display: "flex",
47+
justifyContent: "center",
48+
horizontalAlign: "center",
49+
zIndex: 111,
50+
backgroundColor: themeVariant?.palette?.neutralLighter,
51+
fontSize: 16,
52+
alignItems: "center",
53+
},
54+
bulletCompleted: {
55+
cursor: "default",
56+
width: 34,
57+
height: 34,
58+
borderRadius: "50%",
59+
display: "flex",
60+
justifyContent: "center",
61+
horizontalAlign: "center",
62+
zIndex: 111,
63+
backgroundColor: themeVariant?.palette?.themePrimary,
64+
color: themeVariant?.palette?.themeLighter,
65+
fontSize: 16,
66+
alignItems: "center",
67+
},
68+
bullet: {
69+
borderColor: themeVariant?.palette?.neutralTertiaryAlt,
70+
borderStyle: "solid",
71+
borderWidth: 2,
72+
width: 34,
73+
height: 34,
74+
borderRadius: "50%",
75+
display: "flex",
76+
justifyContent: "center",
77+
alignItems: "center",
78+
horizontalAlign: "center",
79+
verticalAlign: "center",
80+
backgroundColor: themeVariant?.palette?.neutralLight,
81+
fontSize: 16,
82+
zIndex: 111,
83+
},
84+
line: {
85+
height: 2,
86+
backgroundColor: themeVariant?.palette?.neutralQuaternaryAlt,
87+
width: "100%",
88+
position: "relative",
89+
top: 17,
90+
zIndex: 0,
91+
} as IStyle,
92+
93+
});
94+
95+
return {labelStepTitleCurrentStyle,stackStepsStyles,labelStepStyles, labelStepTitleStyle,componentClasses};
96+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './ProgressStepsIndicator';
2+
export { IProgressStepsIndicatorProps } from './IProgressStepsIndicatorProps';
3+
export { IStep } from './IStep';

src/loc/en-us.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ define([], () => {
404404
ModernAudioPause: "Pause",
405405
ModernAudioIncVol: "Increase Volume",
406406
ModernAudioDecVol: "Decrease Volume",
407-
ModernAudioMute: "Mute"
407+
ModernAudioMute: "Mute",
408+
ProgressStepsIndicatorNoSteps: "No steps",
408409
};
409410
});

src/loc/mystrings.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
declare interface IControlStrings {
2+
ProgressStepsIndicatorNoSteps:string;
23
ListItemCommentsLabel: string;
34
ListItemCommentsNoCommentsLabel: string;
45
ListItemCommentDIalogDeleteSubText: string;

0 commit comments

Comments
 (0)