npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@choice-ui/search-input

v0.0.6

Published

A search input component with search icon, clear button, and search-specific styling

Downloads

793

Readme

SearchInput

A specialized search input component built on top of TextField, featuring a search icon prefix and clear button suffix. It provides an intuitive search experience with proper internationalization support and accessible interactions.

Import

import { SearchInput } from "@choice-ui/react"

Features

  • Built on TextField for consistent behavior and styling
  • Search icon prefix for clear visual indication
  • Clear button that appears when input has content
  • Internationalization support for labels and tooltips
  • Multiple visual variants (default, light, dark, reset)
  • All TextField features: sizes, states, and accessibility
  • Automatic focus management and keyboard navigation
  • Tooltip support on clear button

Usage

Basic

<SearchInput
  value={searchQuery}
  onChange={setSearchQuery}
/>

With custom placeholder

<SearchInput
  value={searchQuery}
  onChange={setSearchQuery}
  placeholder="Search products..."
/>

Variants

// Default - follows page theme
<SearchInput variant="default" value={query} onChange={setQuery} />

// Light - fixed light appearance
<SearchInput variant="light" value={query} onChange={setQuery} />

// Dark - fixed dark appearance
<SearchInput variant="dark" value={query} onChange={setQuery} />

// Reset - no variant styling
<SearchInput variant="reset" value={query} onChange={setQuery} />

With internationalization

<SearchInput
  value={searchQuery}
  onChange={setSearchQuery}
  placeholder="Search..."
  i18n={{
    clear: "Clear search",
    placeholder: "Search for anything...",
  }}
/>

Disabled state

<SearchInput
  disabled
  value={searchQuery}
  onChange={setSearchQuery}
  placeholder="Search disabled..."
/>

Large size

<SearchInput
  size="large"
  value={searchQuery}
  onChange={setSearchQuery}
  placeholder="Large search input..."
/>

Props

interface SearchInputProps extends TextFieldProps {
  /** Internationalization configuration */
  i18n?: {
    clear: string
    placeholder: string
  }
}

Inherits all props from TextFieldProps, including:

  • value?: string - Current search value

  • onChange?: (value: string) => void - Callback when value changes

  • placeholder?: string - Placeholder text (defaults to "Search...")

  • variant?: "default" | "light" | "dark" | "reset" - Visual style variant

  • size?: "default" | "large" - Input size

  • disabled?: boolean - Whether the input is disabled

  • All other standard HTML input attributes

  • Defaults:

    • placeholder: "Search..."
    • variant: "default" (follows page theme)
    • i18n.clear: "Clear"
  • Variant options:

    • default: Follows the page theme dynamically (light/dark mode)
    • light: Fixed light appearance regardless of theme
    • dark: Fixed dark appearance regardless of theme
    • reset: Removes variant styling, no variant settings applied
  • Behavior:

    • Search icon is always visible in the prefix position
    • Clear button appears only when there's content to clear
    • Clear button includes tooltip for accessibility
    • All TextField behaviors are inherited (focus selection, editing states, etc.)

Styling

  • This component uses Tailwind CSS via tailwind-variants in tv.ts with slots.
  • Built on TextField, so inherits all TextField styling capabilities
  • Slots available: icon, action
  • Search icon color adapts based on variant and interaction states
  • Clear button integrates seamlessly with the input design

Accessibility

  • Search icon provides visual context for screen readers
  • Clear button includes tooltip with descriptive text
  • Supports all TextField accessibility features
  • Keyboard navigation works seamlessly (Tab to clear button)
  • Clear button is focusable and clickable
  • Proper ARIA attributes inherited from TextField

Internationalization

The component supports customizing text through the i18n prop:

<SearchInput
  value={query}
  onChange={setQuery}
  i18n={{
    clear: "Effacer", // French
    placeholder: "Rechercher...",
  }}
/>

Best practices

  • Use clear, descriptive placeholder text that matches your search context
  • Provide appropriate internationalization for multi-language applications
  • Consider debouncing the onChange callback for performance with large datasets
  • Use the appropriate variant to match your application's theme
  • Ensure the clear functionality provides immediate visual feedback

Examples

Product search with debouncing

import { useDebouncedCallback } from 'use-debounce'

const [query, setQuery] = useState("")
const [results, setResults] = useState([])

const debouncedSearch = useDebouncedCallback(
  async (searchQuery: string) => {
    if (searchQuery.trim()) {
      const results = await searchProducts(searchQuery)
      setResults(results)
    } else {
      setResults([])
    }
  },
  300
)

<SearchInput
  value={query}
  onChange={(value) => {
    setQuery(value)
    debouncedSearch(value)
  }}
  placeholder="Search products..."
/>

Search in dark theme with custom clear text

<SearchInput
  variant="dark"
  size="large"
  value={searchQuery}
  onChange={setSearchQuery}
  placeholder="Search documentation..."
  i18n={{
    clear: "Clear search query",
  }}
/>

Search with external clear control

const [query, setQuery] = useState("")

<div className="flex items-center gap-2">
  <SearchInput
    value={query}
    onChange={setQuery}
    placeholder="Search files..."
  />
  <Button
    variant="secondary"
    onClick={() => setQuery("")}
    disabled={!query}
  >
    Clear All
  </Button>
</div>

Controlled search with validation

const [query, setQuery] = useState("")
const [isValid, setIsValid] = useState(true)

<SearchInput
  value={query}
  onChange={(value) => {
    setQuery(value)
    setIsValid(value.length === 0 || value.length >= 3)
  }}
  selected={!isValid}
  placeholder="Search (minimum 3 characters)..."
/>

Integration with TextField

Since SearchInput is built on TextField, you can use it with all TextField features:

<SearchInput
  value={query}
  onChange={setQuery}
>
  <SearchInput.Label>Search Query</SearchInput.Label>
  <SearchInput.Description>Enter keywords to find relevant content</SearchInput.Description>
</SearchInput>

Notes

  • The clear button uses IconButton with ghost variant for consistent styling
  • Search icon color automatically adapts to hover and focus states
  • Component is fully controlled - always provide both value and onChange
  • Clear functionality calls onChange with an empty string
  • The component maintains all TextField's advanced features like editing state tracking