From c8a8e2305042a49b2cd88c5b70af3f3f9139aa4a Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Fri, 26 Jun 2026 21:25:51 -0400 Subject: [PATCH] feat(explore/tags): return focus to the tag input after every action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explore is a rapid walk-and-tag surface, so focus must keep returning to the tag input with no extra click (operator-asked 2026-06-26). Two gaps closed: - Navigation hardening: refocus on every focused-image change (neighbour click, breadcrumb, Random image, seed) now runs nextTick → requestAnimationFrame, so it lands AFTER the post-navigation re-render/paint instead of being stolen back by the neighbour-grid re-render. - All tag actions refocus, in both Explore and the modal: tag add (existing/new) and remove now hand focus back like accept-suggestion already did; and the rename + fandom-assignment dialogs refocus on @after-leave (fires after Vuetify's own focus-return to the activator, so ours wins). TagAutocomplete's mobile guard is preserved throughout (no soft-keyboard pop on touch). Modal behaviour gains the same stickier focus — consistent, low-risk. Co-Authored-By: Claude Opus 4.8 (1M context) --- frontend/src/components/modal/TagPanel.vue | 20 ++++++++++++++++---- frontend/src/views/ExploreView.vue | 20 ++++++++++++-------- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/frontend/src/components/modal/TagPanel.vue b/frontend/src/components/modal/TagPanel.vue index 4f0d335..0e76142 100644 --- a/frontend/src/components/modal/TagPanel.vue +++ b/frontend/src/components/modal/TagPanel.vue @@ -30,7 +30,15 @@ @accepted="focusTagInput" /> - + + store.currentImageId, - (id) => { if (id != null) nextTick(() => tagPanelRef.value?.focusTagInput?.()) }, -) +// Auto-focus the tag input after any action so tagging needs no extra click — +// the whole point of the workspace (operator-asked 2026-06-26). nextTick waits +// for the post-navigation re-render, then rAF lands the focus AFTER paint so a +// neighbour/breadcrumb click that re-renders the grid can't steal it back. +// Reuses TagPanel/TagAutocomplete's focus, which keeps its mobile guard (no +// soft-keyboard pop on touch). +function refocusTag () { + nextTick(() => requestAnimationFrame(() => tagPanelRef.value?.focusTagInput?.())) +} +// Every focused-image change (seed + every walk: neighbour click, breadcrumb, +// Random image). +watch(() => store.currentImageId, (id) => { if (id != null) refocusTag() }) // The route is the source of truth. With an anchor, walk it; without one (the // bare /explore nav entry) seed a RANDOM image so the tab kick-starts a rabbit