Skip to content

Commit 9885da5

Browse files
feat(a11y): add keyboard focus for time and datetime
1 parent 6c73d06 commit 9885da5

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

Diff for: src/time/list-columns.vue

+27
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,17 @@
66
:data-type="col.type"
77
:data-index="i"
88
@click="handleSelect"
9+
@keydown.enter="handleSelect"
910
>
1011
<li
1112
v-for="(item, j) in col.list"
1213
:key="item.value"
14+
:ref="`item-${i}-${j}`"
15+
:tabindex="isDisabledTime(item.value, col.type) ? '-1' : '0'"
1316
:data-index="j"
1417
:class="[`${prefixClass}-time-item`, getClasses(item.value, col.type)]"
18+
@keydown.left.prevent="handleArrowLeft(i, j)"
19+
@keydown.right.prevent="handleArrowRight(i, j)"
1520
>
1621
{{ item.text }}
1722
</li>
@@ -82,6 +87,10 @@ export default {
8287
type: Function,
8388
default: () => [],
8489
},
90+
isDisabledTime: {
91+
type: Function,
92+
default: () => false,
93+
},
8594
hourOptions: Array,
8695
minuteOptions: Array,
8796
secondOptions: Array,
@@ -173,6 +182,24 @@ export default {
173182
return { text, value };
174183
});
175184
},
185+
handleArrowLeft(col, row) {
186+
if (col <= 0) {
187+
return;
188+
}
189+
const ref = this.$refs[`item-${col - 1}-${row}`]?.[0];
190+
if (ref) {
191+
ref.focus();
192+
}
193+
},
194+
handleArrowRight(col, row) {
195+
if (col >= 2) {
196+
return;
197+
}
198+
const ref = this.$refs[`item-${col + 1}-${row}`]?.[0];
199+
if (ref) {
200+
ref.focus();
201+
}
202+
},
176203
scrollToSelected(duration) {
177204
const elements = this.$el.querySelectorAll('.active');
178205
for (let i = 0; i < elements.length; i++) {

Diff for: src/time/list-options.vue

+6
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
<div
44
v-for="item in list"
55
:key="item.value"
6+
:tabindex="isDisabled(item.value) ? '-1' : '0'"
67
:class="[`${prefixClass}-time-option`, getClasses(item.value)]"
78
@click="handleSelect(item.value)"
9+
@keydown.enter="handleSelect(item.value)"
810
>
911
{{ item.text }}
1012
</div>
@@ -63,6 +65,10 @@ export default {
6365
type: Function,
6466
default: () => [],
6567
},
68+
isDisabled: {
69+
type: Function,
70+
default: () => false,
71+
},
6672
},
6773
computed: {
6874
list() {

Diff for: src/time/time-panel.vue

+11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<div :class="`${prefixClass}-time`">
33
<div v-if="showTimeHeader" :class="`${prefixClass}-time-header`">
44
<button
5+
ref="dateButton"
56
type="button"
67
:class="`${prefixClass}-btn ${prefixClass}-btn-text ${prefixClass}-time-header-title`"
78
@click="handleClickTitle"
@@ -14,13 +15,15 @@
1415
v-if="timePickerOptions"
1516
:date="innerValue"
1617
:get-classes="getClasses"
18+
:is-disabled="isDisabled"
1719
:options="timePickerOptions"
1820
:format="innerForamt"
1921
@select="handleSelect"
2022
></list-options>
2123
<list-columns
2224
v-else
2325
:date="innerValue"
26+
:is-disabled-time="isDisabled"
2427
:get-classes="getClasses"
2528
:hour-options="hourOptions"
2629
:minute-options="minuteOptions"
@@ -157,6 +160,14 @@ export default {
157160
},
158161
},
159162
},
163+
mounted() {
164+
const ref = this.$refs.dateButton;
165+
if (ref) {
166+
setTimeout(() => {
167+
ref.focus();
168+
}, 300);
169+
}
170+
},
160171
methods: {
161172
formatDate(date, fmt) {
162173
return format(date, fmt, { locale: this.getLocale().formatLocale });

0 commit comments

Comments
 (0)