fix(modal): tag-chip kebab + ESC-after-accept + autocomplete scroll-into-view
Two regressions the operator re-flagged (the earlier "fixes" didn't work): #711 tag-chip kebab: TagPanel's kebab used the #activator + v-bind="props" v-menu pattern — the exact pattern SuggestionItem's own comment documents as NEVER toggling inside the teleported ImageViewer modal. Extracted TagChip.vue using the proven explicit pattern (activator="parent" + :open-on-click="false" + a manual v-model), mirroring the working suggestion kebab. Now opens. #700 ESC-after-accept: the guard suppressed close whenever ANY non-tooltip overlay was active anywhere in the DOM, so a stray overlay after accepting a suggestion (focus drops to <body>) blocked Esc. Now key off the event origin — only defer to an overlay when Esc is pressed from INSIDE its content (ev.target.closest('.v-overlay__content')); a stray overlay no longer traps the modal, and dialogs/menus still handle their own Esc. A1: TagAutocomplete arrow-nav now scrollIntoView's the highlighted row — the list is capped at 240px and arrowing past the fold left the active item off-screen (operator-flagged). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -97,20 +97,20 @@ let prevBodyOverflow = null
|
||||
// own keystrokes.
|
||||
function onKeyDown(ev) {
|
||||
if (ev.key === 'Escape') {
|
||||
// Escape closes the modal even from inside a text input — that's
|
||||
// the universal "get me out of here" expectation, and the
|
||||
// autofocused tag-entry field would otherwise trap focus with no
|
||||
// visible escape (operator-flagged 2026-06-01). EXCEPTION: when a
|
||||
// nested Vuetify overlay is open (v-menu autocomplete dropdown,
|
||||
// FandomPicker v-dialog, per-suggestion 3-dot menu), let that
|
||||
// overlay's own Esc handling fire instead of closing the whole
|
||||
// modal mid-interaction. Vuetify marks open overlays with
|
||||
// `.v-overlay--active`.
|
||||
// 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
|
||||
// Escape closes the modal even from inside a text input — the universal
|
||||
// "get me out of here" expectation; the autofocused tag field would
|
||||
// otherwise trap focus (operator-flagged 2026-06-01). EXCEPTION: when the
|
||||
// keystroke originates INSIDE an open Vuetify overlay's content (a rename/
|
||||
// fandom/alias dialog, or a kebab menu), let that overlay handle its own
|
||||
// Esc and don't close the whole modal.
|
||||
//
|
||||
// #700 re-fix (2026-06-07): the prior guard queried for ANY active overlay
|
||||
// anywhere in the DOM and suppressed the close — so a lingering overlay
|
||||
// after accepting a suggestion (focus drops to <body>, not into any
|
||||
// overlay) wrongly blocked Esc. Keying off the event's origin instead means
|
||||
// a stray overlay no longer traps the modal: only an Esc pressed from
|
||||
// within overlay content defers to that overlay.
|
||||
if (ev.target?.closest?.('.v-overlay__content')) return
|
||||
ev.preventDefault()
|
||||
emit('close')
|
||||
} else if (ev.key === 'ArrowLeft') {
|
||||
|
||||
Reference in New Issue
Block a user