refactor(ui): unify confirm-dropdown Enter behavior via useAcceptOnEnter
CI / lint (push) Successful in 2s
CI / backend-lint-and-test (push) Successful in 27s
CI / frontend-build (push) Successful in 1m44s
CI / integration (push) Successful in 3m8s

Operator-flagged (again) on the tag-merge picker: Enter on the dropdown re-opens
it instead of accepting the selection. I'd already patched this twice (fandom
picker + fandom set dialog) with copy-pasted capture-phase handlers, so DRY it.

New composable useAcceptOnEnter(accept): tracks the menu state and, on a
capture-phase Enter, lets Vuetify pick when the menu is open but calls accept()
(and blocks the re-open) when it's closed. Applied to every confirm-style picker:
- TagsView merge-into picker (the reported one)
- AliasPickerDialog
- PostSeriesMenu add-to-existing
- FandomPicker + FandomSetDialog (refactored off their bespoke handlers)

One behavior, one place to change it.
This commit is contained in:
2026-06-08 08:59:55 -04:00
parent f2fbe2ae6e
commit 408fcd488a
6 changed files with 71 additions and 33 deletions
@@ -32,11 +32,13 @@
</p>
<v-autocomplete
v-model="picked"
v-model:menu="pickerMenuOpen"
:items="hits"
:item-title="(s) => s.name"
:item-value="(s) => s.id"
:loading="searching"
label="Series" density="compact" autofocus clearable
@keydown.enter.capture="onEnter"
/>
</v-card-text>
<v-card-actions>
@@ -56,6 +58,7 @@
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useApi } from '../../composables/useApi.js'
import { useAcceptOnEnter } from '../../composables/useAcceptOnEnter.js'
import { toast } from '../../utils/toast.js'
const props = defineProps({ post: { type: Object, required: true } })
@@ -70,6 +73,12 @@ const picked = ref(null)
const hits = ref([])
const searching = ref(false)
// Enter on the closed dropdown adds the chosen series instead of re-opening it.
// (aliased — `menuOpen` above is the outer "Series " v-menu's state.)
const { menuOpen: pickerMenuOpen, onEnter } = useAcceptOnEnter(() => {
if (picked.value != null && !busy.value) onAddExisting()
})
async function onPromote() {
menuOpen.value = false
busy.value = true