mirror of
https://github.com/tenrok/vue-form-wizard.git
synced 2026-06-24 12:40:32 +03:00
#46 WAI-ARIA Add keyboard support for steps/buttons
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="vue-form-wizard" :class="stepSize">
|
<div class="vue-form-wizard" :class="stepSize" @keyup.right="focusNextTab" @keyup.left="focusPrevTab">
|
||||||
<div class="wizard-header">
|
<div class="wizard-header">
|
||||||
<slot name="title">
|
<slot name="title">
|
||||||
<h4 class="wizard-title">{{title}}</h4>
|
<h4 class="wizard-title">{{title}}</h4>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<div class="wizard-progress-bar"
|
<div class="wizard-progress-bar"
|
||||||
:style="progressBarStyle"></div>
|
:style="progressBarStyle"></div>
|
||||||
</div>
|
</div>
|
||||||
<ul class="wizard-nav wizard-nav-pills">
|
<ul class="wizard-nav wizard-nav-pills" role="tablist">
|
||||||
<slot name="step" v-for="(tab, index) in tabs"
|
<slot name="step" v-for="(tab, index) in tabs"
|
||||||
:tab="tab"
|
:tab="tab"
|
||||||
:index="index"
|
:index="index"
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
<wizard-step :tab="tab"
|
<wizard-step :tab="tab"
|
||||||
:step-size="stepSize"
|
:step-size="stepSize"
|
||||||
@click.native="navigateToTab(index)"
|
@click.native="navigateToTab(index)"
|
||||||
|
@keyup.enter.native="navigateOrGoToNext(index)"
|
||||||
:transition="transition"
|
:transition="transition"
|
||||||
:index="index">
|
:index="index">
|
||||||
</wizard-step>
|
</wizard-step>
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
<slot name="footer"
|
<slot name="footer"
|
||||||
v-bind="slotProps">
|
v-bind="slotProps">
|
||||||
<div class="wizard-footer-left">
|
<div class="wizard-footer-left">
|
||||||
<span @click="prevTab" v-if="displayPrevButton">
|
<span @click="prevTab" @keyup.enter="prevTab" v-if="displayPrevButton" role="button" tabindex="0">
|
||||||
<slot name="prev" v-bind="slotProps">
|
<slot name="prev" v-bind="slotProps">
|
||||||
<wizard-button :style="fillButtonStyle"
|
<wizard-button :style="fillButtonStyle"
|
||||||
:disabled="loading">
|
:disabled="loading">
|
||||||
@@ -49,15 +50,15 @@
|
|||||||
|
|
||||||
<div class="wizard-footer-right">
|
<div class="wizard-footer-right">
|
||||||
<slot name="custom-buttons-right" v-bind="slotProps"></slot>
|
<slot name="custom-buttons-right" v-bind="slotProps"></slot>
|
||||||
<span @click="nextTab" v-if="isLastStep">
|
<span @click="nextTab" @keyup.enter="nextTab" v-if="isLastStep" role="button" tabindex="0">
|
||||||
<slot name="finish" v-bind="slotProps">
|
<slot name="finish" v-bind="slotProps">
|
||||||
<wizard-button :style="fillButtonStyle">
|
<wizard-button :style="fillButtonStyle">
|
||||||
{{finishButtonText}}
|
{{finishButtonText}}
|
||||||
</wizard-button>
|
</wizard-button>
|
||||||
</slot>
|
</slot>
|
||||||
</span>
|
</span>
|
||||||
<span @click="nextTab" v-else>
|
<span @click="nextTab" @keyup.enter="nextTab" role="button" tabindex="0" v-else>
|
||||||
<slot name="next" v-bind="slotProps">
|
<slot name="next" v-bind="slotProps" >
|
||||||
<wizard-button :style="fillButtonStyle"
|
<wizard-button :style="fillButtonStyle"
|
||||||
:disabled="loading">
|
:disabled="loading">
|
||||||
{{nextButtonText}}
|
{{nextButtonText}}
|
||||||
@@ -209,6 +210,7 @@
|
|||||||
},
|
},
|
||||||
addTab (item) {
|
addTab (item) {
|
||||||
const index = this.$slots.default.indexOf(item.$vnode)
|
const index = this.$slots.default.indexOf(item.$vnode)
|
||||||
|
item.tabId = `t-${item.title}${index}`
|
||||||
this.tabs.splice(index, 0, item)
|
this.tabs.splice(index, 0, item)
|
||||||
// if a step is added before the current one, go to it
|
// if a step is added before the current one, go to it
|
||||||
if (index < this.activeTabIndex + 1) {
|
if (index < this.activeTabIndex + 1) {
|
||||||
@@ -252,6 +254,14 @@
|
|||||||
cb()
|
cb()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return index <= this.maxStep
|
||||||
|
},
|
||||||
|
navigateOrGoToNext (index) {
|
||||||
|
if (!this.navigateToTab(index)) {
|
||||||
|
for (let i = this.activeTabIndex; i < index; i++) {
|
||||||
|
this.nextTab()
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
nextTab () {
|
nextTab () {
|
||||||
let cb = () => {
|
let cb = () => {
|
||||||
@@ -264,6 +274,27 @@
|
|||||||
}
|
}
|
||||||
this.beforeTabChange(this.activeTabIndex, cb)
|
this.beforeTabChange(this.activeTabIndex, cb)
|
||||||
},
|
},
|
||||||
|
getActiveElementId () {
|
||||||
|
return document.activeElement.id
|
||||||
|
},
|
||||||
|
focusNextTab () {
|
||||||
|
let activeId = this.getActiveElementId()
|
||||||
|
let tabIndex = this.tabs.findIndex(tab => tab.tabId === activeId)
|
||||||
|
if (tabIndex !== -1 && tabIndex < this.tabs.length - 1) {
|
||||||
|
let toFocus = this.tabs[tabIndex + 1].tabId
|
||||||
|
let elem = document.getElementById(toFocus)
|
||||||
|
elem.focus()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
focusPrevTab () {
|
||||||
|
let activeId = this.getActiveElementId()
|
||||||
|
let tabIndex = this.tabs.findIndex(tab => tab.tabId === activeId)
|
||||||
|
if (tabIndex !== -1 && tabIndex > 0) {
|
||||||
|
let toFocus = this.tabs[tabIndex - 1].tabId
|
||||||
|
let elem = document.getElementById(toFocus)
|
||||||
|
elem.focus()
|
||||||
|
}
|
||||||
|
},
|
||||||
prevTab () {
|
prevTab () {
|
||||||
let cb = () => {
|
let cb = () => {
|
||||||
if (this.activeTabIndex > 0) {
|
if (this.activeTabIndex > 0) {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<div v-show="active" class="wizard-tab-container">
|
<div v-show="active" class="wizard-tab-container"
|
||||||
|
role="tabpanel"
|
||||||
|
:id="title"
|
||||||
|
:aria-hidden="!active"
|
||||||
|
:aria-labelledby="title">
|
||||||
<slot :active="active">
|
<slot :active="active">
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<button type="button" class="wizard-btn btn-fill wizard-btn-wd">
|
<button class="wizard-btn btn-fill wizard-btn-wd" tabindex="-1">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</button>
|
</button>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<li :class="{active:tab.active}">
|
<li :class="{active:tab.active}"
|
||||||
|
>
|
||||||
<a>
|
<a>
|
||||||
<div class="wizard-icon-circle md"
|
<div class="wizard-icon-circle md"
|
||||||
|
role="tab"
|
||||||
|
tabindex="0"
|
||||||
|
:id="tab.tabId"
|
||||||
|
:aria-controls="tab.title"
|
||||||
|
:aria-disabled="tab.active"
|
||||||
|
:aria-selected="tab.active"
|
||||||
:class="{checked: tab.checked,square_shape:isStepSquare, tab_shape:isTabShape}"
|
:class="{checked: tab.checked,square_shape:isStepSquare, tab_shape:isTabShape}"
|
||||||
:style="[tab.checked ? stepCheckedStyle : {}, tab.validationError ? errorStyle : {}]">
|
:style="[tab.checked ? stepCheckedStyle : {}, tab.validationError ? errorStyle : {}]">
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user