mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 14:27:40 +00:00
## Summary Background and text colors. ## Screenshot <img width="1186" height="148" alt="image" src="https://github.com/user-attachments/assets/0ff3b0d5-6aae-45c5-9ebf-060a9973489c" /> ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6835-Style-Fix-the-filter-search-sort-controls-on-the-Template-Select-Modal-2b36d73d3650816b9850e1b9f7feb25e) by [Unito](https://www.unito.io)
94 lines
2.5 KiB
Vue
94 lines
2.5 KiB
Vue
<template>
|
|
<div :class="wrapperStyle" @click="focusInput">
|
|
<i class="icon-[lucide--search] text-muted-foreground" />
|
|
<InputText
|
|
ref="input"
|
|
v-model="internalSearchQuery"
|
|
:aria-label="
|
|
placeholder || t('templateWidgets.sort.searchPlaceholder', 'Search...')
|
|
"
|
|
:placeholder="
|
|
placeholder || t('templateWidgets.sort.searchPlaceholder', 'Search...')
|
|
"
|
|
type="text"
|
|
unstyled
|
|
class="absolute inset-0 size-full pl-11 border-none outline-none bg-transparent text-sm text-base-foreground"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useDebounceFn } from '@vueuse/core'
|
|
import InputText from 'primevue/inputtext'
|
|
import { computed, onMounted, ref, watch } from 'vue'
|
|
|
|
import { t } from '@/i18n'
|
|
import { cn } from '@/utils/tailwindUtil'
|
|
|
|
const SEARCH_DEBOUNCE_DELAY_MS = 300
|
|
|
|
const {
|
|
autofocus = false,
|
|
placeholder,
|
|
showBorder = false,
|
|
size = 'md'
|
|
} = defineProps<{
|
|
autofocus?: boolean
|
|
placeholder?: string
|
|
showBorder?: boolean
|
|
size?: 'md' | 'lg'
|
|
}>()
|
|
|
|
// defineModel without arguments uses 'modelValue' as the prop name
|
|
const searchQuery = defineModel<string>()
|
|
|
|
// Internal search query state for immediate UI updates
|
|
const internalSearchQuery = ref<string>(searchQuery.value ?? '')
|
|
|
|
// Create debounced function to update the parent model
|
|
const updateSearchQuery = useDebounceFn((value: string) => {
|
|
searchQuery.value = value
|
|
}, SEARCH_DEBOUNCE_DELAY_MS)
|
|
|
|
// Watch internal query changes and trigger debounced update
|
|
watch(internalSearchQuery, (newValue) => {
|
|
void updateSearchQuery(newValue)
|
|
})
|
|
|
|
// Sync external changes back to internal state
|
|
watch(searchQuery, (newValue) => {
|
|
if (newValue !== internalSearchQuery.value) {
|
|
internalSearchQuery.value = newValue || ''
|
|
}
|
|
})
|
|
|
|
const input = ref<{ $el: HTMLElement } | null>()
|
|
const focusInput = () => {
|
|
if (input.value && input.value.$el) {
|
|
input.value.$el.focus()
|
|
}
|
|
}
|
|
|
|
onMounted(() => autofocus && focusInput())
|
|
|
|
const wrapperStyle = computed(() => {
|
|
const baseClasses =
|
|
'relative flex w-full items-center gap-2 bg-secondary-background cursor-text'
|
|
|
|
if (showBorder) {
|
|
return cn(
|
|
baseClasses,
|
|
'rounded p-2 border border-solid border-border-default'
|
|
)
|
|
}
|
|
|
|
// Size-specific classes matching button sizes for consistency
|
|
const sizeClasses = {
|
|
md: 'h-8 px-2 py-1.5', // Matches button sm size
|
|
lg: 'h-10 px-4 py-2' // Matches button md size
|
|
}[size]
|
|
|
|
return cn(baseClasses, 'rounded-lg', sizeClasses)
|
|
})
|
|
</script>
|