Skip to content
This repository was archived by the owner on Jun 1, 2023. It is now read-only.

Commit e38b125

Browse files
committed
#46 WAI-ARIA Add keyboard support for steps/buttons
1 parent 3783aed commit e38b125

File tree

4 files changed

+51
-9
lines changed

4 files changed

+51
-9
lines changed

src/components/FormWizard.vue

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="vue-form-wizard" :class="stepSize">
2+
<div class="vue-form-wizard" :class="stepSize" @keyup.right="focusNextTab" @keyup.left="focusPrevTab">
33
<div class="wizard-header">
44
<slot name="title">
55
<h4 class="wizard-title">{{title}}</h4>
@@ -11,7 +11,7 @@
1111
<div class="wizard-progress-bar"
1212
:style="progressBarStyle"></div>
1313
</div>
14-
<ul class="wizard-nav wizard-nav-pills">
14+
<ul class="wizard-nav wizard-nav-pills" role="tablist">
1515
<slot name="step" v-for="(tab, index) in tabs"
1616
:tab="tab"
1717
:index="index"
@@ -21,6 +21,7 @@
2121
<wizard-step :tab="tab"
2222
:step-size="stepSize"
2323
@click.native="navigateToTab(index)"
24+
@keyup.enter.native="navigateOrGoToNext(index)"
2425
:transition="transition"
2526
:index="index">
2627
</wizard-step>
@@ -36,7 +37,7 @@
3637
<slot name="footer"
3738
v-bind="slotProps">
3839
<div class="wizard-footer-left">
39-
<span @click="prevTab" v-if="displayPrevButton">
40+
<span @click="prevTab" @keyup.enter="prevTab" v-if="displayPrevButton" role="button" tabindex="0">
4041
<slot name="prev" v-bind="slotProps">
4142
<wizard-button :style="fillButtonStyle"
4243
:disabled="loading">
@@ -49,15 +50,15 @@
4950

5051
<div class="wizard-footer-right">
5152
<slot name="custom-buttons-right" v-bind="slotProps"></slot>
52-
<span @click="nextTab" v-if="isLastStep">
53+
<span @click="nextTab" @keyup.enter="nextTab" v-if="isLastStep" role="button" tabindex="0">
5354
<slot name="finish" v-bind="slotProps">
5455
<wizard-button :style="fillButtonStyle">
5556
{{finishButtonText}}
5657
</wizard-button>
5758
</slot>
5859
</span>
59-
<span @click="nextTab" v-else>
60-
<slot name="next" v-bind="slotProps">
60+
<span @click="nextTab" @keyup.enter="nextTab" role="button" tabindex="0" v-else>
61+
<slot name="next" v-bind="slotProps" >
6162
<wizard-button :style="fillButtonStyle"
6263
:disabled="loading">
6364
{{nextButtonText}}
@@ -209,6 +210,7 @@
209210
},
210211
addTab (item) {
211212
const index = this.$slots.default.indexOf(item.$vnode)
213+
item.tabId = `t-${item.title}${index}`
212214
this.tabs.splice(index, 0, item)
213215
// if a step is added before the current one, go to it
214216
if (index < this.activeTabIndex + 1) {
@@ -252,6 +254,14 @@
252254
cb()
253255
}
254256
}
257+
return index <= this.maxStep
258+
},
259+
navigateOrGoToNext (index) {
260+
if (!this.navigateToTab(index)) {
261+
for (let i = this.activeTabIndex; i < index; i++) {
262+
this.nextTab()
263+
}
264+
}
255265
},
256266
nextTab () {
257267
let cb = () => {
@@ -264,6 +274,27 @@
264274
}
265275
this.beforeTabChange(this.activeTabIndex, cb)
266276
},
277+
getActiveElementId () {
278+
return document.activeElement.id
279+
},
280+
focusNextTab () {
281+
let activeId = this.getActiveElementId()
282+
let tabIndex = this.tabs.findIndex(tab => tab.tabId === activeId)
283+
if (tabIndex !== -1 && tabIndex < this.tabs.length - 1) {
284+
let toFocus = this.tabs[tabIndex + 1].tabId
285+
let elem = document.getElementById(toFocus)
286+
elem.focus()
287+
}
288+
},
289+
focusPrevTab () {
290+
let activeId = this.getActiveElementId()
291+
let tabIndex = this.tabs.findIndex(tab => tab.tabId === activeId)
292+
if (tabIndex !== -1 && tabIndex > 0) {
293+
let toFocus = this.tabs[tabIndex - 1].tabId
294+
let elem = document.getElementById(toFocus)
295+
elem.focus()
296+
}
297+
},
267298
prevTab () {
268299
let cb = () => {
269300
if (this.activeTabIndex > 0) {

src/components/TabContent.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
<template>
2-
<div v-show="active" class="wizard-tab-container">
2+
<div v-show="active" class="wizard-tab-container"
3+
role="tabpanel"
4+
:id="title"
5+
:aria-hidden="!active"
6+
:aria-labelledby="title">
37
<slot :active="active">
48
</slot>
59
</div>

src/components/WizardButton.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<button type="button" class="wizard-btn btn-fill wizard-btn-wd">
2+
<button class="wizard-btn btn-fill wizard-btn-wd" tabindex="-1">
33
<slot></slot>
44
</button>
55
</template>

src/components/WizardStep.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
11
<template>
2-
<li :class="{active:tab.active}">
2+
<li :class="{active:tab.active}"
3+
>
34
<a>
45
<div class="wizard-icon-circle md"
6+
role="tab"
7+
tabindex="0"
8+
:id="tab.tabId"
9+
:aria-controls="tab.title"
10+
:aria-disabled="tab.active"
11+
:aria-selected="tab.active"
512
:class="{checked: tab.checked,square_shape:isStepSquare, tab_shape:isTabShape}"
613
:style="[tab.checked ? stepCheckedStyle : {}, tab.validationError ? errorStyle : {}]">
714

0 commit comments

Comments
 (0)