Skip to content
This repository has been archived by the owner on Jan 8, 2025. It is now read-only.

Commit

Permalink
feat(ui/steps): add component steps
Browse files Browse the repository at this point in the history
  • Loading branch information
leno23 committed Feb 24, 2022
1 parent e9b4e0c commit 88b440c
Show file tree
Hide file tree
Showing 20 changed files with 1,061 additions and 0 deletions.
99 changes: 99 additions & 0 deletions packages/varlet-vue2-ui/src/step/Step.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<template>
<div class="var-step">
<div :class="`var-step-${direction}`">
<div :class="`var-step-${direction}__main`" ref="main">
<div
:class="{
[`var-step-${direction}__tag`]: true,
[`var-step-${direction}__tag--active`]: isActive || isCurrent,
}"
:style="{ backgroundColor: isActive || isCurrent ? activeColor : inactiveColor }"
@click="click"
>
<var-icon class="var-step__icon" var-step-cover :name="activeIcon" v-if="isActive" />
<var-icon class="var-step__icon" var-step-cover :name="currentIcon" v-else-if="isCurrent && currentIcon" />
<var-icon class="var-step__icon" var-step-cover :name="inactiveIcon" v-else-if="inactiveIcon" />
<span v-else>{{ index + 1 }}</span>
</div>
<div
:class="{
[`var-step-${direction}__content`]: true,
[`var-step-${direction}__content--active`]: isActive || isCurrent,
}"
@click="click"
>
<slot />
</div>
</div>
<div :class="`var-step-${direction}__line`" v-if="!isLastChild" :style="{ margin: lineMargin }"></div>
</div>
</div>
</template>

<script>
import { props } from './props'
import { defineComponent } from '../utils/create'
import VarIcon from '../icon'
import { createChildrenMixin } from '../utils/mixins/relation'
export default defineComponent({
name: 'VarStep',
components: {
VarIcon,
},
mixins: [createChildrenMixin('steps', { childrenKey: 'step' })],
data: () => ({
lineMargin: '',
isLastChild: false,
}),
props,
computed: {
index() {
return this.steps.step.indexOf(this)
},
isCurrent({ active, index }) {
return active === index
},
active() {
return this.steps.active
},
isActive({ index, active }) {
return index !== -1 && active > index
},
length() {
return this.steps.step.length
},
activeColor() {
return this.steps.activeColor
},
inactiveColor() {
return this.steps.inactiveColor
},
direction() {
return this.steps.direction
},
},
watch: {
length() {
const { newLength, index } = this
this.isLastChild = newLength - 1 === index
const main = this.$refs.main
if (main) {
const margin = main.offsetWidth / 2 - 14
this.lineMargin = `0 -${margin}px`
}
},
},
methods: {
click() {
this.steps.getListeners().onClickStep?.(this.index)
},
},
})
</script>
<style lang="less">
@import '../styles/common';
@import '../icon/icon';
@import './step';
</style>
15 changes: 15 additions & 0 deletions packages/varlet-vue2-ui/src/step/docs/zh-CN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## API

### 属性

| 参数 | 说明 | 类型 | 默认值 |
| ----- | -------------- | -------- | ---------- |
| `active-icon` | 激活状态图标 | _string_ | `check` |
| `current-icon` | 当前步骤时的图标 | _string_ | - |
| `inactive-icon` | 未激活状态图标 | _string_ | - |

### 插槽

| 名称 | 说明 | 参数 |
| ----- | -------------- | -------- |
| `default` | step 的内容 | - |
10 changes: 10 additions & 0 deletions packages/varlet-vue2-ui/src/step/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { App } from 'vue'
import Step from './Step.vue'

Step.install = function (app: App) {
app.component(Step.name, Step)
}

export const _StepComponent = Step

export default Step
12 changes: 12 additions & 0 deletions packages/varlet-vue2-ui/src/step/props.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export const props = {
activeIcon: {
type: String,
default: 'check',
},
currentIcon: {
type: String,
},
inactiveIcon: {
type: String,
},
}
145 changes: 145 additions & 0 deletions packages/varlet-vue2-ui/src/step/step.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
@step-tag-size: 20px;
@step-tag-background: #9e9e9e;
@step-tag-font-size: var(--font-size-md);
@step-tag-color: #fff;
@step-tag-active-color: var(--color-primary);
@step-tag-margin: 4px 0;
@step-tag-icon-size: var(--font-size-lg);
@step-content-font-size: var(--font-size-md);
@step-content-color: rgba(0, 0, 0, 0.38);
@step-content-active-color: #000;
@step-line-background: #000;
@step-vertical-min-height: 30px;
@step-vertical-tag-margin: 0 4px;
@step-vertical-line-height: calc(100% - 30px);
@step-vertical-line-min-height: 20px;

:root {
--step-tag-size: @step-tag-size;
--step-tag-background: @step-tag-background;
--step-tag-font-size: @step-tag-font-size;
--step-tag-color: @step-tag-color;
--step-tag-active-color: @step-tag-active-color;
--step-tag-margin: @step-tag-margin;
--step-tag-icon-size: @step-tag-icon-size;
--step-content-font-size: @step-content-font-size;
--step-content-color: @step-content-color;
--step-content-active-color: @step-content-active-color;
--step-line-background: @step-line-background;
--step-vertical-min-height: @step-vertical-min-height;
--step-vertical-tag-margin: @step-vertical-tag-margin;
--step-vertical-line-height: @step-vertical-line-height;
--step-vertical-line-min-height: @step-vertical-line-min-height;
}

// Mixins
.tag {
width: var(--step-tag-size);
height: var(--step-tag-size);
background: var(--step-tag-background);
display: flex;
font-size: var(--step-tag-font-size);
align-items: center;
justify-content: center;
border-radius: 50%;
color: var(--step-tag-color);
cursor: pointer;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
transition: 0.3s var(--cubic-bezier);
}

// Mixins
.content {
font-size: var(--step-content-font-size);
color: var(--step-content-color);
cursor: pointer;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
transition: 0.3s var(--cubic-bezier);
}

.var-step {
display: flex;
position: relative;
flex: 1;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);

&-horizontal {
display: flex;
width: 100%;

&__main {
display: flex;
flex-direction: column;
align-items: center;
flex-basis: 100%;
}

&__tag {
margin: var(--step-tag-margin);
.tag();

&--active {
background: var(--step-tag-active-color);
}
}

&__content {
.content();

&--active {
color: var(--step-content-active-color);
}
}

&__line {
position: relative;
top: 14px;
flex: 1;
height: 1px;
transform: scaleY(0.5);
background: var(--step-line-background);
}
}

&-vertical {
width: 100%;

&__main {
display: flex;
align-items: flex-start;
min-height: var(--step-vertical-min-height);
}

&__tag {
margin: var(--step-vertical-tag-margin);
.tag();

&--active {
background: var(--step-tag-active-color);
}
}

&__content {
.content();

&--active {
color: var(--step-content-active-color);
}
}

&__line {
position: relative;
height: var(--step-vertical-line-height);
left: 14px;
top: calc(-100% + 45px);
min-height: var(--step-vertical-line-min-height);
width: 1px;
transform: scaleX(0.5);
background: var(--step-line-background);
}
}

&__icon[var-step-cover] {
font-size: var(--step-tag-icon-size);
}
}
27 changes: 27 additions & 0 deletions packages/varlet-vue2-ui/src/steps/Steps.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<template>
<div class="var-steps" :style="{ flexDirection: direction === 'horizontal' ? 'row' : 'column' }">
<slot />
</div>
</template>

<script>
import { defineComponent } from '../utils/create'
import { props } from './props'
import { createParentMixin } from '../utils/mixins/relation'
export default defineComponent({
name: 'VarSteps',
props,
mixins: [createParentMixin('steps', { childrenKey: 'step' })],
})
</script>

<style lang="less">
@import '../styles/common';
.var-steps {
display: flex;
justify-content: space-between;
overflow: hidden;
}
</style>
Loading

0 comments on commit 88b440c

Please sign in to comment.