ACCESSIBLE Form with React, Typescript, Zod, react-hook-form, SCSS
Design comparison
Solution retrospective
Any feedback is welcome! Especially on accessibility.
Community feedback
- @grace-snowPosted 2 months ago
A few things I notice
- personal data fields must have autocomplete attributes.
- you can use required instead of aria-required.
- the errors should be wrapped in an element that's always in the dom and has an aria-live attribute set to "assertive". That's where the error id should go that's referenced in the aria-desciribedby too. Then you conditionally render the error message inside when needed.
- query type is the legend. You must remove the sr-only legend in this. They are actually breaking the accessibility of this.
- the message does not belong in a fieldset. It's a single form field with a label that's all. Again, the fieldset and legend are making that inaccessible not accessible.
- not accessibility related but input names shouldn't include spaces (including on the button but that actually doesn't need a name attribute at all).
- role alert and aria live should be removed from the errors. You wouldn't ever put both of them on one element as they have related functionality.
Marked as helpful1@dev-paulLPosted 2 months ago@grace-snow Thank you so much! I’ve made those changes in the recent commit 🫡. Do you recommend a particular screen reader? I’m currently using Mr. Narrator on Windows, but it’s new to me, and I find it challenging to understand the expectations of visually impaired users.
btw, I’m constantly learning from what you post and share on Discord about accessibility, it’s really interesting!
0@grace-snowPosted 2 months ago@dev-paulL use NVDA on windows. It's by far the most popular.
1@dev-paulLPosted 2 months ago@grace-snow I'm using NVDA now, and it's way better than the Windows Narrator. After testing, I made a few more changes:
- Added back "aria-required" because it works the same for screen readers and doesn't mess with the errors defined in the Zod schema.
- Set the toast message to show for 5 seconds instead of 3, and added
aria-role="alert"
to it. - Changed the error message from "This field is required" to more specific ones like "First name is required," "Last name is required," etc..
(I completed the form multiple times with my eyes closed)
0@grace-snowPosted 2 months ago@dev-paulL that sounds great, well done! I hadn't actually realised it included a toast notification as I only had a quick look through the code. It sounds good what you've done.
1@grace-snowPosted 2 months agoI just tried it out and on mobile I didn't see the toast as I was at the bottom of the screen. Make sure it scrolls into view or something.
It also looked like it was stacked underneath the form content when I briefly saw it after scrolling so check it can definitely be seen on small screens.
A toast that appears then disappears fast would probably fail on the Timing Adjustable WCAG success criterion too. So it may be better to use a dialog, move focus to it (or to a close button within it), include a close button and let it persist until closed. That would allow people to definitely see it, have enough time to read and intentionally dismiss. Much better than something that appears and potentially disappears before they had time to see it.
Marked as helpful0 - @TedJenklerPosted 2 months ago
Hi again @dev-paulL,
Nice project! Here are some suggestions to further enhance your work:
Custom Checkboxes and Radio Buttons: Consider creating custom checkboxes and radio buttons to better align with your design. This will also give you an opportunity to explore ARIA roles and attributes for custom components, rather than relying on the default native ones.
Validation: Instead of using the required attribute—which can sometimes produce an unsightly default validation message ( The default required mail one so ugly)—use JavaScript validation (such as Zod) for a more polished and visually appealing user experience(Like you have done already*, try hit only g in email and you see what i mean).
Component Question: I’m curious about the IconSuccessCheck.tsx component. What is it for i suspect its something react form hooks related(glad i chosen formik haha)
Modular SCSS: For improved code management, even in smaller projects, consider adopting a modular approach with SCSS. Organize your styles into a styles folder with files like main.scss and _variables.scss. This can enhance maintainability and make your code easier to navigate. (Arguably not needed because of the size of the form/project but think its good practice and makes some really fast edits/refactors)
Keep up the great work!
Best, Teodor
1@dev-paulLPosted 2 months ago@TedJenkler Hey, thanks for the feedback! I haven't had time to add Grace's latest suggestions or the custom checkbox and radio buttons yet. Good call on the email validation; it’s not from the required attribute like you mentioned, but from type="email" (like I said earlier, I’m using aria-required to avoid issues with Zod). I just forgot to remove that line after testing with NVDA.
The IconSuccessCheck component is just an SVG icon for the toast.
This project’s pretty small (only 200 lines of SCSS), so I don’t think it needs a modular approach, but definitely a good idea for bigger projects.
1 - @Git-ElimmanPosted 2 months ago
Please I'm still very new to javascript and I've been stuck with this challenge for a long time now, I need help.
https://github.com/Git-Elimman/Contact-Form
0
Please log in to post a comment
Log in with GitHubJoin our Discord community
Join thousands of Frontend Mentor community members taking the challenges, sharing resources, helping each other, and chatting about all things front-end!
Join our Discord