Files
resolutionflow/frontend/src/components/admin/SearchInput.tsx
chihlasm f4ce1595d6 feat: implement monochrome design system across entire frontend
Migrate all 84 frontend files from the old themed/colored design to a
monochrome glass-morphism design system. Pure black backgrounds, white
text with opacity levels, glass-card components with backdrop-blur, and
functional color reserved for status indicators only.

Foundation: remap CSS variables to monochrome, simplify Tailwind config,
remove theme toggle, convert brand logo/wordmark to white. Pages: all
14 pages updated. Components: all common, library, session, step-library,
tree-editor, tree-preview, admin, and subscription components converted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 21:41:29 -05:00

67 lines
1.8 KiB
TypeScript

import { useState, useEffect, useRef, useCallback } from 'react'
import { Search, X } from 'lucide-react'
import { debounce } from 'lodash'
import { cn } from '@/lib/utils'
interface SearchInputProps {
value?: string
onSearch: (value: string) => void
placeholder?: string
className?: string
}
export function SearchInput({ value = '', onSearch, placeholder = 'Search...', className }: SearchInputProps) {
const [localValue, setLocalValue] = useState(value)
const debouncedRef = useRef<ReturnType<typeof debounce> | null>(null)
useEffect(() => {
setLocalValue(value)
}, [value])
useEffect(() => {
debouncedRef.current = debounce((v: string) => {
onSearch(v)
}, 300)
return () => {
debouncedRef.current?.cancel()
}
}, [onSearch])
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
const v = e.target.value
setLocalValue(v)
debouncedRef.current?.(v)
}, [])
const handleClear = () => {
setLocalValue('')
onSearch('')
}
return (
<div className={cn('relative', className)}>
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-white/50" />
<input
type="text"
value={localValue}
onChange={handleChange}
placeholder={placeholder}
className={cn(
'h-9 w-full rounded-md border border-white/10 bg-black/50 pl-9 pr-8 text-sm text-white',
'placeholder:text-white/40 focus:outline-none focus:border-white/30 focus:ring-2 focus:ring-white/20'
)}
/>
{localValue && (
<button
onClick={handleClear}
className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-white/50 hover:text-white"
>
<X className="h-3.5 w-3.5" />
</button>
)}
</div>
)
}
export default SearchInput