Files
klz-cables.com/components/forms/FormError.tsx
2025-12-29 18:18:48 +01:00

89 lines
2.2 KiB
TypeScript

import React from 'react';
import { cn } from '@/lib/utils';
/**
* FormError Component
* Display error messages with different variants and animations
*/
export interface FormErrorProps {
errors?: string | string[];
variant?: 'inline' | 'block' | 'toast';
className?: string;
showIcon?: boolean;
animate?: boolean;
id?: string;
}
export const FormError: React.FC<FormErrorProps> = ({
errors,
variant = 'inline',
className,
showIcon = true,
animate = true,
id,
}) => {
if (!errors || (Array.isArray(errors) && errors.length === 0)) {
return null;
}
const errorArray = Array.isArray(errors) ? errors : [errors];
const hasMultipleErrors = errorArray.length > 1;
const baseClasses = {
inline: 'text-sm text-danger mt-1',
block: 'p-3 bg-danger/10 border border-danger/20 rounded-md text-danger text-sm',
toast: 'fixed bottom-4 right-4 p-4 bg-danger text-white rounded-lg shadow-lg max-w-md z-tooltip animate-slide-up',
};
const animationClasses = animate ? 'animate-fade-in' : '';
const Icon = () => (
<svg
className="w-4 h-4 mr-1 inline-block"
fill="currentColor"
viewBox="0 0 20 20"
aria-hidden="true"
>
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
clipRule="evenodd"
/>
</svg>
);
return (
<div
role="alert"
aria-live="polite"
id={id}
className={cn(
baseClasses[variant],
animationClasses,
'transition-all duration-200',
className
)}
>
{hasMultipleErrors ? (
<ul className="list-disc list-inside space-y-1">
{errorArray.map((error, index) => (
<li key={index} className="flex items-start">
{showIcon && <Icon />}
<span>{error}</span>
</li>
))}
</ul>
) : (
<div className="flex items-start">
{showIcon && <Icon />}
<span>{errorArray[0]}</span>
</div>
)}
</div>
);
};
FormError.displayName = 'FormError';
export default FormError;