EmberClone/apps/web/src/components/Select.tsx

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;