85 lines
2.2 KiB
TypeScript
85 lines
2.2 KiB
TypeScript
import React from 'react';
|
|
import { ChevronDown } from 'lucide-react';
|
|
|
|
export interface SelectOption {
|
|
value: string;
|
|
label: string;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
interface SelectProps {
|
|
value: string;
|
|
onChange: (value: string) => void;
|
|
options: SelectOption[];
|
|
label?: string;
|
|
placeholder?: string;
|
|
error?: string;
|
|
disabled?: boolean;
|
|
name?: string;
|
|
}
|
|
|
|
const Select: React.FC<SelectProps> = ({
|
|
value,
|
|
onChange,
|
|
options,
|
|
label,
|
|
placeholder,
|
|
error,
|
|
disabled = false,
|
|
name,
|
|
}) => {
|
|
return (
|
|
<div className="flex flex-col gap-1.5 w-full">
|
|
{label && (
|
|
<label
|
|
htmlFor={name}
|
|
className="text-sm font-medium text-slate-700 dark:text-slate-300"
|
|
>
|
|
{label}
|
|
</label>
|
|
)}
|
|
|
|
<div className="relative">
|
|
<select
|
|
id={name}
|
|
name={name}
|
|
value={value}
|
|
onChange={(e) => onChange(e.target.value)}
|
|
disabled={disabled}
|
|
className={`
|
|
w-full appearance-none rounded-md border bg-white px-3 py-2 text-sm transition-colors
|
|
focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:bg-slate-900 dark:text-slate-100
|
|
${error
|
|
? 'border-red-500 focus:ring-red-500 dark:border-red-500'
|
|
: 'border-slate-300 dark:border-slate-700 focus:border-indigo-500'
|
|
}
|
|
${disabled ? 'opacity-50 cursor-not-allowed bg-slate-100 dark:bg-slate-800' : 'cursor-pointer'}
|
|
`}
|
|
>
|
|
{placeholder && (
|
|
<option value="" disabled>
|
|
{placeholder}
|
|
</option>
|
|
)}
|
|
{options.map((opt) => (
|
|
<option key={opt.value} value={opt.value} disabled={opt.disabled}>
|
|
{opt.label}
|
|
</option>
|
|
))}
|
|
</select>
|
|
|
|
<div className="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-slate-500 dark:text-slate-400">
|
|
<ChevronDown className="h-4 w-4" />
|
|
</div>
|
|
</div>
|
|
|
|
{error && (
|
|
<span className="text-xs text-red-500 dark:text-red-400">
|
|
{error}
|
|
</span>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Select; |