kontenhumas-fe/components/auth/form-field.tsx

93 lines
2.4 KiB
TypeScript

"use client";
import React from "react";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { cn } from "@/lib/utils";
import { Eye, EyeOff } from "lucide-react";
interface FormFieldProps {
label: string;
name: string;
type?: "text" | "email" | "password" | "tel" | "number";
placeholder?: string;
error?: string;
disabled?: boolean;
required?: boolean;
className?: string;
inputProps?: React.ComponentProps<typeof Input>;
showPasswordToggle?: boolean;
onPasswordToggle?: () => void;
showPassword?: boolean;
}
export const FormField: React.FC<FormFieldProps> = ({
label,
name,
type = "text",
placeholder,
error,
disabled = false,
required = false,
className,
inputProps,
showPasswordToggle = false,
onPasswordToggle,
showPassword = false,
}) => {
const inputType = showPasswordToggle && type === "password"
? (showPassword ? "text" : "password")
: type;
return (
<div className={cn("space-y-2", className)}>
<Label
htmlFor={name}
className="font-medium text-default-600"
>
{label}
{required && <span className="text-red-500 ml-1">*</span>}
</Label>
<div className="relative">
<Input
id={name}
name={name}
type={inputType}
placeholder={placeholder}
disabled={disabled}
className={cn(
"peer",
{
"border-destructive": error,
"pr-10": showPasswordToggle,
},
inputProps?.className
)}
aria-invalid={!!error}
aria-describedby={error ? `${name}-error` : undefined}
{...inputProps}
/>
{showPasswordToggle && (
<button
type="button"
onClick={onPasswordToggle}
className="absolute right-3 top-1/2 -translate-y-1/2 text-default-500 hover:text-default-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 rounded"
tabIndex={-1}
aria-label={showPassword ? "Hide password" : "Show password"}
>
{showPassword ? <EyeOff size={18} /> : <Eye size={18} />}
</button>
)}
</div>
{error && (
<div
id={`${name}-error`}
className="text-destructive mt-2 text-sm"
role="alert"
>
{error}
</div>
)}
</div>
);
};