polish(contact): zod validation, persistent success/error, fallback email#22
Open
f1shyfang wants to merge 1 commit into
Open
polish(contact): zod validation, persistent success/error, fallback email#22f1shyfang wants to merge 1 commit into
f1shyfang wants to merge 1 commit into
Conversation
…or, fallback email
This is one of two surfaces (with /sponsors) where industry contacts
decide whether to reach out. The form was missing real validation
(browser-default messages on submit only), missing autoComplete (bad
mobile UX), and auto-dismissed success/error after 5s so a sponsor
who looked away missed confirmation.
Form rebuilt with react-hook-form + zod (existing deps; no new
dependencies). Validation runs onBlur with onChange re-validation,
producing plain-language messages with concrete fix guidance
("That email looks incomplete. Check for an @ and a domain.").
Each field gets: top label with htmlFor/id, autoComplete (name,
email), inputMode="email" on email, aria-required, aria-invalid,
aria-describedby pointing at error OR a calm helper line setting
expectations.
Submit button: bg-[#1B397E] (was bg-blue-600), full-width on mobile,
aria-busy when sending, label flips to "Sending..." with disabled
state. Focus-visible ring with token-aligned blue-600/25 tint.
Success state now replaces the form with a friendly confirmation,
restates reply-time SLA ("3 to 4 days during term"), surfaces a
fallback email address, and offers "Send another message" + ghost
"Email us instead" CTAs. Server-error path uses role="alert", does
not auto-dismiss, points to fallback email with plain-language fix
guidance.
Layout switched from 50/50 columns to lg:grid-cols-5 with form
lg:col-span-3 / info lg:col-span-2, giving the form proper weight.
Tokens corrected throughout: text-gray-900 with tracking-tight for
headings; text-gray-700 body; text-gray-600 helpers; hairline
border-gray-200; rounded-md inputs with px-4 py-3.
Required-field legend with hidden screen-reader text. Icons get
aria-hidden and recolour from text-blue-500 to text-[#1B397E]. Map
iframe title made descriptive. Buzzword copy ("We'd love to hear
from you", "ready to answer all your questions") replaced.
tsc --noEmit: clean. eslint: clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Pull request overview
Polish pass on the /contact surface by improving form UX/accessibility and making submit feedback (success/error) persistent, while aligning layout and styling with current design tokens.
Changes:
- Updated
/contactmetadata title/description to be more specific and include response-time expectations. - Rebuilt the contact form UI with
react-hook-form+zodvalidation and improved a11y attributes/helper text. - Reworked submit states so success and error messaging persist and include a fallback email CTA.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
CEUS/src/app/contact/page.tsx |
Updates contact page metadata (title/description). |
CEUS/src/app/contact/ContactClient.tsx |
Replaces the contact form implementation with RHF+Zod validation, persistent success/error states, and refreshed layout/styling/a11y. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+74
to
+76
| setServerErrorMessage( | ||
| 'Something went wrong on our end. Please try again in a moment, or email us directly.' | ||
| ); |
Comment on lines
+8
to
+9
| description: | ||
| 'Get in touch with the Chemical Engineering Undergraduate Society at UNSW. Send us a message about events, merch, or sponsorship and we will reply within 3 to 4 days during term.', |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Polish pass on
/contact. Critique score moved from 17/40 → 34/40. This is one of two surfaces (with/sponsors) where prospective industry contacts decide whether to reach out — form UX matters disproportionately here.Validation & errors
react-hook-form+zod(existing deps; no new dependencies).onBlurwithonChangere-validation.Inputs
htmlFor/id,autoComplete(name, email),inputMode="email",aria-required,aria-invalid,aria-describedbylinking to either the error or a calm helper line.rounded-md,border-gray-200,px-4 py-3, focus borderblue-600withring-3 ring-blue-600/25.Submit & state
bg-[#1B397E](wasbg-blue-600), full-width on mobile,aria-busywhen sending, label flips to "Sending..." withdisabled.role="alert", does not auto-dismiss, points to fallback email with plain-language fix guidance.Layout & tokens
lg:grid-cols-5with formlg:col-span-3/ infolg:col-span-2— gives the form proper weight.text-gray-900+tracking-tight; bodytext-gray-700; helperstext-gray-600; hairlineborder-gray-200.aria-hidden, recoloured to Brand Navy.Test plan
npm run dev→/contact— verify form layout works at mobile and desktopautoCompletefills name/email from saved dataOpen questions for the team
ceus@unsw.edu.auactually monitored, or is there a sponsorship-specific alias?Verification
tsc --noEmit: cleaneslint: cleanMerge note
Independently mergeable. Touches only
CEUS/src/app/contact/page.tsxandContactClient.tsx.🤖 Generated with Claude Code