Simplify filter UI

Simplify filter UI by using SearchFilterDropdown for all filters

- Remove complex template logic with Dropdown and MultiSelect components
- Use SearchFilterDropdown component for all filters (consistent with sort/mode dropdowns)
- Remove multi-select support to simplify implementation
- Add placeholder and clear functionality to SearchFilterDropdown
This commit is contained in:
bymyself
2025-06-15 20:00:17 -07:00
parent 3f036fcf51
commit 6eed618a94
4 changed files with 22 additions and 74 deletions

View File

@@ -47,56 +47,13 @@
</div>
<!-- Add search refinement dropdowns if provider supports them -->
<div v-if="filterOptions?.length" class="flex gap-3 ml-1 text-sm">
<template v-for="filterOption in filterOptions" :key="filterOption.id">
<div class="flex items-center gap-1">
<span class="text-muted">{{ filterOption.label }}:</span>
<Dropdown
v-if="filterOption.type === 'single-select'"
:model-value="selectedFilters[filterOption.id] as string"
:options="filterOption.options || []"
option-label="label"
option-value="value"
placeholder="Any"
:show-clear="true"
class="min-w-[6rem] border-none bg-transparent shadow-none"
:pt="{
input: { class: 'py-0 px-1 border-none' },
trigger: { class: 'hidden' },
panel: { class: 'shadow-md' },
item: { class: 'py-2 px-3 text-sm' }
}"
@update:model-value="
$event
? (selectedFilters[filterOption.id] = $event)
: delete selectedFilters[filterOption.id]
"
/>
<MultiSelect
v-else-if="filterOption.type === 'multi-select'"
:model-value="selectedFilters[filterOption.id] as string[]"
:options="filterOption.options || []"
option-label="label"
option-value="value"
display="chip"
class="min-w-[6rem] border-none bg-transparent shadow-none"
:pt="{
input: { class: 'py-0 px-1 border-none' },
trigger: { class: 'hidden' },
panel: { class: 'shadow-md' },
item: { class: 'py-2 px-3 text-sm' },
label: { class: 'py-0 px-1 text-sm' },
header: { class: 'p-2' },
filterInput: { class: 'text-sm' },
emptyMessage: { class: 'text-sm text-muted p-3' }
}"
@update:model-value="
$event?.length > 0
? (selectedFilters[filterOption.id] = $event)
: delete selectedFilters[filterOption.id]
"
/>
</div>
</template>
<SearchFilterDropdown
v-for="filterOption in filterOptions"
:key="filterOption.id"
v-model:modelValue="selectedFilters[filterOption.id]"
:options="availableFilterOptions(filterOption)"
:label="filterOption.label"
/>
</div>
</div>
</div>
@@ -107,8 +64,6 @@ import { stubTrue } from 'lodash'
import AutoComplete, {
AutoCompleteOptionSelectEvent
} from 'primevue/autocomplete'
import Dropdown from 'primevue/dropdown'
import MultiSelect from 'primevue/multiselect'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
@@ -157,6 +112,17 @@ const searchModeOptions: SearchOption<SearchMode>[] = [
{ id: 'nodes', label: t('g.nodes') }
]
// Convert filter options to SearchOption format for SearchFilterDropdown
const availableFilterOptions = (
filter: SearchFilter
): SearchOption<string>[] => {
if (!filter.options) return []
return filter.options.map((option) => ({
id: option.value,
label: option.label
}))
}
// When a dropdown query suggestion is selected, update the search query
const onOptionSelect = (event: AutoCompleteOptionSelectEvent) => {
searchQuery.value = event.value.query

View File

@@ -6,6 +6,7 @@
:options="options"
option-label="label"
option-value="id"
placeholder="Any"
class="min-w-[6rem] border-none bg-transparent shadow-none"
:pt="{
input: { class: 'py-0 px-1 border-none' },

View File

@@ -108,25 +108,6 @@ export function useRegistrySearch(
return getFilterableFields()
})
// Initialize filters with default values when they become available
const filterOptionsInitialized = ref(false)
watch(
filterOptions,
(newOptions) => {
if (!filterOptionsInitialized.value && newOptions.length > 0) {
const defaultFilters: ActiveFilters = {}
for (const option of newOptions) {
if (option.defaultValue !== undefined) {
defaultFilters[option.id] = option.defaultValue
}
}
activeFilters.value = { ...activeFilters.value, ...defaultFilters }
filterOptionsInitialized.value = true
}
},
{ immediate: true }
)
return {
isLoading,
pageNumber,

View File

@@ -16,9 +16,9 @@ export type QuerySuggestion = {
export interface SearchFilter {
id: string
label: string
type: 'multi-select' | 'single-select' | 'boolean'
type: 'single-select' | 'boolean'
options?: FilterOption[]
defaultValue?: string | string[] | boolean
defaultValue?: string | boolean
}
export interface FilterOption {
@@ -27,7 +27,7 @@ export interface FilterOption {
icon?: string
}
export type ActiveFilters = Record<string, string | string[] | boolean>
export type ActiveFilters = Record<string, string | boolean>
export interface SearchPacksResult {
nodePacks: RegistryNodePack[]