tenantpilot/components/search/SearchInput.tsx
2025-12-05 22:06:22 +01:00

46 lines
1.4 KiB
TypeScript

'use client';
import { Input } from '@/components/ui/input';
import { Search, Loader2 } from 'lucide-react';
import { useState, useEffect } from 'react';
import { useDebounce } from 'use-debounce';
interface SearchInputProps {
onSearch: (query: string) => void;
isSearching?: boolean;
}
export function SearchInput({ onSearch, isSearching = false }: SearchInputProps) {
const [query, setQuery] = useState('');
const [debouncedQuery] = useDebounce(query, 300);
// Show typing indicator when input differs from debounced value
const isTyping = query !== debouncedQuery && query.length > 0;
useEffect(() => {
// Only trigger search when debounced value changes
if (debouncedQuery.length >= 2 || debouncedQuery.length === 0) {
onSearch(debouncedQuery);
}
}, [debouncedQuery, onSearch]);
return (
<div className="relative w-full max-w-2xl">
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<Input
type="text"
placeholder="Search policy settings... (e.g., USB, Camera, Defender)"
value={query}
onChange={(e) => setQuery(e.target.value)}
disabled={isSearching}
className="pl-10 pr-10"
/>
{(isSearching || isTyping) && (
<div className="absolute right-3 top-1/2 -translate-y-1/2">
<Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
</div>
)}
</div>
);
}