feat(explore/tags): return focus to the tag input after every action
CI / lint (push) Successful in 3s
CI / frontend-build (push) Successful in 19s
CI / backend-lint-and-test (push) Successful in 27s
CI / integration (push) Successful in 3m18s

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) <noreply@anthropic.com>
This commit is contained in:
2026-06-26 21:25:51 -04:00
parent e3855a5ae0
commit c8a8e23050
2 changed files with 28 additions and 12 deletions
+12 -8
View File
@@ -130,14 +130,18 @@ const seeding = ref(false)
const seedError = ref(null)
const tagPanelRef = ref(null)
// Auto-focus the tag input whenever the focused image changes (seed + every
// walk) so tagging needs no extra click — the whole point of the workspace
// (operator-asked 2026-06-26). Reuses TagPanel/TagAutocomplete's focus, which
// keeps its own mobile guard (no soft-keyboard pop on touch).
watch(
() => 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