altarra/src/components/FormField.tsx

66 lines
1.7 KiB
TypeScript

"use client"
import { useId } from 'react'
import { AlertCircle } from 'lucide-react'
type Props = {
label: string
type?: string
value: string
onChange: (v: string) => void
placeholder?: string
required?: boolean
min?: number
max?: number
step?: number
disabled?: boolean
error?: string
}
export default function FormField({
label,
type = 'text',
value,
onChange,
placeholder,
required,
min,
max,
step,
disabled,
error
}: Props) {
const id = useId()
return (
<div className="mb-4">
<label htmlFor={id} className="mb-2 block text-sm font-semibold text-gray-900">
{label} {required ? <span className="text-[#FF0000]" aria-hidden>*</span> : null}
</label>
<input
id={id}
className={`w-full rounded-lg border-2 px-4 py-3 text-base outline-none transition-colors ${
error
? 'border-[#FF0000] bg-[#fff5f5] focus-visible:ring-2 focus-visible:ring-[#FF0000]/30'
: 'border-gray-300 focus-visible:ring-2 focus-visible:ring-[#006600]/30'
}`}
type={type}
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
required={required}
min={min}
max={max}
step={step}
disabled={disabled}
aria-invalid={!!error}
aria-describedby={error ? `${id}-error` : undefined}
/>
{error ? (
<div id={`${id}-error`} className="mt-2 flex items-center gap-2 text-sm text-[#991b1b] font-medium">
<AlertCircle className="h-4 w-4 flex-shrink-0" style={{ color: '#FF0000' }} />
{error}
</div>
) : null}
</div>
)
}