feat(form): Add clearable functionality to Select component
This commit introduces a new `clearable` prop to the `Select` component, allowing users to easily reset its value. When the `clearable` prop is set to true, a clear button (an 'X' icon) is displayed when an option is selected. Clicking this button resets the select input to its initial placeholder state and triggers an optional `onClear` callback. To support this, the component's internal state management was refactored to control the input's value. Additionally, the `AdminListFilters` component has been updated to: - Utilize the new clearable select for the status filter. - Consolidate multiple search fields (email, username, full_name) into a single generic "search" input. - Add explicit "Reset" and "Apply" buttons for better filter management.
This commit is contained in:
@@ -22,6 +22,8 @@ type PropsType<T extends FieldValues> = {
|
||||
register?: UseFormRegister<T>;
|
||||
errors?: FieldErrors<T>;
|
||||
required?: boolean;
|
||||
clearable?: boolean;
|
||||
onClear?: () => void;
|
||||
} & (
|
||||
| { placeholder?: string; defaultValue: string }
|
||||
| { placeholder: string; defaultValue?: string }
|
||||
@@ -42,13 +44,22 @@ export function Select<T extends FieldValues>({
|
||||
onChange,
|
||||
onBlur,
|
||||
ref,
|
||||
clearable = false,
|
||||
onClear,
|
||||
...props
|
||||
}: PropsType<T>) {
|
||||
const id = useId();
|
||||
|
||||
const [isOptionSelected, setIsOptionSelected] = useState(!!defaultValue);
|
||||
const [value, setValue] = useState(defaultValue || "");
|
||||
const error = errors && errors[name];
|
||||
|
||||
const handleClear = () => {
|
||||
setValue("");
|
||||
setIsOptionSelected(false);
|
||||
onClear?.();
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={cn("space-y-3", className)}>
|
||||
<label
|
||||
@@ -70,8 +81,9 @@ export function Select<T extends FieldValues>({
|
||||
id={id}
|
||||
name={name}
|
||||
ref={ref}
|
||||
defaultValue={defaultValue || ""}
|
||||
value={value}
|
||||
onChange={(e) => {
|
||||
setValue(e.target.value);
|
||||
setIsOptionSelected(!!e.target.value);
|
||||
onChange?.(e);
|
||||
}}
|
||||
@@ -81,6 +93,7 @@ export function Select<T extends FieldValues>({
|
||||
isOptionSelected && "text-dark dark:text-white",
|
||||
error && "border-red focus:border-red dark:border-red",
|
||||
prefixIcon && "pl-11.5",
|
||||
clearable && value && "pr-20",
|
||||
)}
|
||||
>
|
||||
{placeholder && (
|
||||
@@ -96,6 +109,30 @@ export function Select<T extends FieldValues>({
|
||||
))}
|
||||
</select>
|
||||
|
||||
{clearable && value && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleClear}
|
||||
className="absolute right-10 top-1/2 -translate-y-1/2 text-dark-5 hover:text-dark dark:text-dark-6 dark:hover:text-white"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M12 4L4 12M4 4L12 12"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<ChevronUpIcon className="pointer-events-none absolute right-4 top-1/2 -translate-y-1/2 rotate-180" />
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user