SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
4 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
1.9 KB · 49 lines tsx
Raw Blame History
1"use client";23import { Search, X } from "lucide-react";4import { forwardRef, type InputHTMLAttributes, type ReactNode } from "react";5import { cn } from "./cn";67export interface SearchInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "size" | "onChange"> {8  value: string;9  onChange: (v: string) => void;10  onClear?: () => void;11  size?: "sm" | "md" | "lg";12  trailing?: ReactNode;13  wrapperClassName?: string;14  loading?: boolean;15}1617export const SearchInput = forwardRef<HTMLInputElement, SearchInputProps>(function SearchInput({ value, onChange, onClear, size = "md", trailing, className, wrapperClassName, loading, ...rest }, ref) {18  const h = size === "lg" ? "h-12 text-[15px]" : size === "sm" ? "h-10 text-[13px] sm:h-9" : "h-10 text-[14px]";19  return (20    <div className={cn("relative flex items-center rounded-sm border border-hair-2 bg-surface text-ink focus-within:border-ink", h, wrapperClassName)}>21      <Search className={cn("ml-3 shrink-0 text-ink-3", size === "lg" ? "size-[18px]" : "size-4", loading && "animate-pulse-soft")} strokeWidth={1.75} aria-hidden />22      <input23        ref={ref}24        type="search"25        value={value}26        onChange={(e) => onChange(e.target.value)}27        autoComplete="off"28        spellCheck={false}29        className={cn("h-full min-w-0 flex-1 bg-transparent px-2.5 outline-none placeholder:text-ink-4", className)}30        {...rest}31      />32      {value && (33        <button34          type="button"35          aria-label="Clear search"36          onClick={() => {37            onChange("");38            onClear?.();39          }}40          className="mr-1 inline-flex size-8 items-center justify-center rounded-xs text-ink-3 hover:text-ink"41        >42          <X className="size-4" />43        </button>44      )}45      {trailing && <div className="mr-2 flex shrink-0 items-center gap-1">{trailing}</div>}46    </div>47  );48});49