Skip to content

Commit 88324c4

Browse files
committed
cleanup: Unify the SearchBox, align use in sidebars
1 parent 6028931 commit 88324c4

File tree

15 files changed

+116
-184
lines changed

15 files changed

+116
-184
lines changed

src/components/input/SearchBox.stories.ts renamed to src/components/common/SearchBox.stories.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import type { Meta, StoryObj } from '@storybook/vue3-vite'
22
import { ref } from 'vue'
33

4-
import SearchBox from './SearchBox.vue'
4+
import SearchBox from '@/components/common/SearchBox.vue'
5+
import type { ComponentExposed } from 'vue-component-type-helpers'
6+
interface GenericMeta<C> extends Omit<Meta<C>, 'component'> {
7+
component: Omit<ComponentExposed<C>, 'focus'>
8+
}
59

6-
const meta: Meta<typeof SearchBox> = {
10+
const meta: GenericMeta<typeof SearchBox> = {
711
title: 'Components/Input/SearchBox',
812
component: SearchBox,
913
tags: ['autodocs'],
1014
argTypes: {
15+
modelValue: {
16+
control: 'text'
17+
},
1118
placeholder: {
1219
control: 'text'
1320
},
@@ -19,9 +26,12 @@ const meta: Meta<typeof SearchBox> = {
1926
control: 'select',
2027
options: ['md', 'lg'],
2128
description: 'Size variant of the search box'
22-
}
29+
},
30+
'onUpdate:modelValue': { action: 'update:modelValue' },
31+
onSearch: { action: 'search' }
2332
},
2433
args: {
34+
modelValue: '',
2535
placeholder: 'Search...',
2636
showBorder: false,
2737
size: 'md'
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
33
import { nextTick } from 'vue'
44
import { createI18n } from 'vue-i18n'
55

6-
import SearchBox from './SearchBox.vue'
6+
import SearchBox from '@/components/common/SearchBox.vue'
77

88
const i18n = createI18n({
99
legacy: false,

src/components/common/SearchBox.vue

Lines changed: 72 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,89 @@
11
<template>
2-
<div>
3-
<IconField>
4-
<Button
5-
v-if="filterIcon"
6-
class="p-inputicon filter-button"
7-
:icon="filterIcon"
8-
text
9-
severity="contrast"
10-
@click="$emit('showFilter', $event)"
11-
/>
12-
<InputText
13-
ref="inputRef"
14-
class="search-box-input w-full"
15-
:model-value="modelValue"
16-
:placeholder="placeholder"
17-
:autofocus="autofocus"
18-
@input="handleInput"
19-
/>
20-
<InputIcon v-if="!modelValue" :class="icon" />
21-
<Button
22-
v-if="modelValue"
23-
class="p-inputicon clear-button"
24-
icon="pi pi-times"
25-
text
26-
severity="contrast"
27-
@click="clearSearch"
28-
/>
29-
</IconField>
30-
<div
31-
v-if="filters?.length"
32-
class="search-filters flex flex-wrap gap-2 pt-2"
33-
>
34-
<SearchFilterChip
35-
v-for="filter in filters"
36-
:key="filter.id"
37-
:text="filter.text"
38-
:badge="filter.badge"
39-
:badge-class="filter.badgeClass"
40-
@remove="$emit('removeFilter', filter)"
41-
/>
42-
</div>
2+
<div
3+
:class="
4+
cn(
5+
'relative flex w-full items-center gap-2 bg-comfy-input cursor-text text-comfy-input-foreground',
6+
wrapperStyle
7+
)
8+
"
9+
>
10+
<InputText
11+
ref="inputRef"
12+
v-model="modelValue"
13+
:placeholder
14+
:autofocus
15+
unstyled
16+
class="absolute inset-0 size-full pl-11 border-none outline-none bg-transparent text-sm"
17+
/>
18+
<IconButton
19+
v-if="filterIcon"
20+
class="p-inputicon filter-button absolute right-0 inset-y-0 h-full m-0 p-0"
21+
:icon="filterIcon"
22+
severity="contrast"
23+
@click="$emit('showFilter', $event)"
24+
/>
25+
<InputIcon v-if="!modelValue" :class="icon" />
26+
<Button
27+
v-if="modelValue"
28+
class="p-inputicon clear-button"
29+
icon="pi pi-times"
30+
text
31+
severity="contrast"
32+
@click="modelValue = ''"
33+
/>
34+
</div>
35+
<div v-if="filters?.length" class="search-filters flex flex-wrap gap-2 pt-2">
36+
<SearchFilterChip
37+
v-for="filter in filters"
38+
:key="filter.id"
39+
:text="filter.text"
40+
:badge="filter.badge"
41+
:badge-class="filter.badgeClass"
42+
@remove="$emit('removeFilter', filter)"
43+
/>
4344
</div>
4445
</template>
4546

4647
<script setup lang="ts" generic="TFilter extends SearchFilter">
47-
import { debounce } from 'es-toolkit/compat'
48+
import { cn } from '@comfyorg/tailwind-utils'
49+
import { watchDebounced } from '@vueuse/core'
4850
import Button from 'primevue/button'
49-
import IconField from 'primevue/iconfield'
5051
import InputIcon from 'primevue/inputicon'
5152
import InputText from 'primevue/inputtext'
52-
import { ref } from 'vue'
53+
import { computed, ref } from 'vue'
5354
55+
import IconButton from '../button/IconButton.vue'
5456
import type { SearchFilter } from './SearchFilterChip.vue'
5557
import SearchFilterChip from './SearchFilterChip.vue'
5658
5759
const {
58-
modelValue,
5960
placeholder = 'Search...',
6061
icon = 'pi pi-search',
6162
debounceTime = 300,
6263
filterIcon,
6364
filters = [],
64-
autofocus = false
65+
autofocus = false,
66+
showBorder = false,
67+
size = 'md'
6568
} = defineProps<{
66-
modelValue: string
6769
placeholder?: string
6870
icon?: string
6971
debounceTime?: number
7072
filterIcon?: string
7173
filters?: TFilter[]
7274
autofocus?: boolean
75+
showBorder?: boolean
76+
size?: 'md' | 'lg'
7377
}>()
7478
7579
const emit = defineEmits<{
76-
(e: 'update:modelValue', value: string): void
7780
(e: 'search', value: string, filters: TFilter[]): void
7881
(e: 'showFilter', event: Event): void
7982
(e: 'removeFilter', filter: TFilter): void
8083
}>()
8184
85+
const modelValue = defineModel<string>({ required: true })
86+
8287
const inputRef = ref()
8388
8489
defineExpose({
@@ -87,20 +92,27 @@ defineExpose({
8792
}
8893
})
8994
90-
const emitSearch = debounce((value: string) => {
91-
emit('search', value, filters)
92-
}, debounceTime)
95+
watchDebounced(
96+
modelValue,
97+
(value: string) => {
98+
emit('search', value, filters)
99+
},
100+
{ debounce: debounceTime }
101+
)
93102
94-
const handleInput = (event: Event) => {
95-
const target = event.target as HTMLInputElement
96-
emit('update:modelValue', target.value)
97-
emitSearch(target.value)
98-
}
103+
const wrapperStyle = computed(() => {
104+
if (showBorder) {
105+
return cn('rounded p-2 border border-solid border-border-default')
106+
}
99107
100-
const clearSearch = () => {
101-
emit('update:modelValue', '')
102-
emitSearch('')
103-
}
108+
// Size-specific classes matching button sizes for consistency
109+
const sizeClasses = {
110+
md: 'h-8 px-2 py-1.5', // Matches button sm size
111+
lg: 'h-10 px-4 py-2' // Matches button md size
112+
}[size]
113+
114+
return cn('rounded-lg', sizeClasses)
115+
})
104116
</script>
105117

106118
<style scoped>

src/components/custom/widget/WorkflowTemplateSelectorDialog.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ import CardBottom from '@/components/card/CardBottom.vue'
388388
import CardContainer from '@/components/card/CardContainer.vue'
389389
import CardTop from '@/components/card/CardTop.vue'
390390
import SquareChip from '@/components/chip/SquareChip.vue'
391+
import SearchBox from '@/components/common/SearchBox.vue'
391392
import MultiSelect from '@/components/input/MultiSelect.vue'
392-
import SearchBox from '@/components/input/SearchBox.vue'
393393
import SingleSelect from '@/components/input/SingleSelect.vue'
394394
import AudioThumbnail from '@/components/templates/thumbnails/AudioThumbnail.vue'
395395
import CompareSliderThumbnail from '@/components/templates/thumbnails/CompareSliderThumbnail.vue'

src/components/input/MultiSelect.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ import MultiSelect from 'primevue/multiselect'
178178
import { computed, useAttrs } from 'vue'
179179
import { useI18n } from 'vue-i18n'
180180
181-
import SearchBox from '@/components/input/SearchBox.vue'
181+
import SearchBox from '@/components/common/SearchBox.vue'
182182
import { usePopoverSizing } from '@/composables/usePopoverSizing'
183183
import { cn } from '@/utils/tailwindUtil'
184184

src/components/input/SearchBox.vue

Lines changed: 0 additions & 95 deletions
This file was deleted.

src/components/sidebar/tabs/ModelLibrarySidebarTab.vue

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,19 @@
1717
/>
1818
</template>
1919
<template #header>
20-
<SearchBox
21-
ref="searchBoxRef"
22-
v-model:model-value="searchQuery"
23-
class="model-lib-search-box p-2 2xl:p-4"
24-
:placeholder="$t('g.searchModels') + '...'"
25-
@search="handleSearch"
26-
/>
20+
<div class="px-2 2xl:px-4">
21+
<SearchBox
22+
ref="searchBoxRef"
23+
v-model:model-value="searchQuery"
24+
:placeholder="$t('g.searchModels') + '...'"
25+
@search="handleSearch"
26+
/>
27+
</div>
2728
</template>
2829
<template #body>
2930
<ElectronDownloadItems v-if="isElectron()" />
3031

32+
<Divider type="dashed" class="m-2" />
3133
<TreeExplorer
3234
v-model:expanded-keys="expandedKeys"
3335
class="model-lib-tree-explorer"
@@ -43,6 +45,7 @@
4345
</template>
4446

4547
<script setup lang="ts">
48+
import { Divider } from 'primevue'
4649
import Button from 'primevue/button'
4750
import { computed, nextTick, onMounted, ref, toRef, watch } from 'vue'
4851

src/components/sidebar/tabs/NodeLibrarySidebarTab.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@
7575
</Popover>
7676
</template>
7777
<template #header>
78-
<div>
78+
<div class="px-2 2xl:px-4">
7979
<SearchBox
8080
ref="searchBoxRef"
8181
v-model:model-value="searchQuery"
82-
class="node-lib-search-box p-2 2xl:p-4"
82+
class="node-lib-search-box"
8383
:placeholder="$t('g.searchNodes') + '...'"
8484
filter-icon="pi pi-filter"
8585
:filters

0 commit comments

Comments
 (0)