|
1 | 1 | <template> |
2 | | - <div class="vue-form-wizard" :class="stepSize"> |
| 2 | + <div class="vue-form-wizard" :class="stepSize" @keyup.right="focusNextTab" @keyup.left="focusPrevTab"> |
3 | 3 | <div class="wizard-header"> |
4 | 4 | <slot name="title"> |
5 | 5 | <h4 class="wizard-title">{{title}}</h4> |
|
11 | 11 | <div class="wizard-progress-bar" |
12 | 12 | :style="progressBarStyle"></div> |
13 | 13 | </div> |
14 | | - <ul class="wizard-nav wizard-nav-pills"> |
| 14 | + <ul class="wizard-nav wizard-nav-pills" role="tablist"> |
15 | 15 | <slot name="step" v-for="(tab, index) in tabs" |
16 | 16 | :tab="tab" |
17 | 17 | :index="index" |
|
21 | 21 | <wizard-step :tab="tab" |
22 | 22 | :step-size="stepSize" |
23 | 23 | @click.native="navigateToTab(index)" |
| 24 | + @keyup.enter.native="navigateOrGoToNext(index)" |
24 | 25 | :transition="transition" |
25 | 26 | :index="index"> |
26 | 27 | </wizard-step> |
|
36 | 37 | <slot name="footer" |
37 | 38 | v-bind="slotProps"> |
38 | 39 | <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"> |
40 | 41 | <slot name="prev" v-bind="slotProps"> |
41 | 42 | <wizard-button :style="fillButtonStyle" |
42 | 43 | :disabled="loading"> |
|
49 | 50 |
|
50 | 51 | <div class="wizard-footer-right"> |
51 | 52 | <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"> |
53 | 54 | <slot name="finish" v-bind="slotProps"> |
54 | 55 | <wizard-button :style="fillButtonStyle"> |
55 | 56 | {{finishButtonText}} |
56 | 57 | </wizard-button> |
57 | 58 | </slot> |
58 | 59 | </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" > |
61 | 62 | <wizard-button :style="fillButtonStyle" |
62 | 63 | :disabled="loading"> |
63 | 64 | {{nextButtonText}} |
|
209 | 210 | }, |
210 | 211 | addTab (item) { |
211 | 212 | const index = this.$slots.default.indexOf(item.$vnode) |
| 213 | + item.tabId = `t-${item.title}${index}` |
212 | 214 | this.tabs.splice(index, 0, item) |
213 | 215 | // if a step is added before the current one, go to it |
214 | 216 | if (index < this.activeTabIndex + 1) { |
|
252 | 254 | cb() |
253 | 255 | } |
254 | 256 | } |
| 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 | + } |
255 | 265 | }, |
256 | 266 | nextTab () { |
257 | 267 | let cb = () => { |
|
264 | 274 | } |
265 | 275 | this.beforeTabChange(this.activeTabIndex, cb) |
266 | 276 | }, |
| 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 | + }, |
267 | 298 | prevTab () { |
268 | 299 | let cb = () => { |
269 | 300 | if (this.activeTabIndex > 0) { |
|
0 commit comments