Skip to content

Commit 1391098

Browse files
committed
Add autofocus for filter dropdown
1 parent 52a1639 commit 1391098

File tree

2 files changed

+19
-6
lines changed

2 files changed

+19
-6
lines changed

src/Frontend/src/components/FilterInput.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<script setup lang="ts">
2-
import { computed } from "vue";
2+
import { computed, useTemplateRef } from "vue";
33
import debounce from "lodash/debounce";
44
55
const model = defineModel<string>({ required: true });
@@ -13,15 +13,21 @@ const localInput = computed({
1313
debounceUpdateModel(newValue);
1414
},
1515
});
16-
16+
const textField = useTemplateRef<HTMLInputElement>("textField");
1717
const debounceUpdateModel = debounce((value: string) => {
1818
model.value = value;
1919
}, 600);
20+
21+
defineExpose({ focus });
22+
23+
function focus() {
24+
textField.value?.focus();
25+
}
2026
</script>
2127

2228
<template>
2329
<div role="search" aria-label="filter" class="filter-input">
24-
<input type="search" @focus="() => emit('focus')" @blur="() => emit('blur')" :placeholder="props.placeholder" :aria-label="props.ariaLabel" class="form-control filter-input" v-model="localInput" />
30+
<input ref="textField" type="search" @focus="() => emit('focus')" @blur="() => emit('blur')" :placeholder="props.placeholder" :aria-label="props.ariaLabel" class="form-control filter-input" v-model="localInput" />
2531
</div>
2632
</template>
2733

src/Frontend/src/components/audit/ListFilterSelector.vue

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script setup lang="ts">
22
import FilterInput from "@/components/FilterInput.vue";
3-
import { ref, watch } from "vue";
3+
import { onMounted, ref, useTemplateRef, watch } from "vue";
44
55
const selected = defineModel<string>({ required: true });
66
const props = withDefaults(
@@ -29,17 +29,24 @@ watch([filter, () => props.items], () => {
2929
function setFilter(item: string, isSelected: boolean) {
3030
selected.value = isSelected && props.canClear ? "" : item;
3131
}
32+
const bootstrapDropDown = useTemplateRef<HTMLElement | null>("bootstrapDropDown");
33+
const filterInput = useTemplateRef<{ focus: () => void } | null>("filterInput");
34+
onMounted(() => {
35+
bootstrapDropDown.value?.addEventListener("shown.bs.dropdown", () => {
36+
filterInput.value?.focus();
37+
});
38+
});
3239
</script>
3340

3441
<template>
35-
<div class="dropdown">
42+
<div ref="bootstrapDropDown" class="dropdown">
3643
<button type="button" aria-label="open dropdown menu" class="btn btn-dropdown dropdown-toggle sp-btn-menu" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
3744
<span class="wrap-text">{{ selected || defaultEmptyText }}</span>
3845
</button>
3946
<div class="dropdown-menu wrapper">
4047
<div class="instructions">{{ instructions }}</div>
4148
<div v-if="showFilter" class="filter-input">
42-
<FilterInput v-model="filter" :placeholder="`Filter ${itemName}s`" />
49+
<FilterInput ref="filterInput" v-model="filter" :placeholder="`Filter ${itemName}s`" />
4350
</div>
4451
<div class="items-container">
4552
<div class="item-container" v-if="showClear && selected" @click.prevent="() => setFilter('', true)">

0 commit comments

Comments
 (0)