Skip to content

Commit 9948cb1

Browse files
committed
add focus loop to tag dropdown to improve focus management
1 parent 3026edd commit 9948cb1

File tree

1 file changed

+38
-33
lines changed

1 file changed

+38
-33
lines changed

resources/js/packages/ui/src/Tag/TagDropdown.vue

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import TagCreateModal from '@/packages/ui/src/Tag/TagCreateModal.vue';
66
import MultiselectDropdownItem from '@/packages/ui/src/Input/MultiselectDropdownItem.vue';
77
import type { Tag } from '@/packages/api/src';
88
import type { Placement } from '@floating-ui/vue';
9+
import {UseFocusTrap} from "@vueuse/integrations/useFocusTrap/component";
910
1011
const props = withDefaults(
1112
defineProps<{
@@ -177,46 +178,50 @@ const showCreateTagModal = ref(false);
177178
<slot name="trigger"></slot>
178179
</template>
179180
<template #content>
180-
<input
181-
ref="searchInput"
182-
:value="searchValue"
183-
data-testid="tag_dropdown_search"
184-
class="bg-card-background border-0 placeholder-muted text-sm text-white py-2.5 focus:ring-0 border-b border-card-background-separator focus:border-card-background-separator w-full"
185-
placeholder="Search for a Tag..."
186-
@input="updateSearchValue"
187-
@keydown.enter="addTagIfNoneExists"
188-
@keydown.up.prevent="moveHighlightUp"
189-
@keydown.down.prevent="moveHighlightDown" />
190-
<div ref="dropdownViewport" class="w-60 max-h-60 overflow-y-scroll">
191-
<div
192-
v-for="tag in filteredTags"
193-
:key="tag.id"
194-
role="option"
195-
:value="tag.id"
196-
:class="{
181+
<UseFocusTrap
182+
v-if="open"
183+
:options="{ immediate: true, allowOutsideClick: true }">
184+
<input
185+
ref="searchInput"
186+
:value="searchValue"
187+
data-testid="tag_dropdown_search"
188+
class="bg-card-background border-0 placeholder-muted text-sm text-white py-2.5 focus:ring-0 border-b border-card-background-separator focus:border-card-background-separator w-full"
189+
placeholder="Search for a Tag..."
190+
@input="updateSearchValue"
191+
@keydown.enter="addTagIfNoneExists"
192+
@keydown.up.prevent="moveHighlightUp"
193+
@keydown.down.prevent="moveHighlightDown" />
194+
<div ref="dropdownViewport" class="w-60 max-h-60 overflow-y-scroll">
195+
<div
196+
v-for="tag in filteredTags"
197+
:key="tag.id"
198+
role="option"
199+
:value="tag.id"
200+
:class="{
197201
'bg-card-background-active':
198202
tag.id === highlightedItemId,
199203
}"
200-
data-testid="tag_dropdown_entries"
201-
:data-tag-id="tag.id">
202-
<MultiselectDropdownItem
203-
:selected="isTagSelected(tag.id)"
204-
:name="tag.name"
205-
@click="toggleTag(tag.id)"></MultiselectDropdownItem>
204+
data-testid="tag_dropdown_entries"
205+
:data-tag-id="tag.id">
206+
<MultiselectDropdownItem
207+
:selected="isTagSelected(tag.id)"
208+
:name="tag.name"
209+
@click="toggleTag(tag.id)"></MultiselectDropdownItem>
210+
</div>
206211
</div>
207-
</div>
208-
<div class="hover:bg-card-background-active rounded-b-lg">
209-
<button
210-
class="text-white w-full flex space-x-3 items-center px-4 py-3 text-xs font-semibold border-t border-card-background-separator"
211-
@click="
212+
<div class="hover:bg-card-background-active rounded-b-lg">
213+
<button
214+
class="text-white w-full flex space-x-3 items-center px-4 py-3 text-xs font-semibold border-t border-card-background-separator"
215+
@click="
212216
open = false;
213217
showCreateTagModal = true;
214218
">
215-
<PlusCircleIcon
216-
class="w-5 flex-shrink-0 text-icon-default"></PlusCircleIcon>
217-
<span>Create new Tag</span>
218-
</button>
219-
</div>
219+
<PlusCircleIcon
220+
class="w-5 flex-shrink-0 text-icon-default"></PlusCircleIcon>
221+
<span>Create new Tag</span>
222+
</button>
223+
</div>
224+
</UseFocusTrap>
220225
</template>
221226
</Dropdown>
222227
</template>

0 commit comments

Comments
 (0)