Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x | 'use client';
import { ChangeEvent, InputHTMLAttributes, KeyboardEvent, useState } from 'react';
import { Icon } from '@/components/icon';
import { Input } from '@/components/ui';
import { cn } from '@/lib/utils';
interface SearchBarProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange'> {
onSearch?: (value: string) => void;
onChange?: (value: string) => void;
value?: string;
defaultValue?: string;
}
export const SearchBar = ({
className,
placeholder = '검색어를 입력하세요',
onSearch,
onChange,
value,
defaultValue = '',
...props
}: SearchBarProps) => {
const isControlled = value !== undefined;
const [innerValue, setInnerValue] = useState(defaultValue);
const currentValue = isControlled ? value : innerValue;
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value;
if (!isControlled) {
setInnerValue(newValue);
}
onChange?.(newValue);
};
const handleSearch = () => {
onSearch?.(currentValue ?? '');
// 추가 동작 추천?
// 검색 실행 전 공백 제거 로직
};
const handleKeyDown = (event: KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
handleSearch();
}
};
return (
<Input
className={cn(
'focus:border-mint-500 rounded-3xl border border-transparent bg-gray-100',
className,
)}
iconButton={
<button
className='absolute top-1/2 right-5 h-6 w-6 -translate-y-1/2'
aria-label='검색 실행'
type='button'
onClick={handleSearch}
>
<Icon id='search' className='text-mint-600' />
</button>
}
placeholder={placeholder}
value={currentValue}
onChange={handleChange}
onKeyDown={handleKeyDown}
{...props}
/>
);
};
|