mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
68 lines
1.6 KiB
TypeScript
68 lines
1.6 KiB
TypeScript
import React from 'react';
|
|
import { clsx } from 'clsx';
|
|
|
|
export interface FormFieldProps {
|
|
label?: string;
|
|
description?: string;
|
|
error?: string;
|
|
required?: boolean;
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
labelClassName?: string;
|
|
errorClassName?: string;
|
|
}
|
|
|
|
/**
|
|
* Form field wrapper with label, description, and error
|
|
*/
|
|
export const FormField = ({
|
|
label,
|
|
description,
|
|
error,
|
|
required,
|
|
children,
|
|
className,
|
|
labelClassName,
|
|
errorClassName,
|
|
}: FormFieldProps) => {
|
|
const fieldId = React.useId();
|
|
|
|
return (
|
|
<div className={clsx('flex flex-col gap-2', className)}>
|
|
{label && (
|
|
<label
|
|
htmlFor={fieldId}
|
|
className={clsx(
|
|
'text-sm font-medium text-foreground',
|
|
{
|
|
"after:content-['*'] after:ml-1 after:text-destructive": required,
|
|
},
|
|
labelClassName
|
|
)}
|
|
>
|
|
{label}
|
|
</label>
|
|
)}
|
|
{description && <p className="text-xs text-muted-foreground">{description}</p>}
|
|
<div>
|
|
{React.isValidElement(children)
|
|
? React.cloneElement(children as React.ReactElement, {
|
|
id: fieldId,
|
|
'aria-invalid': error ? 'true' : 'false',
|
|
'aria-describedby': error ? `${fieldId}-error` : undefined,
|
|
})
|
|
: children}
|
|
</div>
|
|
{error && (
|
|
<p
|
|
id={`${fieldId}-error`}
|
|
className={clsx('text-sm text-destructive', errorClassName)}
|
|
role="alert"
|
|
>
|
|
{error}
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|