Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Linear stepper and custom step actions #3641

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
569d2c8
Added Linear stepper and custom step actions
Bond-Addict Jul 27, 2023
0b51579
Reverted prettier changes and removed package-lock
Bond-Addict Jul 31, 2023
c05cb2c
Wip for pr comments
Bond-Addict Jul 31, 2023
9b140f8
Passing form to stepper wip
Bond-Addict Jul 31, 2023
3ad5c22
Trying to pass ref as a nested object to protect against unwrapping
Bond-Addict Jul 31, 2023
8a6a272
fix(va-stepper): register va-form component in demos
m0ksem Jul 31, 2023
d2d30c4
fix(va-stepper): memory leak using useForm in methods
m0ksem Jul 31, 2023
3141bac
fix(va-stepper): remove extra FormRef type
m0ksem Jul 31, 2023
99af65a
Working on form ref reactivity
Bond-Addict Jul 31, 2023
c4cfdde
Merge branch 'feat/stepper-with-save-actions-and-linear-mode' of http…
Bond-Addict Jul 31, 2023
167a584
Cleanup
Bond-Addict Jul 31, 2023
27eaca0
Set prop default and add another field to demo
Bond-Addict Aug 1, 2023
389d1a4
Set navigation buttons disabled if invalid
Bond-Addict Aug 1, 2023
6135343
Set invalid color on invalid form
Bond-Addict Aug 1, 2023
543dda4
Package updates
Bond-Addict Aug 1, 2023
f25e1b2
Docs update
Bond-Addict Aug 1, 2023
6df7c59
Changed stepper to not handle validating form. Linear does work as in…
Bond-Addict Aug 1, 2023
166bf1d
Cleanup
Bond-Addict Aug 1, 2023
4225443
Whitespace fixes
Bond-Addict Aug 1, 2023
639f6ac
More whitespace fixes
Bond-Addict Aug 1, 2023
dde399d
More whitespace fixes
Bond-Addict Aug 1, 2023
6fb6258
More whitespace fixes and doc updates
Bond-Addict Aug 1, 2023
5dc0e0b
More whitespace fixes
Bond-Addict Aug 1, 2023
832d4eb
More whitespace fixes
Bond-Addict Aug 1, 2023
42a7c47
More whitespace fixes
Bond-Addict Aug 1, 2023
4569173
More whitespace fixes
Bond-Addict Aug 1, 2023
87f0c4d
Whitespace
Bond-Addict Aug 2, 2023
1e8ed54
Whitespace
Bond-Addict Aug 2, 2023
0ac8d46
Whitespace
Bond-Addict Aug 2, 2023
91f1a70
Whitespace
Bond-Addict Aug 2, 2023
792a742
Whitespace
Bond-Addict Aug 2, 2023
d3ef492
Whitespace
Bond-Addict Aug 2, 2023
cd1fe47
Merge branch 'develop' into pr/Bond-Addict/3641
m0ksem Aug 10, 2023
77c2adb
chore: update yarn lock
m0ksem Aug 10, 2023
08b353c
Suggestions Pt.1
Bond-Addict Aug 10, 2023
c3a9317
Trying to set danger if error exists
Bond-Addict Aug 10, 2023
49fb066
Trying to fix error color. It seems like it should work, but the step…
Bond-Addict Aug 10, 2023
0255991
fix(stepper): fix: refactor stepper validation
m0ksem Aug 11, 2023
160ecbc
feat(stepper): added computed error
m0ksem Aug 11, 2023
9241045
Merge branch 'develop' into pr/Bond-Addict/3641
m0ksem Aug 11, 2023
1376b22
Merge branch 'develop' into pr/Bond-Addict/3641
m0ksem Aug 11, 2023
5d49247
docs(stepper): add linear docs demo
m0ksem Aug 21, 2023
f807217
Merge remote-tracking branch 'upstream/develop' into feat/stepper-wit…
asvae Aug 25, 2023
e8eb928
chore: beforeSave -> beforeLeave
asvae Aug 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export default defineApiDescription({
controlsHidden: "Removes 'Back' and 'Next' buttons.",
vertical: "Changes stepper orientation to vertical.",
finishButtonHidden: "Hides 'Finish' button",
ariaLabel: "The aria-label of the component"
ariaLabel: "The aria-label of the component",
linear: "Requires that each step must be manually marked as complete",
},
events: {
finish: "Emits when 'Finish' button is getting pressed"
Expand Down
5 changes: 4 additions & 1 deletion packages/docs/page-config/ui-elements/stepper/api-options.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
export default defineManualApi({
props: {
steps: { types: '{ label: string, icon?: string, disabled?: boolean }' },
steps: {
types:
'{ label: string, icon?: string, disabled?: boolean, save?: Function, hasError?: boolean, completed?: boolean }',
},
},
slots: {
stepButton: { },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<VaStepper
ref="actionStepper"
v-model="currentStep"
:steps="steps"
>
<template #step-content-0>
<p>Validate on save</p>
<va-input
v-model="model.a"
label="A"
/>
</template>
<template #step-content-1>
<p>Validate on save and disable navigation</p>
<va-input
v-model="model.b"
label="B"
required-mark
/>
</template>
<template #step-content-2>
<p>Validate instantly</p>
<va-input
v-model="model.c"
label="C"
required-mark
/>
</template>
</VaStepper>
</template>

<script setup>
import { ref } from 'vue'
import { defineVaStepperSteps } from 'vuestic-ui'

const currentStep = ref(0)
const model = ref({ a: '', b: '', c: '', d: '' })

const steps = ref(defineVaStepperSteps([
{
label: 'One', beforeLeave: (fromStep, toStep) => {
if (fromStep !== toStep) {
alert('Thanks!')
}
}
},
{
label: 'Two', beforeLeave: (step) => {
step.hasError = model.value.b === ''
return !step.hasError
}
},
{ label: 'Three' },
]))
</script>
69 changes: 69 additions & 0 deletions packages/docs/page-config/ui-elements/stepper/examples/Linear.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<template>
<VaForm ref="stepForm">
<VaStepper
ref="linearStepper"
v-model="currentStep"
:steps="steps"
linear
>
<template #step-content-0>
<va-input
v-model="model.a"
label="A"
:rules="[
(v) => !!v || 'Required',
]"
required-mark
/>
</template>
<template #step-content-1>
<va-input
v-model="model.b"
label="B"
:rules="[
(v) => !!v || 'Required',
]"
required-mark
/>
</template>
<template #step-content-2>
<va-input
v-model="model.c"
label="C"
/>
</template>
<template #step-content-3>
<va-input
v-model="model.d"
label="D"
:rules="[
(v) => !!v || 'Required',
]"
required-mark
/>
</template>
</VaStepper>
</VaForm>
</template>

<script setup>
import { ref } from 'vue';
import { useForm, defineVaStepperSteps } from 'vuestic-ui'

const currentStep = ref(0);
const model = ref({ a: '', b: '', c: '', d: '' })

const { validate } = useForm('stepForm')

const steps = ref(defineVaStepperSteps([
{
label: 'One',
beforeLeave: (step) => {
step.hasError = !validate()
},
},
{ label: 'Two', beforeLeave: (step) => { step.hasError = !validate() } },
{ label: 'Three', beforeLeave: (step) => { step.hasError = !validate() } },
{ label: 'Four', beforeLeave: (step) => { step.hasError = !validate() } },
]))
</script>
16 changes: 13 additions & 3 deletions packages/docs/page-config/ui-elements/stepper/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default definePageConfig({

block.example('Default', { title: "Basic usage" }),

block.example('Vertical', { title: "Vertical" }),
block.example('Vertical', { title: 'Vertical' }),

block.example('Icons', {
title: "Custom icons",
Expand All @@ -19,16 +19,26 @@ export default definePageConfig({

block.example('Custom', { title: "Customized with slots" }),

block.alert('You can iterate through slots using template literals in slot name. \n Example: ``{\'#[`step-button-${i}`]=\"{ setStep, isActive, isCompleted }\"\'}``', 'info'),
block.alert('You can iterate through slots using template literals in slot name. \n Example: ``#[`step-button-${i}`]="{ setStep, isActive, isCompleted }"``', 'info'),

block.example('Minimal', {
title: "Navigation only",
description: "You can hide controls and use stepper navigation independently"
}),

block.example('CustomSave', {
title: 'Custom save action for each step',
description: 'This adds a property of `beforeLeave` that accepts a function. When you click `next` `previous` or click on a navigation item at the top, your function will be called. If `beforeLeave` returns `false` navigation is disabled. You can also set `hasError` using this function.'
}),

block.example('Linear', {
title: 'Linear',
description: 'Prevent navigation to the step if any of previous steps have error. It means that you can\'t go to the next step until you fix the error. You can set `hasError` in `beforeLeave` function.'
}),

block.subtitle('Accessibility'),

block.paragraph('The component itself has a [role=\"group\"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/group_role)[[target=_blank]] with aria attributes like an [aria-orientation](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-orientation)[[target=_blank]] attribute that depends on the `vertical` property. The current step element has the attribute [aria-current=\"step\"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#values)[[target=_blank]]. Keyboard navigation for this component is based on the [w3 tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/)[[target=_blank]].'),
block.paragraph('The component itself has a [role="group"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/group_role)[[target=_blank]] with aria attributes like an [aria-orientation](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-orientation)[[target=_blank]] attribute that depends on the `vertical` property. The current step element has the attribute [aria-current="step"](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-current#values)[[target=_blank]]. Keyboard navigation for this component is based on the [w3 tabs pattern](https://www.w3.org/WAI/ARIA/apg/patterns/tabs/)[[target=_blank]].'),

block.subtitle("API"),
block.api("VaStepper", apiDescription, apiOptions),
Expand Down
1 change: 0 additions & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@
"eslint-plugin-standard": "^5.0.0",
"eslint-plugin-storybook": "^0.6.12",
"eslint-plugin-vue": "^7.0.1",
"friendly-errors-webpack-plugin": "^1.7.0",
"identity-obj-proxy": "^3.0.0",
"ionicons": "^3.0.0",
"jsdom": "^16.2.2",
Expand Down
80 changes: 80 additions & 0 deletions packages/ui/src/components/va-stepper/VaStepper.demo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,14 +62,64 @@
<VbCard title="Finish button hidden">
<VaStepper v-model="step" :steps="steps" finishButtonHidden> </VaStepper>
</VbCard>

<VbCard title="Step validation">
Highlight step is has error
<VaStepper ref="actionStepper" v-model="actionStep" :steps="stepsWithNextAction">
<template #step-content-0>
<va-input v-model="model.a" label="A">
</va-input>
</template>
<template #step-content-1>
<va-input v-model="model.b" label="B"></va-input>
<p>Navigation is enabled, because it is not a linear stepper</p>
<p>Validated after moved to another pages</p>
</template>
<template #step-content-2>
<va-input v-model="model.c" label="C"></va-input>
<p>Navigation is disabled, because beforeLeave explicitly returned false</p>
</template>
<template #step-content-3>
<va-input v-model="model.d" label="D"></va-input>
<p>Validates on rendering</p>
</template>
</VaStepper>
</VbCard>

<VbCard title="Step validation (with linear stepper)">
Highlight step is has error. User is not able to navigate if current step has error. User is not able over jump step if previous step has error or wasn't completed.
<VaStepper ref="linearStepper" v-model="linearStep" :steps="linearSteps" linear>
<template #step-content-0>
<va-input v-model="model.a" label="A"></va-input>
</template>
<template #step-content-1>
<va-input v-model="model.b" label="B"></va-input>
<p>Navigation is disabled if input is empty</p>
</template>
<template #step-content-2>
<va-input v-model="model.c" label="C"></va-input>
</template>
<template #step-content-3>
<va-input v-model="model.d" label="D"></va-input>
</template>
</VaStepper>
</VbCard>
</VbDemo>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { VaStepper } from './index'
import { VaInput } from '../va-input'
import { Step } from './types'

const step = ref(2)
const linearStep = ref()
const actionStep = ref()
const model = ref({ a: '', b: '', c: '', d: '' })
const retryCount = ref(0)
const linearStepper = ref()
const actionStepper = ref()

const steps = [
{ label: 'One' },
Expand All @@ -79,6 +129,29 @@ const steps = [
{ label: 'Five' },
]

const linearSteps = ref([
{
label: 'One',
beforeLeave: (step) => {
if (step.completed) { return }

retryCount.value++

if (retryCount.value < 3) {
alert('Try again. You need to click next ' + (3 - retryCount.value) + ' more times')
return false
}

retryCount.value = 0
return true
},
},
// VaForm can be used here: step.hasError = !form.validate()
{ label: 'Two', beforeLeave: (step) => { step.hasError = model.value.b === '' } },
{ label: 'Three', disabled: true },
{ label: 'Four' },
] as Step[])

const stepsWithDisabled = [
{ label: 'One' },
{ label: 'Two', disabled: true },
Expand All @@ -94,4 +167,11 @@ const stepsWithCustomIcons = [
{ label: 'Four', icon: 'grade' },
{ label: 'Five', icon: 'list' },
]

const stepsWithNextAction = ref([
{ label: 'One' },
{ label: 'Two', beforeLeave: (step) => { step.hasError = true } },
{ label: 'Three', beforeLeave: (step) => model.value.c !== '' },
{ label: 'Four', hasError: (step) => model.value.d === '' },
] as Step[])
</script>
Loading