VibeUI
ComponentsDocs
VibeUI

Components with taste, that you own. Copy the source, retint the tokens, keep every line.

Library

  • All components
  • Signature pieces
  • Text effects
  • Footers

Docs

  • Introduction
  • Installation
  • Theming
  • CLI

Project

  • GitHub
  • Agents and MCP
  • Issues
  • MIT license
© 2026 VibeUI · MIT licensed
  1. Components
  2. Forms
  3. Search Field

Search Field

Search input with a leading icon and a clear button.

FormsClient component

Type to see the clear button appear.

Install

bash
npx @agents-npm-packages/vibeui add search-field --dir ./src/components/ui

Import

tsx
import { SearchField } from "@/components/ui/search-field"

API

Generated from the component's TypeScript types, so it always matches the source. * marks a required prop.

<SearchField>

PropTypeDefaultDescription
valuestring—Controlled value.
onChange((value: string) => void)—Called when the value changes.
placeholderstring"Search…"Hint text shown while empty.
classNamestring—Extra classes, merged with the component's own.
autoFocusboolean—Focuses the input on mount.

Source

src/components/ui/search-field.tsx
"use client";

import { MagnifyingGlass, X } from "@phosphor-icons/react";
import { cn } from "@/lib/utils";

/** Search input with a leading icon and a clear button. */
export function SearchField({
  value,
  onChange,
  placeholder = "Search…",
  className,
  autoFocus,
}: {
  value?: string;
  onChange?: (value: string) => void;
  placeholder?: string;
  className?: string;
  autoFocus?: boolean;
}) {
  return (
    <div
      className={cn(
        "flex h-10 items-center gap-2 rounded-sm border border-line-strong bg-surface px-3 shadow-quiet transition-[border-color,box-shadow] duration-150 hover:border-faint focus-within:border-accent focus-within:ring-[3px] focus-within:ring-ring",
        className,
      )}
    >
      <MagnifyingGlass size={16} className="shrink-0 text-faint" weight="bold" />
      <input
        type="search"
        value={value}
        autoFocus={autoFocus}
        onChange={(e) => onChange?.(e.target.value)}
        placeholder={placeholder}
        aria-label={placeholder}
        className="h-full w-full bg-transparent text-sm text-ink outline-none placeholder:text-faint [&::-webkit-search-cancel-button]:hidden"
      />
      {value ? (
        <button
          type="button"
          aria-label="Clear search"
          onClick={() => onChange?.("")}
          className="flex size-5 shrink-0 animate-pop-in items-center justify-center rounded-full bg-surface-muted text-muted transition-[color,transform] duration-150 hover:text-ink active:scale-90"
        >
          <X size={10} weight="bold" />
        </button>
      ) : null}
    </div>
  );
}

Exports SearchField. Peer dependencies: clsx, tailwind-merge, @phosphor-icons/react.

PreviousRatingNextSelect