71 lines
1.6 KiB
JavaScript
71 lines
1.6 KiB
JavaScript
|
|
import { forwardRef } from 'react';
|
||
|
|
import Input from './Input';
|
||
|
|
|
||
|
|
function SearchIcon() {
|
||
|
|
return (
|
||
|
|
<svg
|
||
|
|
xmlns="http://www.w3.org/2000/svg"
|
||
|
|
className="h-5 w-5"
|
||
|
|
fill="none"
|
||
|
|
viewBox="0 0 24 24"
|
||
|
|
stroke="currentColor"
|
||
|
|
>
|
||
|
|
<path
|
||
|
|
strokeLinecap="round"
|
||
|
|
strokeLinejoin="round"
|
||
|
|
strokeWidth={2}
|
||
|
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
||
|
|
/>
|
||
|
|
</svg>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
function ClearButton({ onClear }) {
|
||
|
|
return (
|
||
|
|
<button
|
||
|
|
type="button"
|
||
|
|
onClick={onClear}
|
||
|
|
aria-label="Clear search"
|
||
|
|
className="inline-flex h-6 w-6 items-center justify-center rounded-full transition-opacity hover:opacity-70"
|
||
|
|
style={{ color: 'var(--text-secondary)' }}
|
||
|
|
>
|
||
|
|
<svg
|
||
|
|
className="h-4 w-4"
|
||
|
|
fill="none"
|
||
|
|
stroke="currentColor"
|
||
|
|
viewBox="0 0 24 24"
|
||
|
|
aria-hidden="true"
|
||
|
|
>
|
||
|
|
<path
|
||
|
|
strokeLinecap="round"
|
||
|
|
strokeLinejoin="round"
|
||
|
|
strokeWidth={2}
|
||
|
|
d="M6 18L18 6M6 6l12 12"
|
||
|
|
/>
|
||
|
|
</svg>
|
||
|
|
</button>
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
const SearchBar = forwardRef(function SearchBar(
|
||
|
|
{ value, onChange, onClear, placeholder = 'Search…', className, ...rest },
|
||
|
|
ref
|
||
|
|
) {
|
||
|
|
const showClear = onClear && value && value.length > 0;
|
||
|
|
return (
|
||
|
|
<Input
|
||
|
|
ref={ref}
|
||
|
|
type="search"
|
||
|
|
value={value}
|
||
|
|
onChange={onChange}
|
||
|
|
placeholder={placeholder}
|
||
|
|
leadingIcon={<SearchIcon />}
|
||
|
|
trailingAction={showClear ? <ClearButton onClear={onClear} /> : undefined}
|
||
|
|
className={className}
|
||
|
|
{...rest}
|
||
|
|
/>
|
||
|
|
);
|
||
|
|
});
|
||
|
|
|
||
|
|
export default SearchBar;
|