Expandable Search with Rich Results
Published Feb 19, 2024
Search experience needed to handle both document and people results, while keeping interactions smooth and intuitive. I ended up with a responsive autocomplete that highlights matched terms and groups results by type, with keyboard navigation that feels natural whether you're searching through documents or contacts.
Implementation Details
"use client";
import { useState } from "react";
import { Search, User, File } from "lucide-react";
import { cn } from "@/lib/cn";
export default function SearchInterface() {
const [query, setQuery] = useState("");
const [selectedIndex, setSelectedIndex] = useState(0);
return (
<div className="w-full max-w-md mx-auto">
<div className="relative">
<input
type="text"
placeholder="Start typing..."
className="w-full px-10 py-2 rounded-full border border-gray-200 dark:border-gray-700 focus:outline-none focus:ring-2"
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
<Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
{query && (
<button
className="absolute right-3 top-1/2 -translate-y-1/2 text-sm text-gray-400"
onClick={() => setQuery("")}
>
Clear
</button>
)}
</div>
{query && (
<div className="mt-1 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 overflow-hidden">
<div className="p-2">
<div className="text-sm text-gray-500 dark:text-gray-400 mb-2">Documents</div>
<SearchResults type="documents" query={query} selectedIndex={selectedIndex} />
<div className="text-sm text-gray-500 dark:text-gray-400 mt-4 mb-2">People</div>
<SearchResults type="people" query={query} selectedIndex={selectedIndex} />
</div>
</div>
)}
</div>
);
}