Enhance MarketFuzzySearch component with improved suggestion display and input focus handling
- Added focus and blur event handlers to manage input focus state. - Updated suggestion display to show both search suggestions and recent searches in a unified dropdown. - Improved styling for suggestion buttons to enhance user interaction. - Ensured input field is focused after clearing search, improving usability. These changes enhance the search experience by providing clearer suggestions and better input management.
This commit is contained in:
parent
06d4cc4d4a
commit
f2a432b6df
1 changed files with 69 additions and 54 deletions
|
|
@ -11,6 +11,8 @@
|
|||
:model-value="searchQuery"
|
||||
@update:model-value="handleSearchChange"
|
||||
@keydown="handleKeydown"
|
||||
@focus="handleFocus"
|
||||
@blur="handleBlur"
|
||||
:placeholder="enhancedPlaceholder"
|
||||
:disabled="disabled"
|
||||
class="pl-10 pr-20"
|
||||
|
|
@ -56,48 +58,54 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search Suggestions (when no input but focused) -->
|
||||
<div v-if="showSuggestions && !searchQuery && isFocused" class="mt-2 p-3 border rounded-lg bg-muted/50">
|
||||
<div class="text-sm font-medium mb-2">Try searching for:</div>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<Button
|
||||
v-for="suggestion in searchSuggestions"
|
||||
:key="suggestion"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@click="applySuggestion(suggestion)"
|
||||
class="h-6 px-2 text-xs"
|
||||
>
|
||||
{{ suggestion }}
|
||||
</Button>
|
||||
<!-- Floating Search Suggestions & Recent Searches -->
|
||||
<div
|
||||
v-if="(showSuggestions || showRecentSearches) && !searchQuery && isFocused"
|
||||
class="absolute top-full left-0 right-0 z-50 mt-1 max-h-80 overflow-y-auto bg-popover border border-border rounded-md shadow-lg"
|
||||
>
|
||||
<!-- Search Suggestions -->
|
||||
<div v-if="showSuggestions && searchSuggestions.length > 0" class="p-3 border-b border-border">
|
||||
<div class="text-sm font-medium mb-2 text-foreground">Try searching for:</div>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<Button
|
||||
v-for="suggestion in searchSuggestions"
|
||||
:key="suggestion"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@click="applySuggestion(suggestion)"
|
||||
class="h-6 px-2 text-xs hover:bg-accent hover:text-accent-foreground"
|
||||
>
|
||||
{{ suggestion }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Recent Searches -->
|
||||
<div v-if="showRecentSearches && recentSearches.length > 0 && !searchQuery && isFocused" class="mt-2 p-3 border rounded-lg bg-muted/50">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="text-sm font-medium">Recent searches:</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@click="clearRecentSearches"
|
||||
class="h-5 px-1 text-xs"
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<Button
|
||||
v-for="recent in recentSearches.slice(0, 5)"
|
||||
:key="recent"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@click="applyRecentSearch(recent)"
|
||||
class="h-6 px-2 text-xs"
|
||||
>
|
||||
<History class="w-3 h-3 mr-1" />
|
||||
{{ recent }}
|
||||
</Button>
|
||||
<!-- Recent Searches -->
|
||||
<div v-if="showRecentSearches && recentSearches.length > 0" class="p-3">
|
||||
<div class="flex items-center justify-between mb-2">
|
||||
<div class="text-sm font-medium text-foreground">Recent searches:</div>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@click="clearRecentSearches"
|
||||
class="h-5 px-1 text-xs hover:bg-destructive hover:text-destructive-foreground"
|
||||
>
|
||||
Clear
|
||||
</Button>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-1">
|
||||
<Button
|
||||
v-for="recent in recentSearches.slice(0, 5)"
|
||||
:key="recent"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
@click="applyRecentSearch(recent)"
|
||||
class="h-6 px-2 text-xs hover:bg-accent hover:text-accent-foreground"
|
||||
>
|
||||
<History class="w-3 h-3 mr-1" />
|
||||
{{ recent }}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -267,7 +275,14 @@ const handleClear = () => {
|
|||
emit('search', '')
|
||||
emit('results', filteredItems.value)
|
||||
emit('clear')
|
||||
searchInputRef.value?.focus()
|
||||
|
||||
// Focus the input after clearing
|
||||
if (searchInputRef.value) {
|
||||
const inputElement = searchInputRef.value.$el?.querySelector('input') || searchInputRef.value.$el
|
||||
if (inputElement && typeof inputElement.focus === 'function') {
|
||||
inputElement.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeydown = (event: KeyboardEvent) => {
|
||||
|
|
@ -275,8 +290,11 @@ const handleKeydown = (event: KeyboardEvent) => {
|
|||
if (event.key === 'Escape') {
|
||||
if (searchQuery.value) {
|
||||
handleClear()
|
||||
} else {
|
||||
searchInputRef.value?.blur()
|
||||
} else if (searchInputRef.value) {
|
||||
const inputElement = searchInputRef.value.$el?.querySelector('input') || searchInputRef.value.$el
|
||||
if (inputElement && typeof inputElement.blur === 'function') {
|
||||
inputElement.blur()
|
||||
}
|
||||
}
|
||||
event.preventDefault()
|
||||
}
|
||||
|
|
@ -323,7 +341,14 @@ const handleGlobalKeydown = (event: KeyboardEvent) => {
|
|||
// ⌘K or Ctrl+K to focus search
|
||||
if ((event.metaKey || event.ctrlKey) && event.key === 'k') {
|
||||
event.preventDefault()
|
||||
searchInputRef.value?.focus()
|
||||
console.log('⌘K/Ctrl+K pressed, focusing search input', !!searchInputRef.value)
|
||||
if (searchInputRef.value) {
|
||||
// Access the underlying HTML input element from the Shadcn Input component
|
||||
const inputElement = searchInputRef.value.$el?.querySelector('input') || searchInputRef.value.$el
|
||||
if (inputElement && typeof inputElement.focus === 'function') {
|
||||
inputElement.focus()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -335,20 +360,10 @@ watch(filteredItems, (items) => {
|
|||
// Setup and cleanup
|
||||
onMounted(() => {
|
||||
document.addEventListener('keydown', handleGlobalKeydown)
|
||||
|
||||
if (searchInputRef.value) {
|
||||
searchInputRef.value.addEventListener('focus', handleFocus)
|
||||
searchInputRef.value.addEventListener('blur', handleBlur)
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
document.removeEventListener('keydown', handleGlobalKeydown)
|
||||
|
||||
if (searchInputRef.value) {
|
||||
searchInputRef.value.removeEventListener('focus', handleFocus)
|
||||
searchInputRef.value.removeEventListener('blur', handleBlur)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue