Skip to content

Commit 47bc71d

Browse files
committed
feat(datepicker): Update tabbable cell on focus change
1 parent 26d29ee commit 47bc71d

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

src/components/Datepicker.vue

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,15 @@ export default {
490490
491491
this.isRevertingToOpenDate = false
492492
},
493+
/**
494+
* Returns true if element has the given className
495+
* @param {HTMLElement} element
496+
* @param {String} className
497+
* @returns {Boolean}
498+
*/
499+
hasClass(element, className) {
500+
return element && element.className.split(' ').includes(className)
501+
},
493502
/**
494503
* Initiate the component
495504
*/

src/mixins/navMixin.vue

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default {
99
},
1010
navElements: [],
1111
navElementsFocusedIndex: 0,
12+
resetTabbableCell: false,
1213
tabbableCell: null,
1314
}
1415
},
@@ -39,6 +40,19 @@ export default {
3940
}
4041
}
4142
},
43+
/**
44+
* Returns the currently focused cell element, if there is one...
45+
*/
46+
getActiveCell() {
47+
const isActiveElementACell = this.hasClass(document.activeElement, 'cell')
48+
const isOnSameView = this.hasClass(document.activeElement, this.view)
49+
50+
if (isActiveElementACell && isOnSameView && !this.resetTabbableCell) {
51+
return document.activeElement
52+
}
53+
54+
return null
55+
},
4256
/**
4357
* Returns true if the calendar has been passed the given slot
4458
* @param {String} slotName The name of the slot
@@ -162,13 +176,17 @@ export default {
162176
return
163177
}
164178
179+
this.tabbableCell = null
180+
this.resetTabbableCell = true
181+
165182
this.$nextTick(() => {
166-
this.setTabbableCell()
167183
this.setNavElements()
168184
169185
setTimeout(() => {
170186
this.applyFocus()
171187
}, this.focus.delay)
188+
189+
this.resetTabbableCell = false
172190
})
173191
},
174192
/**
@@ -191,6 +209,8 @@ export default {
191209
setNavElements() {
192210
if (!this.view) return
193211
212+
this.updateTabbableCell()
213+
194214
const view = this.ucFirst(this.view)
195215
196216
this.navElements = [
@@ -230,6 +250,7 @@ export default {
230250
const pickerCells = this.$refs.picker.$refs.cells.$el
231251
232252
this.tabbableCell =
253+
this.getActiveCell() ||
233254
pickerCells.querySelector('button.selected:not(.muted):enabled') ||
234255
pickerCells.querySelector('button.open:not(.muted):enabled') ||
235256
pickerCells.querySelector('button.today:not(.muted):enabled') ||
@@ -276,6 +297,17 @@ export default {
276297
this.tabForwards()
277298
}
278299
},
300+
/**
301+
* Update which cell in the picker should be focus-trapped
302+
*/
303+
updateTabbableCell() {
304+
const isActiveElementACell = this.hasClass(document.activeElement, 'cell')
305+
const needToUpdate = !this.tabbableCell || isActiveElementACell
306+
307+
if (needToUpdate) {
308+
this.setTabbableCell()
309+
}
310+
},
279311
},
280312
}
281313
</script>

0 commit comments

Comments
 (0)