-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d3d9031
commit 9fdb04c
Showing
5 changed files
with
347 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
.van-steps { | ||
overflow: hidden; | ||
background-color: #fff; | ||
background-color: var(--steps-background-color, #fff); | ||
} | ||
.van-steps--horizontal { | ||
padding: 10px; | ||
} | ||
.van-steps--horizontal .van-step__wrapper { | ||
position: relative; | ||
display: flex; | ||
overflow: hidden; | ||
} | ||
.van-steps--vertical { | ||
padding-left: 10px; | ||
} | ||
.van-steps--vertical .van-step__wrapper { | ||
padding: 0 0 0 20px; | ||
} | ||
.van-step { | ||
position: relative; | ||
flex: 1; | ||
font-size: 14px; | ||
font-size: var(--step-font-size, 14px); | ||
color: #969799; | ||
color: var(--step-text-color, #969799); | ||
} | ||
.van-step--finish { | ||
color: #323233; | ||
color: var(--step-finish-text-color, #323233); | ||
} | ||
.van-step__circle { | ||
border-radius: 50%; | ||
width: 5px; | ||
width: var(--step-circle-size, 5px); | ||
height: 5px; | ||
height: var(--step-circle-size, 5px); | ||
background-color: #969799; | ||
background-color: var(--step-circle-color, #969799); | ||
} | ||
.van-step--horizontal { | ||
padding-bottom: 14px; | ||
} | ||
.van-step--horizontal:first-child .van-step__title { | ||
transform: none; | ||
} | ||
.van-step--horizontal:first-child .van-step__circle-container { | ||
padding: 0 8px 0 0; | ||
transform: translate3d(0, 50%, 0); | ||
} | ||
.van-step--horizontal:last-child { | ||
position: absolute; | ||
right: 0; | ||
width: auto; | ||
} | ||
.van-step--horizontal:last-child .van-step__title { | ||
text-align: right; | ||
transform: none; | ||
} | ||
.van-step--horizontal:last-child .van-step__circle-container { | ||
right: 0; | ||
padding: 0 0 0 8px; | ||
transform: translate3d(0, 50%, 0); | ||
} | ||
.van-step--horizontal .van-step__circle-container { | ||
position: absolute; | ||
bottom: 6px; | ||
z-index: 1; | ||
transform: translate3d(-50%, 50%, 0); | ||
background-color: #fff; | ||
background-color: var(--white, #fff); | ||
padding: 0 8px; | ||
padding: 0 var(--padding-xs, 8px); | ||
} | ||
.van-step--horizontal .van-step__title { | ||
display: inline-block; | ||
transform: translate3d(-50%, 0, 0); | ||
font-size: 12px; | ||
font-size: var(--step-horizontal-title-font-size, 12px); | ||
} | ||
.van-step--horizontal .van-step__line { | ||
position: absolute; | ||
right: 0; | ||
bottom: 6px; | ||
left: 0; | ||
height: 1px; | ||
transform: translate3d(0, 50%, 0); | ||
background-color: #ebedf0; | ||
background-color: var(--step-line-color, #ebedf0); | ||
} | ||
.van-step--horizontal.van-step--process { | ||
color: #323233; | ||
color: var(--step-process-text-color, #323233); | ||
} | ||
.van-step--horizontal.van-step--process .van-step__icon { | ||
display: block; | ||
line-height: 1; | ||
font-size: 12px; | ||
font-size: var(--step-icon-size, 12px); | ||
} | ||
.van-step--vertical { | ||
padding: 10px 10px 10px 0; | ||
line-height: 18px; | ||
} | ||
.van-step--vertical::after { | ||
border-bottom-width: 1px; | ||
} | ||
.van-step--vertical:last-child::after { | ||
border-bottom-width: none; | ||
} | ||
.van-step--vertical:first-child::before { | ||
position: absolute; | ||
top: 0; | ||
left: -15px; | ||
z-index: 1; | ||
width: 1px; | ||
height: 20px; | ||
content: ''; | ||
background-color: #fff; | ||
background-color: var(--white, #fff); | ||
} | ||
.van-step--vertical .van-step__icon, | ||
.van-step--vertical .van-step__circle, | ||
.van-step--vertical .van-step__line { | ||
position: absolute; | ||
top: 19px; | ||
left: -14px; | ||
z-index: 2; | ||
transform: translate3d(-50%, -50%, 0); | ||
} | ||
.van-step--vertical .van-step__icon { | ||
line-height: 1; | ||
font-size: 12px; | ||
font-size: var(--step-icon-size, 12px); | ||
} | ||
.van-step--vertical .van-step__line { | ||
z-index: 1; | ||
width: 1px; | ||
height: 100%; | ||
transform: translate3d(-50%, 0, 0); | ||
background-color: #ebedf0; | ||
background-color: var(--step-line-color, #ebedf0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// packages | ||
import React, { FunctionComponent, CSSProperties, ReactElement } from 'react'; | ||
import clsx from 'clsx'; | ||
import { View } from 'remax/wechat'; | ||
// internal | ||
import Icon from '../Icon'; | ||
import withDefaultProps from '../tools/with-default-props-advance'; | ||
import pickStyle from '../tools/pick-style'; | ||
import './Steps.css'; | ||
|
||
interface StepItem { | ||
text: string; | ||
desc: string; | ||
} | ||
|
||
// 默认值填充属性 | ||
interface NeutralStepsProps { | ||
active: number; | ||
direction: 'horizontal' | 'vertical'; | ||
activeColor: string; | ||
inactiveColor: string; | ||
// 自定义图标占位 | ||
renderActiveCircle: (color: string) => ReactElement; | ||
renderInactiveCircel: (color: string) => ReactElement; | ||
} | ||
|
||
interface ExogenousStepsProps { | ||
// 步骤定义 | ||
steps: StepItem[]; | ||
onClickStep?: (event: { detail: number }) => void; | ||
// 容器类名,用以覆盖内部 | ||
className?: string; | ||
} | ||
|
||
type StepsProps = NeutralStepsProps & ExogenousStepsProps; | ||
|
||
const DefaultStepsProps: NeutralStepsProps = { | ||
active: 0, | ||
direction: 'horizontal', | ||
activeColor: '#07c160', | ||
inactiveColor: '#969799', | ||
// 默认渲染逻辑,平行移植 vant-weapp,.van-step__icon | ||
renderActiveCircle: (color) => ( | ||
<Icon name="checked" className="van-step__icon" color={color} /> | ||
), | ||
renderInactiveCircel: (color) => ( | ||
<View | ||
className="van-step__circle" | ||
style={{ | ||
backgroundColor: color, | ||
}} | ||
/> | ||
), | ||
}; | ||
|
||
const Steps: FunctionComponent<StepsProps> = (props) => { | ||
const { | ||
className, | ||
direction, | ||
steps, | ||
active, | ||
activeColor, | ||
inactiveColor, | ||
} = props; | ||
const classnames = { | ||
container: clsx(className, 'van-steps', `van-steps--${direction}`), | ||
}; | ||
const children = steps.map((step, index) => { | ||
const { onClickStep, renderActiveCircle, renderInactiveCircel } = props; | ||
// 派生状态 | ||
const status = | ||
// eslint-disable-next-line no-nested-ternary | ||
index < active ? 'finish' : index === active ? 'process' : 'inactive'; | ||
const styles: Record<'container' | 'title' | 'line', CSSProperties> = { | ||
container: { | ||
color: status === 'inactive' ? inactiveColor : undefined, | ||
}, | ||
title: { | ||
color: status === 'process' ? activeColor : undefined, | ||
}, | ||
line: { | ||
backgroundColor: status === 'finish' ? activeColor : inactiveColor, | ||
}, | ||
}; | ||
const classNameStep = clsx( | ||
'van-step', | ||
'van-hairline', | ||
`van-step--${direction}`, | ||
`van-step--${status}` | ||
); | ||
// 新增 van-step__title-text,van-step__title-desc 便于样式覆盖 | ||
const title = ( | ||
<View className="van-step__title" style={pickStyle(styles.title)}> | ||
<View className="van-step__title-text">{step.text}</View> | ||
<View className="van-step__title-desc">{step.desc}</View> | ||
</View> | ||
); | ||
const currentColor = status === 'inactive' ? inactiveColor : activeColor; | ||
const circle = ( | ||
<View className="van-step__circle-container"> | ||
{index === active | ||
? renderActiveCircle(currentColor) | ||
: renderInactiveCircel(currentColor)} | ||
</View> | ||
); | ||
// 非末尾填充线条 | ||
const line = index !== steps.length - 1 && ( | ||
<View style={pickStyle(styles.line)} className="van-step__line" /> | ||
); | ||
// 事件绑定 | ||
const onClick = () => { | ||
if (typeof onClickStep === 'function') { | ||
onClickStep({ detail: index }); | ||
} | ||
}; | ||
|
||
return ( | ||
/* eslint-disable react/no-array-index-key */ | ||
<View | ||
key={index} | ||
style={pickStyle(styles.container)} | ||
className={classNameStep} | ||
onClick={onClick} | ||
> | ||
{title} | ||
{circle} | ||
{line} | ||
</View> | ||
); | ||
}); | ||
|
||
return ( | ||
<View className={classnames.container}> | ||
<View className="van-step__wrapper">{children}</View> | ||
</View> | ||
); | ||
}; | ||
|
||
export default withDefaultProps<ExogenousStepsProps, NeutralStepsProps>( | ||
DefaultStepsProps | ||
)(Steps); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/** | ||
* @description - nothing but export component | ||
*/ | ||
export { default } from './Steps'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// packages | ||
import React, { useState } from 'react'; | ||
import { View, Text } from 'remax/wechat'; | ||
|
||
// internal | ||
import Steps from '../../../packages/Steps'; | ||
import Icon from '../../../packages/Icon'; | ||
|
||
export default () => { | ||
const [active, setActive] = useState(0); | ||
const steps = [ | ||
{ | ||
text: '步骤一', | ||
desc: '描述信息', | ||
}, | ||
{ | ||
text: '步骤二', | ||
desc: '描述信息', | ||
}, | ||
{ | ||
text: '步骤三', | ||
desc: '描述信息', | ||
}, | ||
{ | ||
text: '步骤四', | ||
desc: '描述信息', | ||
}, | ||
]; | ||
|
||
return ( | ||
<View className="demo-block"> | ||
<Text className="demo-block__title">基础用法</Text> | ||
<View> | ||
<Steps | ||
steps={steps} | ||
active={active} | ||
onClickStep={(event) => setActive(event.detail)} | ||
/> | ||
</View> | ||
<Text className="demo-block__title">竖向步骤条</Text> | ||
<View> | ||
<Steps direction="vertical" steps={steps} active={active} /> | ||
</View> | ||
<Text className="demo-block__title">自定义样式</Text> | ||
<View> | ||
<Steps | ||
steps={steps} | ||
active={active} | ||
activeColor="#ee0a24" | ||
renderActiveCircle={(color) => <Icon name="success" color={color} />} | ||
renderInactiveCircel={(color) => ( | ||
<Icon name="clock-o" color={color} /> | ||
)} | ||
/> | ||
</View> | ||
</View> | ||
); | ||
}; |