From 4fe53cdf6b1d584a384ebc211c9fc8739f2676d0 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Sat, 6 Jun 2026 15:15:02 -0400 Subject: [PATCH] =?UTF-8?q?fix(modal/tags):=20fandom=20list,=20modal=20keb?= =?UTF-8?q?ab,=20ESC-after-accept=20=E2=80=94=20#712=20#711=20#700?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #712 — fandom picker showed no existing fandoms: loadFandoms enumerated via /tags/autocomplete with q=' ', which the backend strips to empty → returns []. Switch to the cursor-paged /tags/directory?kind=fandom (loop all pages); drop the load-once guard so the dialog reflects fandoms created elsewhere. #711 — modal tag-chip kebab never opened: the kebab + menu were nested INSIDE the v-chip, which swallowed the click / mis-anchored the teleported menu. Un-nest it as a sibling v-btn using the standard v-menu activator slot (Vuetify wires the click and stacks the overlay above the modal natively). Removes the openTagId workaround. #700 — ESC didn't close the modal after accepting a suggested tag: the guard suppressed close while ANY .v-overlay--active existed, which includes tooltips — a lingering tooltip blocked the close. Exclude .v-tooltip from the guard so only real interactive overlays (menus/dialogs) keep ESC from closing. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/components/modal/FandomPicker.vue | 3 +- .../src/components/modal/FandomSetDialog.vue | 3 +- frontend/src/components/modal/ImageViewer.vue | 6 +- frontend/src/components/modal/TagPanel.vue | 80 +++++++++---------- frontend/src/stores/tags.js | 18 ++++- 5 files changed, 61 insertions(+), 49 deletions(-) diff --git a/frontend/src/components/modal/FandomPicker.vue b/frontend/src/components/modal/FandomPicker.vue index e9ed4a8..d412b6c 100644 --- a/frontend/src/components/modal/FandomPicker.vue +++ b/frontend/src/components/modal/FandomPicker.vue @@ -38,7 +38,8 @@ const store = useTagStore() const selectedId = ref(null) const newName = ref('') -onMounted(() => { if (store.fandomCache.length === 0) store.loadFandoms() }) +// Always refresh on open so the list reflects fandoms created elsewhere (#712). +onMounted(() => store.loadFandoms()) async function onCreate() { const f = await store.createFandom(newName.value.trim()) diff --git a/frontend/src/components/modal/FandomSetDialog.vue b/frontend/src/components/modal/FandomSetDialog.vue index 4706d59..07f38da 100644 --- a/frontend/src/components/modal/FandomSetDialog.vue +++ b/frontend/src/components/modal/FandomSetDialog.vue @@ -84,7 +84,8 @@ const busy = ref(false) const error = ref(null) const collision = ref(null) -onMounted(() => { if (store.fandomCache.length === 0) store.loadFandoms() }) +// Always refresh on open so the list reflects fandoms created elsewhere (#712). +onMounted(() => store.loadFandoms()) async function onCreate() { const name = newName.value.trim() diff --git a/frontend/src/components/modal/ImageViewer.vue b/frontend/src/components/modal/ImageViewer.vue index 5bf9c79..53e17be 100644 --- a/frontend/src/components/modal/ImageViewer.vue +++ b/frontend/src/components/modal/ImageViewer.vue @@ -106,7 +106,11 @@ function onKeyDown(ev) { // overlay's own Esc handling fire instead of closing the whole // modal mid-interaction. Vuetify marks open overlays with // `.v-overlay--active`. - if (document.querySelector('.v-overlay--active')) return + // EXCLUDE tooltips (`.v-tooltip`): they're also `.v-overlay--active` while + // shown, so one lingering after a hover/click (e.g. just after accepting a + // suggested tag) wrongly suppressed the close (#700). Only real interactive + // overlays (menus/dialogs) should keep ESC from closing the modal. + if (document.querySelector('.v-overlay--active:not(.v-tooltip)')) return ev.preventDefault() emit('close') } else if (ev.key === 'ArrowLeft') { diff --git a/frontend/src/components/modal/TagPanel.vue b/frontend/src/components/modal/TagPanel.vue index 319b0b9..4123c18 100644 --- a/frontend/src/components/modal/TagPanel.vue +++ b/frontend/src/components/modal/TagPanel.vue @@ -2,45 +2,43 @@