dramaling-vocab-learning/frontend/components/shared/ValidatedTextInput.tsx

69 lines
1.9 KiB
TypeScript

import React from 'react'
interface ValidatedTextInputProps {
value: string
onChange: (value: string) => void
maxLength: number
placeholder: string
rows?: number
className?: string
showCounter?: boolean
warningThreshold?: number
errorThreshold?: number
}
export const ValidatedTextInput: React.FC<ValidatedTextInputProps> = ({
value,
onChange,
maxLength,
placeholder,
rows = 4,
className = '',
showCounter = true,
warningThreshold = 0.8,
errorThreshold = 0.95
}) => {
const currentLength = value.length
const isNearLimit = currentLength >= maxLength * warningThreshold
const isAtLimit = currentLength >= maxLength * errorThreshold
const getBorderColor = () => {
if (isAtLimit) return 'border-red-300 focus:ring-red-500'
if (isNearLimit) return 'border-yellow-300 focus:ring-yellow-500'
return 'border-gray-300 focus:ring-blue-500'
}
const getCounterColor = () => {
if (isAtLimit) return 'text-red-600'
if (isNearLimit) return 'text-yellow-600'
return 'text-gray-500'
}
return (
<div className={`relative ${className}`}>
<textarea
value={value}
onChange={(e) => onChange(e.target.value)}
placeholder={placeholder}
rows={rows}
maxLength={maxLength}
className={`w-full p-4 rounded-lg focus:ring-2 focus:outline-none transition-colors resize-none ${getBorderColor()}`}
/>
{showCounter && (
<div className={`absolute bottom-2 right-2 text-sm ${getCounterColor()}`}>
{currentLength}/{maxLength}
</div>
)}
{isAtLimit && (
<div className="mt-1 text-sm text-red-600">
</div>
)}
{isNearLimit && !isAtLimit && (
<div className="mt-1 text-sm text-yellow-600">
</div>
)}
</div>
)
}