Adam Shelley

Web Developer

Back

React
Motion
Tailwind

Search Bar

A minimal, opinionated search bar component. Built with React, Motion, and Tailwind CSS.


Overview

5 suggestions available.

My main goal with this component was to create a search bar that is both easy to use, and satisfying in terms of animations and UX.

Currently this is a copy-paste component rather than an installable package.


Installation

  1. Install the dependencies

NPM

npm install motion tailwind tailwindmerge clsx

Bun

bun add motion tailwind tailwindmerge clsx
  1. Add the util file for tailwind merge @/utils/cn.ts
import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge"

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}
  1. Copy the source code into your project @/components/searchbar.tsx
"use client";

import * as React from "react";
import { useState, useRef, useEffect, useCallback } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { cn } from "@/lib/utils";
import { useTheme } from "next-themes";

// -------------------- Types --------------------

export interface Option {
  id: number;
  label: string;
}

export interface SearchBarProps {
  dropdownOptions?: Option[];
  maxSuggestions?: number;
  placeholder?: string;
  onSelect?: (selectedOption: Option) => void;
  onChange?: (inputValue: string) => void;
  disabled?: boolean;
  minimizable?: boolean;
  showClearButton?: boolean;
  clearButtonStyleClass?: string;
  clearOnSelect?: boolean;
  noResultsMessage?: string;
  filterDebounceTime?: number;
  renderItem?: (item: Option, isSelected: boolean) => React.ReactNode;
  highlightMatches?: boolean;
  highlightMatchesStyles?: string;
  customLoader?: React.ReactNode;
  width?: string;
  height?: string;
  darkMode?: boolean;
}

// ... rest of component

Usage

Basic

import { SearchBar } from "@/components/ui/searchbar";

<SearchBar
  dropdownOptions={[
    { id: 4, label: "Apple" },
    { id: 5, label: "Banana" },
    { id: 6, label: "Orange" },
    { id: 7, label: "Pineapple" },
  ]}
/>

Props

  • dropdownOptions { id: number, label: string }[] — The list of items to search through
  • placeholder string — Input placeholder text (default: "Search...")
  • maxSuggestions number — Max number of suggestions to show (default: 5)
  • highlightMatches boolean — Highlight matching characters in results (default: false)
  • highlightMatchesStyles string — Custom class for highlighted match text
  • minimizable boolean — Allow the search bar to be collapsed (default: false)
  • showClearButton boolean — Show a clear button when input has a value
  • clearOnSelect boolean — Clear the input after selecting a suggestion
  • noResultsMessage string — Message shown when no results match
  • filterDebounceTime number — Debounce delay for filtering in ms (default: 100)
  • disabled boolean — Disable the input
  • darkMode boolean — Override dark mode detection
  • width string — Width of the search bar (default: "400px")
  • height string — Height of the search bar (default: "48px")
  • renderItem (item, isSelected) => ReactNode — Custom renderer for dropdown items
  • onSelect (item) => void — Callback fired when an item is selected
  • onChange (value) => void — Callback fired on input change
  • customLoader ReactNode — Custom loading element shown in the dropdown