feat: Steps component
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { createNamespace } from '../utils';
|
||||
import { BORDER } from '../utils/constant';
|
||||
import { ChildrenMixin } from '../mixins/relation';
|
||||
import Icon from '../icon';
|
||||
|
||||
const [createComponent, bem] = createNamespace('step');
|
||||
|
||||
export default createComponent({
|
||||
mixins: [ChildrenMixin('vanSteps')],
|
||||
|
||||
computed: {
|
||||
status() {
|
||||
if (this.index < this.parent.active) {
|
||||
return 'finish';
|
||||
}
|
||||
if (this.index === +this.parent.active) {
|
||||
return 'process';
|
||||
}
|
||||
},
|
||||
|
||||
active() {
|
||||
return this.status === 'process';
|
||||
},
|
||||
|
||||
lineStyle() {
|
||||
if (this.status === 'finish' && this.parent.activeColor) {
|
||||
return {
|
||||
background: this.parent.activeColor,
|
||||
};
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
genCircle() {
|
||||
const { activeIcon, activeColor, inactiveIcon } = this.parent;
|
||||
|
||||
if (this.active) {
|
||||
return this.$slots['active-icon'] ? (
|
||||
this.$slots['active-icon']()
|
||||
) : (
|
||||
<Icon
|
||||
class={bem('icon', 'active')}
|
||||
name={activeIcon}
|
||||
color={activeColor}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (inactiveIcon || this.$slots['inactive-icon']) {
|
||||
return this.$slots['inactive-icon'] ? (
|
||||
this.$slots['inactive-icon']()
|
||||
) : (
|
||||
<Icon class={bem('icon')} name={inactiveIcon} />
|
||||
);
|
||||
}
|
||||
|
||||
return <i class={bem('circle')} style={this.lineStyle} />;
|
||||
},
|
||||
|
||||
onClickStep() {
|
||||
this.parent.$emit('click-step', this.index);
|
||||
},
|
||||
},
|
||||
|
||||
render() {
|
||||
const { status, active } = this;
|
||||
const { activeColor, direction } = this.parent;
|
||||
|
||||
const titleStyle = active && { color: activeColor };
|
||||
|
||||
return (
|
||||
<div class={[BORDER, bem([direction, { [status]: status }])]}>
|
||||
<div
|
||||
class={bem('title', { active })}
|
||||
style={titleStyle}
|
||||
onClick={this.onClickStep}
|
||||
>
|
||||
{this.$slots.default?.()}
|
||||
</div>
|
||||
<div class={bem('circle-container')} onClick={this.onClickStep}>
|
||||
{this.genCircle()}
|
||||
</div>
|
||||
<div class={bem('line')} style={this.lineStyle} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,151 @@
|
||||
@import '../style/var';
|
||||
|
||||
.van-step {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
color: @step-text-color;
|
||||
font-size: @step-font-size;
|
||||
|
||||
&__circle {
|
||||
display: block;
|
||||
width: @step-circle-size;
|
||||
height: @step-circle-size;
|
||||
background-color: @step-circle-color;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&__line {
|
||||
position: absolute;
|
||||
background-color: @step-line-color;
|
||||
transition: background-color @animation-duration-base;
|
||||
}
|
||||
|
||||
&--horizontal {
|
||||
float: left;
|
||||
|
||||
&:first-child {
|
||||
.van-step__title {
|
||||
margin-left: 0;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
width: auto;
|
||||
|
||||
.van-step__title {
|
||||
margin-left: 0;
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.van-step__circle-container {
|
||||
right: -9px;
|
||||
left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.van-step__circle-container {
|
||||
position: absolute;
|
||||
top: 30px;
|
||||
left: -@padding-xs;
|
||||
z-index: 1;
|
||||
padding: 0 @padding-xs;
|
||||
background-color: @white;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.van-step__title {
|
||||
display: inline-block;
|
||||
margin-left: 3px;
|
||||
font-size: @step-horizontal-title-font-size;
|
||||
transform: translateX(-50%);
|
||||
|
||||
@media (max-width: 321px) {
|
||||
font-size: @step-horizontal-title-font-size - 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.van-step__line {
|
||||
top: 30px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
.van-step__icon {
|
||||
display: block;
|
||||
font-size: @step-icon-size;
|
||||
}
|
||||
|
||||
.van-step--process {
|
||||
color: @step-process-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
&--vertical {
|
||||
display: block;
|
||||
float: none;
|
||||
padding: 10px 10px 10px 0;
|
||||
line-height: 18px;
|
||||
|
||||
&:not(:last-child)::after {
|
||||
border-bottom-width: 1px;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
&::before {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -15px;
|
||||
z-index: 1;
|
||||
width: 1px;
|
||||
height: 20px;
|
||||
background-color: @white;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
|
||||
.van-step__circle-container {
|
||||
position: absolute;
|
||||
top: 19px;
|
||||
left: -15px;
|
||||
z-index: 2;
|
||||
font-size: @step-icon-size;
|
||||
line-height: 1;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.van-step__line {
|
||||
top: 16px;
|
||||
left: -15px;
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
.van-step__line {
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&--finish {
|
||||
color: @step-finish-text-color;
|
||||
|
||||
.van-step__circle,
|
||||
.van-step__line {
|
||||
background-color: @step-finish-line-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon,
|
||||
&__title {
|
||||
transition: color @animation-duration-base;
|
||||
|
||||
&--active {
|
||||
color: @step-active-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user