mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-01-26 19:09:52 +00:00
feat(sidebar): autofocus search input in Workflows, Model, and Node tabs (#7179)
## Summary This PR improves the user experience by automatically focusing the search input field when opening the Workflows, Model Library, or Node Library sidebar tabs. ## Changes - **SearchBox.vue**: Exposed a `focus()` method to allow parent components to programmatically set focus on the input. - **WorkflowsSidebarTab.vue**: Added a watcher to focus the search box when the tab is activated. - **ModelLibrarySidebarTab.vue**: Added autofocus on component mount. - **NodeLibrarySidebarTab.vue**: Added autofocus on component mount. ## Motivation Users often switch to these tabs specifically to search for an item. Automatically focusing the search box reduces friction and saves a click. https://github.com/user-attachments/assets/8438e71c-a5e4-4b6c-8665-04d535d3ad8e ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-7179-feat-sidebar-autofocus-search-input-in-Workflows-Model-and-Node-tabs-2c06d73d36508199b8c0e83d19f1cd84) by [Unito](https://www.unito.io)
This commit is contained in:
committed by
GitHub
parent
5a4fd9ec40
commit
2636136f87
@@ -10,6 +10,7 @@
|
||||
@click="$emit('showFilter', $event)"
|
||||
/>
|
||||
<InputText
|
||||
ref="inputRef"
|
||||
class="search-box-input w-full"
|
||||
:model-value="modelValue"
|
||||
:placeholder="placeholder"
|
||||
@@ -48,6 +49,7 @@ import Button from 'primevue/button'
|
||||
import IconField from 'primevue/iconfield'
|
||||
import InputIcon from 'primevue/inputicon'
|
||||
import InputText from 'primevue/inputtext'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import type { SearchFilter } from './SearchFilterChip.vue'
|
||||
import SearchFilterChip from './SearchFilterChip.vue'
|
||||
@@ -77,6 +79,14 @@ const emit = defineEmits<{
|
||||
(e: 'removeFilter', filter: TFilter): void
|
||||
}>()
|
||||
|
||||
const inputRef = ref()
|
||||
|
||||
defineExpose({
|
||||
focus: () => {
|
||||
inputRef.value?.$el?.focus()
|
||||
}
|
||||
})
|
||||
|
||||
const emitSearch = debounce((value: string) => {
|
||||
emit('search', value, filters)
|
||||
}, debounceTime)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
</template>
|
||||
<template #header>
|
||||
<SearchBox
|
||||
ref="searchBoxRef"
|
||||
v-model:model-value="searchQuery"
|
||||
class="model-lib-search-box p-2 2xl:p-4"
|
||||
:placeholder="$t('g.searchModels') + '...'"
|
||||
@@ -66,6 +67,7 @@ import { buildTree } from '@/utils/treeUtil'
|
||||
const modelStore = useModelStore()
|
||||
const modelToNodeStore = useModelToNodeStore()
|
||||
const settingStore = useSettingStore()
|
||||
const searchBoxRef = ref()
|
||||
const searchQuery = ref<string>('')
|
||||
const expandedKeys = ref<Record<string, boolean>>({})
|
||||
const { expandNode, toggleNodeOnEvent } = useTreeExpansion(expandedKeys)
|
||||
@@ -180,6 +182,7 @@ watch(
|
||||
)
|
||||
|
||||
onMounted(async () => {
|
||||
searchBoxRef.value?.focus()
|
||||
if (settingStore.get('Comfy.ModelLibrary.AutoLoadAll')) {
|
||||
await modelStore.loadModels()
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
<template #header>
|
||||
<div>
|
||||
<SearchBox
|
||||
ref="searchBoxRef"
|
||||
v-model:model-value="searchQuery"
|
||||
class="node-lib-search-box p-2 2xl:p-4"
|
||||
:placeholder="$t('g.searchNodes') + '...'"
|
||||
@@ -130,7 +131,7 @@ import Button from 'primevue/button'
|
||||
import Divider from 'primevue/divider'
|
||||
import Popover from 'primevue/popover'
|
||||
import type { Ref } from 'vue'
|
||||
import { computed, h, nextTick, ref, render } from 'vue'
|
||||
import { computed, h, nextTick, onMounted, ref, render } from 'vue'
|
||||
|
||||
import SearchBox from '@/components/common/SearchBox.vue'
|
||||
import type { SearchFilter } from '@/components/common/SearchFilterChip.vue'
|
||||
@@ -171,6 +172,12 @@ const { expandNode, toggleNodeOnEvent } = useTreeExpansion(expandedKeys)
|
||||
const nodeBookmarkTreeExplorerRef = ref<InstanceType<
|
||||
typeof NodeBookmarkTreeExplorer
|
||||
> | null>(null)
|
||||
const searchBoxRef = ref()
|
||||
|
||||
onMounted(() => {
|
||||
searchBoxRef.value?.focus()
|
||||
})
|
||||
|
||||
const searchFilter = ref<InstanceType<typeof Popover> | null>(null)
|
||||
const groupingPopover = ref<InstanceType<typeof Popover> | null>(null)
|
||||
const sortingPopover = ref<InstanceType<typeof Popover> | null>(null)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
</template>
|
||||
<template #header>
|
||||
<SearchBox
|
||||
ref="searchBoxRef"
|
||||
v-model:model-value="searchQuery"
|
||||
class="workflows-search-box p-2 2xl:p-4"
|
||||
:placeholder="$t('g.searchWorkflows') + '...'"
|
||||
@@ -158,6 +159,8 @@ const workflowTabsPosition = computed(() =>
|
||||
settingStore.get('Comfy.Workflow.WorkflowTabsPosition')
|
||||
)
|
||||
|
||||
const searchBoxRef = ref()
|
||||
|
||||
const searchQuery = ref('')
|
||||
const isSearching = computed(() => searchQuery.value.length > 0)
|
||||
const filteredWorkflows = ref<ComfyWorkflow[]>([])
|
||||
@@ -295,6 +298,7 @@ const selectionKeys = computed(() => ({
|
||||
|
||||
const workflowBookmarkStore = useWorkflowBookmarkStore()
|
||||
onMounted(async () => {
|
||||
searchBoxRef.value?.focus()
|
||||
await workflowBookmarkStore.loadBookmarks()
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user