[Sprint 10] feat: Add contact form validation and UX polish #94

Open
opened 2026-02-01 18:18:24 +00:00 by lmiranda · 0 comments
Owner

Overview

Add client-side validation, required field indicators, and form clearing after successful submission.

Files to Modify

  • portfolio_app/pages/contact.py
  • portfolio_app/callbacks/contact.py

Acceptance Criteria

  • Required fields marked with asterisk (Name, Email, Message)
  • Email field validates format before submission
  • Error feedback shown for validation failures
  • Form fields clear after successful submission
  • Submit button disabled while loading
  • End-to-end test: form submits successfully to Formspree

Technical Notes

  • Use DMC's required=True and error props for validation feedback
  • Email validation: basic regex or use email-validator library
  • Reset form by returning empty strings to component values
  • Test with real Formspree endpoint to verify integration

Labels

type/enhancement scope/frontend priority/medium size/S

Dependencies

Depends on Issue #93 (callback must exist first)

## Overview Add client-side validation, required field indicators, and form clearing after successful submission. ## Files to Modify - `portfolio_app/pages/contact.py` - `portfolio_app/callbacks/contact.py` ## Acceptance Criteria - [ ] Required fields marked with asterisk (Name, Email, Message) - [ ] Email field validates format before submission - [ ] Error feedback shown for validation failures - [ ] Form fields clear after successful submission - [ ] Submit button disabled while loading - [ ] End-to-end test: form submits successfully to Formspree ## Technical Notes - Use DMC's `required=True` and `error` props for validation feedback - Email validation: basic regex or use email-validator library - Reset form by returning empty strings to component values - Test with real Formspree endpoint to verify integration ## Labels `type/enhancement` `scope/frontend` `priority/medium` `size/S` ## Dependencies Depends on Issue #93 (callback must exist first)
Sign in to join this conversation.