auto-claude: subtask-1-1 - Add character counter state and logic to ContactForm

- Added MAX_MESSAGE_LENGTH constant (1000 characters)
- Added messageLength calculation from formData.message
- Implemented character counter display below message textarea
- Added color feedback: red (over limit), yellow (80%+), gray (normal)
- Counter updates in real-time as user types

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-25 06:31:18 +01:00
co-authored by Claude Sonnet 4.5
parent eec1758827
commit a46b4f61fe
+17
View File
@@ -15,6 +15,8 @@ interface FormData {
export function ContactForm() { export function ContactForm() {
const t = useTranslations('pages.contact'); const t = useTranslations('pages.contact');
const MAX_MESSAGE_LENGTH = 1000;
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle'); const [submitStatus, setSubmitStatus] = useState<'idle' | 'success' | 'error'>('idle');
const [formData, setFormData] = useState<FormData>({ const [formData, setFormData] = useState<FormData>({
@@ -24,6 +26,8 @@ export function ContactForm() {
}); });
const [errors, setErrors] = useState<Partial<FormData>>({}); const [errors, setErrors] = useState<Partial<FormData>>({});
const messageLength = formData.message.length;
const validateForm = () => { const validateForm = () => {
const newErrors: Partial<FormData> = {}; const newErrors: Partial<FormData> = {};
@@ -276,6 +280,19 @@ export function ContactForm() {
{errors.message && ( {errors.message && (
<p className="text-sm text-red-400">{errors.message}</p> <p className="text-sm text-red-400">{errors.message}</p>
)} )}
<div className="flex justify-end">
<p
className={`text-xs transition-colors ${
messageLength > MAX_MESSAGE_LENGTH
? 'text-red-500'
: messageLength >= MAX_MESSAGE_LENGTH * 0.8
? 'text-yellow-500'
: 'text-zinc-500'
}`}
>
{messageLength} / {MAX_MESSAGE_LENGTH} characters
</p>
</div>
</div> </div>
</div> </div>