Skip to main content

Overview

InputSearch is a specialized input component designed for search interfaces. It includes a search icon, optional clear button, loading state, keyboard shortcut display, and debounced input handling.

Props

value
string
default:"''"
The search input value. This prop is bindable using bind:value.
shortcut
string
default:"''"
Keyboard shortcut to display (e.g., “⌘K” or “Ctrl+K”). Each character is displayed in a separate key wrapper.
placeholder
string
default:"''"
Placeholder text shown when the input is empty.
icon
IconSource
default:"Search"
Icon displayed on the left side of the input. Defaults to the Search icon.
focusOnLoad
boolean
default:"false"
When true, the input automatically receives focus when mounted.
size
'xs' | 'sm' | 'md'
default:"'md'"
Size variant of the input:
  • xs: Height 26px, rounded-sm
  • sm: Height 28px, rounded-md
  • md: Height 32px, rounded-lg
loading
boolean
default:"false"
When true, displays a pulsing loading icon instead of the clear button.
oninput
(value: string) => void
Callback fired when the input value changes. Debounced by 750ms.
onclick
(event: MouseEvent) => void
Callback fired when the input is clicked.
onfocus
(event: FocusEvent) => void
Callback fired when the input receives focus.
onblur
(event: FocusEvent) => void
Callback fired when the input loses focus.

Exported Methods

focus()
function
Programmatically focus the input.
blur()
function
Programmatically blur the input.
toggle()
function
Toggle focus state - if focused, blur; if blurred, focus.
clear()
function
Clear the input value and trigger the oninput callback with empty string.

Usage

<script>
  import { InputSearch } from 'popui'
  
  let searchQuery = $state('')
</script>

<InputSearch 
  bind:value={searchQuery}
  placeholder="Search..." 
/>

With Keyboard Shortcut

<script>
  import { InputSearch } from 'popui'
  
  let query = $state('')
</script>

<InputSearch 
  bind:value={query}
  placeholder="Quick search"
  shortcut="⌘K"
/>

With Search Handler

<script>
  import { InputSearch } from 'popui'
  
  let searchTerm = $state('')
  let results = $state([])
  
  async function handleSearch(value: string) {
    if (!value) {
      results = []
      return
    }
    
    // Debounced search - only called 750ms after user stops typing
    const response = await fetch(`/api/search?q=${value}`)
    results = await response.json()
  }
</script>

<InputSearch 
  bind:value={searchTerm}
  placeholder="Search products..."
  oninput={handleSearch}
/>

With Loading State

<script>
  import { InputSearch } from 'popui'
  
  let query = $state('')
  let isSearching = $state(false)
  
  async function search(value: string) {
    if (!value) {
      isSearching = false
      return
    }
    
    isSearching = true
    await fetch(`/api/search?q=${value}`)
    isSearching = false
  }
</script>

<InputSearch 
  bind:value={query}
  placeholder="Search..."
  loading={isSearching}
  oninput={search}
/>

Different Sizes

<InputSearch size="xs" placeholder="Extra small search" />
<InputSearch size="sm" placeholder="Small search" />
<InputSearch size="md" placeholder="Medium search" />

With Custom Icon

<script>
  import { InputSearch } from 'popui'
  import { Magnifier } from '@invopop/ui-icons'
  
  let value = $state('')
</script>

<InputSearch 
  bind:value
  icon={Magnifier}
  placeholder="Find items..."
/>

Using Exported Methods

<script>
  import { InputSearch } from 'popui'
  
  let searchInput: InputSearch
  let query = $state('')
  
  function focusSearch() {
    searchInput.focus()
  }
  
  function clearAndFocus() {
    searchInput.clear()
    searchInput.focus()
  }
</script>

<div class="space-y-4">
  <InputSearch bind:this={searchInput} bind:value={query} />
  
  <div class="flex gap-2">
    <button onclick={focusSearch}>Focus Search</button>
    <button onclick={clearAndFocus}>Clear & Focus</button>
  </div>
</div>

Global Search with Keyboard Shortcut

<script>
  import { InputSearch } from 'popui'
  import { onMount } from 'svelte'
  
  let searchInput: InputSearch
  let query = $state('')
  
  onMount(() => {
    function handleKeydown(e: KeyboardEvent) {
      if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
        e.preventDefault()
        searchInput.toggle()
      }
    }
    
    window.addEventListener('keydown', handleKeydown)
    return () => window.removeEventListener('keydown', handleKeydown)
  })
</script>

<InputSearch 
  bind:this={searchInput}
  bind:value={query}
  placeholder="Search anything..."
  shortcut="⌘K"
/>

Features

  • Debounced Input: The oninput callback is automatically debounced by 750ms to reduce API calls
  • Clear Button: Displays an X button when the input has a value, allowing quick clearing
  • Loading State: Shows a pulsing icon when loading is true
  • Keyboard Shortcuts: Displays keyboard shortcuts in styled key wrappers
  • Auto Focus: Can automatically focus on mount with focusOnLoad
  • Programmatic Control: Exported methods for focus(), blur(), toggle(), and clear()
  • Smart Padding: Automatically adjusts right padding based on shortcut length and loading/clear button presence
  • Accessible: Includes proper focus states and interactive elements

Build docs developers (and LLMs) love