Skip to content
This repository has been archived by the owner on Mar 17, 2021. It is now read-only.

Commit

Permalink
Added stepper component
Browse files Browse the repository at this point in the history
  • Loading branch information
romanslonov committed Apr 2, 2019
1 parent c9e9d53 commit 37bbbaf
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ module.exports = {
'components/radio',
'components/radio-group',
'components/spinner',
'components/stepper',
'components/tabs',
'components/textbox',
'components/toggle',
Expand Down
50 changes: 50 additions & 0 deletions docs/components/stepper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Stepper <badge text="development" type="warn" />
The stepper component displays progress through numbered steps.

## Example
<div class="p-3 pb-5 border rounded-2 my-3 flex">
<v-stepper v-model="step" :steps="steps" />
</div>

```html
<v-stepper v-model="step" :steps="steps" />
```

```javascript
export default {
data() {
return {
step: 1,
steps: [
{ id: 1, title: 'First' },
{ id: 2, title: 'Second' },
{ id: 3, title: 'Third' },
],
};
},
};
```

## Props
Name | Type | Description | Default | Required
---------- | -------- | ----------- | --------| --------
steps | Array | List of steps | None | true
value, v-model | Number | The model that the stepper value syncs to. Can be set initially as a default value. | 1 | false
manual | Boolean | If set true then you should manually change steps | false | false
hideLabel | Boolean | Hide labels for steps | false | false
disablePrev | Boolean | Disabled step back option | false | false

<script>
export default {
data() {
return {
step: 1,
steps: [
{ id: 1, title: 'First', label: true },
{ id: 2, title: 'Second' },
{ id: 3, title: 'Third' },
],
};
},
};
</script>
2 changes: 1 addition & 1 deletion docs/components/toggle.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Toggle
# Toggle <badge text="stable" />

## Example
<div class="p-3 border rounded-2 my-3 flex flex-column">
Expand Down
8 changes: 8 additions & 0 deletions src/components/Stepper/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import Stepper from './main.vue';

// eslint-disable-next-line func-names
Stepper.install = function (Vue) {
Vue.component('VStepper', Stepper);
};

export default Stepper;
108 changes: 108 additions & 0 deletions src/components/Stepper/main.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<template>
<div class="stepper">
<ol class="stepper__list">
<v-step
:key="step.id"
v-for="step in steps"
:id="step.id"
:title="step.title"
:hideLabel="hideLabel"
@click="onClick(step.id)"
></v-step>
</ol>
<div
role="progressbar"
class="stepper__bar"
aria-valuemin="0"
aria-valuemax="100"
:aria-valuenow="currentProgress"
>
<span class="stepper__bar-value" :style="{ width: currentProgress }"></span>
</div>
</div>
</template>

<script>
import VStep from './step.vue';
export default {
name: 'VStepper',
props: {
steps: {
type: Array,
required: true,
},
value: {
type: Number,
default: 1,
},
manual: {
type: Boolean,
default: false,
},
disablePrev: {
type: Boolean,
default: false,
},
hideLabel: {
type: Boolean,
default: false,
},
},
data() {
return {
currentStep: this.value,
};
},
mounted() {
this.onChange(this.currentStep);
},
computed: {
progressRange() {
return this.steps.length - 1;
},
progressForEachItem() {
return 100 / this.progressRange;
},
currentProgress() {
const initialProgress = 0;
const progress = (initialProgress + this.progressForEachItem) * (this.currentStep - 1);
return `${progress}%`;
},
},
methods: {
setStep(step) {
this.onChange(step);
},
nextStep() {
const limit = this.steps.length - 1;
if (this.currentStep <= limit) {
this.onChange(this.currentStep + 1);
}
},
prevStep() {
const limit = this.steps[0].id;
if (this.currentStep > limit && !this.disablePrev) {
this.onChange(this.currentStep - 1);
}
},
onChange(id) {
if (id < this.currentStep && this.disablePrev) return;
this.currentStep = id;
this.$emit('change', id);
this.$emit('input', id);
},
onClick(id) {
if (this.manual) return;
this.onChange(id);
},
},
watch: {
value(newVal) {
this.currentStep = newVal;
},
},
components: { VStep },
};
</script>
56 changes: 56 additions & 0 deletions src/components/Stepper/step.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<li
@click="onClick"
class="step"
:class="classes"
>
<button class="step__marker">
<span class="step__label" v-if="!hideLabel">{{ title }}</span>
</button>
</li>
</template>

<script>
export default {
name: 'VStep',
props: {
id: {
type: Number,
required: true,
},
title: {
type: String,
required: true,
},
hideLabel: {
type: Boolean,
default: false,
},
},
data() {
return {};
},
computed: {
isActive() {
return this.$parent.currentStep === this.id;
},
isPrevious() {
return this.$parent.currentStep > this.id;
},
isNext() {
return this.$parent.currentStep < this.id;
},
classes() {
return [
{ 'step--completed': this.isPrevious || this.isActive },
{ 'step--active': this.isActive },
];
},
},
methods: {
onClick() {
this.$emit('click');
},
},
};
</script>
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export { default as VProgress } from './Progress';
export { default as VRadio } from './Radio';
export { default as VRadioGroup } from './RadioGroup';
export { default as VSpinner } from './Spinner';
export { default as VStepper } from './Stepper';
export { default as VTab } from './Tab';
export { default as VTabs } from './Tabs';
export { default as VTextbox } from './Textbox';
Expand Down

0 comments on commit 37bbbaf

Please sign in to comment.