Merge pull request 'feat(explore): auto-focus tag input on every image change' (#133) from dev into main
Build images / sign-extension (push) Successful in 3s
CI / lint (push) Successful in 3s
Build images / build-ml (push) Successful in 7s
Build images / build-web (push) Successful in 11s
CI / frontend-build (push) Successful in 20s
CI / backend-lint-and-test (push) Successful in 28s
CI / integration (push) Successful in 3m25s

This commit was merged in pull request #133.
This commit is contained in:
2026-06-26 11:28:32 -04:00
2 changed files with 19 additions and 2 deletions
@@ -86,7 +86,11 @@ async function onNavigate(tag) {
// Return focus to the tag input after a suggestion is accepted (from the
// Suggestions panel or the autocomplete dropdown) so the operator can keep
// typing the next tag without re-clicking the field (operator-asked 2026-06-08).
// Exposed so a host surface (the Explore workspace) can re-focus the field when
// it swaps the focused image, without re-clicking. The field's own mobile guard
// (TagAutocomplete) is preserved.
function focusTagInput() { tagInputRef.value?.focus?.() }
defineExpose({ focusTagInput })
async function onRemove(tagId) {
errorMsg.value = null
+15 -2
View File
@@ -98,7 +98,10 @@
<!-- RIGHT: the modal's tag rail, hosted on the anchor. -->
<aside class="fc-ex__rail" aria-label="Tags for the focused image">
<TagPanel v-if="store.currentImageId != null" :host="store" />
<TagPanel
v-if="store.currentImageId != null"
ref="tagPanelRef" :host="store"
/>
</aside>
</div>
</template>
@@ -106,7 +109,7 @@
</template>
<script setup>
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useApi } from '../composables/useApi.js'
import { useExploreStore } from '../stores/explore.js'
@@ -125,6 +128,16 @@ const modal = useModalStore()
const anchorId = computed(() => route.params.imageId || null)
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?.()) },
)
// 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