Skip to content

Commit 29eacf4

Browse files
committed
feat: [Stepper] support inverted
1 parent f655b5c commit 29eacf4

File tree

4 files changed

+168
-33
lines changed

4 files changed

+168
-33
lines changed

demo/src/demo/Stepper.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,85 @@ export default () => (
1313
<Step title="退款成功" />
1414
</Stepper>
1515
</DemoSection>
16+
<DemoSection title="倒序">
17+
<Stepper inverted>
18+
<Step
19+
title="官方客服处理中"
20+
subTitle="05-23 11:23"
21+
desc="客服将在24小时内联系您核实问题,请注意接听。"
22+
/>
23+
<Step
24+
title="您发起投诉"
25+
subTitle="05-23 11:23"
26+
desc={
27+
<div>
28+
<div>投诉原因:物流问题,未放指定代收点。</div>
29+
<div>投诉说明:都说了很多遍不要放驿站,还是放了。</div>
30+
</div>
31+
}
32+
/>
33+
</Stepper>
34+
</DemoSection>
35+
<DemoSection title="倒序&成功">
36+
<Stepper inverted status="success">
37+
<Step
38+
title="官方客服判决,投诉成立"
39+
subTitle="05-23 11:23"
40+
desc="客服将在24小时内联系您核实问题,请注意接听。"
41+
/>
42+
<Step
43+
title="您补充留言"
44+
subTitle="05-23 11:23"
45+
desc="卖家说好要发货怎么不发货,态度太差了!!"
46+
/>
47+
<Step title="买家填写退货并填写物流信息" subTitle="昨天 15:00" />
48+
<Step title="卖家确认收货并退款" subTitle="昨天 16:00" />
49+
<Step title="退款成功" />
50+
</Stepper>
51+
</DemoSection>
52+
<DemoSection title="倒序&失败">
53+
<Stepper inverted status="fail">
54+
<Step
55+
title="官方客服判决,投诉不成立"
56+
subTitle="05-23 11:23"
57+
desc="原因:核实订单还在约定发货时效内,已催促卖家发货,请耐心等待。"
58+
/>
59+
<Step
60+
title="官方客服处理中"
61+
subTitle="05-23 11:23"
62+
desc="客服将在24小时内联系您核实问题,请注意接听。"
63+
/>
64+
<Step
65+
title="您发起投诉"
66+
subTitle="05-23 11:23"
67+
desc={
68+
<div>
69+
<div>投诉原因:物流问题,未放指定代收点。</div>
70+
<div>投诉说明:都说了很多遍不要放驿站,还是放了。</div>
71+
</div>
72+
}
73+
/>
74+
</Stepper>
75+
</DemoSection>
76+
<DemoSection title="倒序&取消">
77+
<Stepper inverted status="abort">
78+
<Step title="您撤销投诉" subTitle="05-23 11:23" desc="若后续遇到有问题,您可联系客服。" />
79+
<Step
80+
title="官方客服处理中"
81+
subTitle="05-23 11:23"
82+
desc="客服将在24小时内联系您核实问题,请注意接听。"
83+
/>
84+
<Step
85+
title="您发起投诉"
86+
subTitle="05-23 11:23"
87+
desc={
88+
<div>
89+
<div>投诉原因:物流问题,未放指定代收点。</div>
90+
<div>投诉说明:都说了很多遍不要放驿站,还是放了。</div>
91+
</div>
92+
}
93+
/>
94+
</Stepper>
95+
</DemoSection>
1696
</DemoPage>
1797
);

src/components/Stepper/Step.tsx

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,44 @@
11
import React from 'react';
22
import clsx from 'clsx';
3+
import { Icon } from '../Icon';
4+
5+
export type StepStatus = 'success' | 'fail' | 'abort';
36

47
export type StepProps = {
58
className?: string;
69
active?: boolean;
710
completed?: boolean;
811
disabled?: boolean;
12+
status?: StepStatus;
913
index?: number;
1014
title?: string;
11-
desc?: string;
15+
subTitle?: string;
16+
desc?: React.ReactNode;
1217
children?: React.ReactNode;
1318
};
1419

20+
function renderDot(status?: StepStatus) {
21+
if (status) {
22+
const iconMap: Record<string, string> = {
23+
success: 'check-circle-fill',
24+
fail: 'warning-circle-fill',
25+
abort: 'dash-circle-fill',
26+
};
27+
return <Icon type={iconMap[status]} />;
28+
}
29+
return <div className="Step-dot" />;
30+
}
31+
1532
export const Step = React.forwardRef<HTMLLIElement, StepProps>((props, ref) => {
1633
const {
1734
className,
1835
active = false,
1936
completed = false,
2037
disabled = false,
38+
status,
2139
index,
2240
title,
41+
subTitle,
2342
desc,
2443
children,
2544
...other
@@ -37,12 +56,18 @@ export const Step = React.forwardRef<HTMLLIElement, StepProps>((props, ref) => {
3756
className,
3857
)}
3958
ref={ref}
59+
data-status={status}
4060
{...other}
4161
>
42-
<div className="Step-dot" />
62+
<div className="Step-icon">{renderDot(status)}</div>
4363
<div className="Step-line" />
4464
<div className="Step-content">
45-
{title && <div className="Step-title">{title}</div>}
65+
{title && (
66+
<div className="Step-title">
67+
{title && <span>{title}</span>}
68+
{subTitle && <small>{subTitle}</small>}
69+
</div>
70+
)}
4671
{desc && <div className="Step-desc">{desc}</div>}
4772
{children}
4873
</div>

src/components/Stepper/Stepper.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
import React from 'react';
22
import clsx from 'clsx';
3+
import type { StepProps, StepStatus } from './Step';
34

45
export type StepperProps = {
56
className?: string;
67
current?: number;
8+
status?: StepStatus;
9+
inverted?: boolean;
710
children?: React.ReactNode;
811
};
912

1013
export const Stepper = React.forwardRef<HTMLUListElement, StepperProps>((props, ref) => {
11-
const { className, current = 0, children, ...other } = props;
14+
const { className, current = 0, status, inverted, children, ...other } = props;
1215

1316
const childrenArray = React.Children.toArray(children);
1417
const steps = childrenArray.map((child, index) => {
15-
const state = {
18+
const state: StepProps = {
1619
index,
1720
active: false,
1821
completed: false,
@@ -21,10 +24,12 @@ export const Stepper = React.forwardRef<HTMLUListElement, StepperProps>((props,
2124

2225
if (current === index) {
2326
state.active = true;
27+
state.status = status;
2428
} else if (current > index) {
2529
state.completed = true;
2630
} else {
27-
state.disabled = true;
31+
state.disabled = !inverted;
32+
state.completed = inverted;
2833
}
2934

3035
return React.isValidElement(child)

src/components/Stepper/style.less

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
@step-icon-width: 24px;
2+
13
.Stepper {
24
margin: 0;
35
padding: 0;
@@ -6,8 +8,8 @@
68

79
.Step {
810
position: relative;
9-
padding-left: 24px;
10-
padding-bottom: 10px;
11+
padding-left: (@step-icon-width + 5px);
12+
padding-bottom: 18px;
1113

1214
&:last-child {
1315
padding-bottom: 0;
@@ -20,54 +22,77 @@
2022

2123
.Step--active {
2224
.Step-dot {
23-
transform: scale(1.5);
2425
background: var(--brand-1);
2526
}
26-
.Step-line {
27-
background: var(--gray-6);
27+
.Step-title {
28+
span {
29+
color: var(--brand-1);
30+
font-weight: 500;
31+
}
2832
}
29-
.Step-title,
3033
.Step-desc {
3134
color: var(--gray-1);
3235
}
33-
}
34-
35-
.Step--disabled {
36-
.Step-dot,
37-
.Step-line {
38-
background: var(--gray-6);
36+
&[data-status] {
37+
.Step-line {
38+
top: (@step-icon-width + 2px);
39+
}
40+
.Step-icon {
41+
color: var(--red);
42+
}
3943
}
40-
.Step-title,
41-
.Step-desc {
42-
color: var(--gray-4);
44+
&[data-status='success'] {
45+
.Step-icon {
46+
color: var(--green);
47+
}
4348
}
4449
}
4550

46-
.Step-dot {
51+
.Step-icon {
4752
position: absolute;
48-
top: 6px;
49-
left: 2px;
50-
z-index: @zindex-step-dot;
53+
top: 0;
54+
left: 0;
55+
width: @step-icon-width;
56+
height: @step-icon-width;
57+
font-size: @step-icon-width;
58+
display: flex;
59+
justify-content: center;
60+
align-items: center;
61+
}
62+
63+
.Step-dot {
5164
width: 8px;
5265
height: 8px;
66+
background: var(--white);
67+
border: 1px solid var(--brand-1);
5368
border-radius: 50%;
54-
background: var(--brand-3);
5569
}
5670

5771
.Step-line {
5872
position: absolute;
59-
top: 13px;
60-
left: 5px;
61-
bottom: -7px;
62-
width: 2px;
63-
background: var(--brand-3);
73+
top: (@step-icon-width / 2 + 5px + 3px);
74+
left: (@step-icon-width / 2);
75+
bottom: -4px;
76+
width: 1px;
77+
background: var(--brand-1);
78+
opacity: 0.5;
6479
}
6580

6681
.Step-title {
67-
color: var(--gray-2);
82+
display: flex;
83+
align-items: center;
84+
color: var(--gray-1);
85+
font-size: var(--font-size-md);
86+
87+
small {
88+
margin-left: 12px;
89+
color: var(--gray-3);
90+
font-size: var(--font-size-xs);
91+
}
6892
}
6993

7094
.Step-desc {
95+
margin-top: 3px;
7196
color: var(--gray-3);
72-
font-size: @font-size-xs;
97+
font-size: var(--font-size-sm);
7398
}

0 commit comments

Comments
 (0)