2
0
mirror of https://github.com/tenrok/vue-form-wizard.git synced 2026-06-24 15:30:32 +03:00

#46 WAI-ARIA Add keyboard support for steps/buttons

This commit is contained in:
cristijora
2017-09-18 00:11:48 +03:00
parent 3783aed673
commit e38b12502b
4 changed files with 51 additions and 9 deletions
+37 -6
View File
@@ -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) {
+5 -1
View File
@@ -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 -1
View File
@@ -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>
+8 -1
View File
@@ -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 : {}]">