Files
workshop-manager/src/components/ui/Select.tsx
Julien Froidefond 5f661c8bfd
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 12m53s
feat: introduce Teams & OKRs feature with models, types, and UI components for team management and objective tracking
2026-01-07 10:11:59 +01:00

72 lines
2.2 KiB
TypeScript

import { forwardRef, SelectHTMLAttributes } from 'react';
interface SelectOption {
value: string;
label: string;
disabled?: boolean;
}
interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'children'> {
label?: string;
error?: string;
options: SelectOption[];
placeholder?: string;
}
export const Select = forwardRef<HTMLSelectElement, SelectProps>(
({ className = '', label, error, id, options, placeholder, ...props }, ref) => {
const selectId = id || props.name;
return (
<div className="w-full">
{label && (
<label htmlFor={selectId} className="mb-2 block text-sm font-medium text-foreground">
{label}
</label>
)}
<div className="relative">
<select
ref={ref}
id={selectId}
className={`
w-full appearance-none rounded-lg border bg-input px-4 py-2.5 pr-10 text-foreground
placeholder:text-muted-foreground
focus:outline-none focus:ring-2 focus:ring-primary/20
disabled:cursor-not-allowed disabled:opacity-50
${error ? 'border-destructive focus:border-destructive' : 'border-input-border focus:border-primary'}
${className}
`}
{...props}
>
{placeholder && (
<option value="" disabled={props.required}>
{placeholder}
</option>
)}
{options.map((option) => (
<option key={option.value} value={option.value} disabled={option.disabled}>
{option.label}
</option>
))}
</select>
{/* Custom arrow icon */}
<div className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2">
<svg
className="h-5 w-5 text-muted-foreground"
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</div>
</div>
{error && <p className="mt-1.5 text-sm text-destructive">{error}</p>}
</div>
);
}
);
Select.displayName = 'Select';