Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling form validation errors in a more accessible way #1535

Closed
dwhly opened this issue Apr 18, 2024 · 1 comment · Fixed by hypothesis/frontend-shared#1534
Closed

Handling form validation errors in a more accessible way #1535

dwhly opened this issue Apr 18, 2024 · 1 comment · Fixed by hypothesis/frontend-shared#1534
Assignees

Comments

@dwhly
Copy link
Member

dwhly commented Apr 18, 2024

The final VPAT item (3.3.1) which is about how we handle form validation errors, needs another review from us to see if we can resolve the issue they flagged without causing the problems that Alejandro identified in hypothesis/lms#6040. This will come up with other UI in future, so it is worth understanding generally how to solve it.

For reference:
Adding the alert role to the error message causes assistive technologies to announce the error twice when the text input is focused. Some accessibility guides recommend not using this as long as this issue remains. The text input is marked as invalid, so assistive technologies announce the error anyway.The notes at https://github.com/hypothesis/lms/pull/6042 and https://github.com/hypothesis/lms/pull/6040#issuecomment-1935946769 explain our approach.

I think the crux of the issue here is that if one enters invalid data and presses the submit button, nothing happens for non-sighted users. No announcement is made and one has to navigate back into the form to find that there’s an error. I understand the desire to avoid duplicate announcements, but the issue here is the lack of immediate feedback to non-sighted users when an error occurs, which forces the user to have to search through the page to discover that a) an error has occurred; and b) what the error is.

robertknight added a commit to hypothesis/lms that referenced this issue Apr 23, 2024
Revise how validation for the URL input works so that:

 - Validation errors due to the `required` property on the input and the custom
   URL validation are handled the same way. Previously a native form validation
   error would be presented if `required` was missing and a custom error was
   shown for invalid URLs.

 - Pressing the "Submit" button focuses the first input field with an error

 - Validation issues with the input field are shown when changes are committed
   (eg. when the field is blurred), not just when it loses focus.

This is done by:

 - Integrating custom constraint validation errors with the native validation
   API, so we can use `HTMLFormElement.checkValidity` at the point of submission

 - Doing validation in the "change" event of the input, instead of the form's
   "submit" event. Note that when the user commits and submits at the same time
   by pressing enter when the input has focus, the layout effect that sets
   the validity runs before the "submit" event.

 - Setting `noValidate` on the form to disable the browser's own UI messages.
   This disables both the UI message but also the behavior of focusing the
   first input with an error, which we want to keep.

 - Re-implementing the behavior of focusing the first field with an error
   ourselves.

All the above aligns with how eg. React Aria handles communicating validation
state to the browser while displaying a custom message. See
https://react-spectrum.adobe.com/react-aria/forms.html.

Part of hypothesis/product-backlog#1535
robertknight added a commit to hypothesis/lms that referenced this issue Apr 23, 2024
Revise how validation for the URL input works so that:

 - Validation errors due to the `required` property on the input and the custom
   URL validation are handled the same way. Previously a native form validation
   error would be presented if `required` was missing and a custom error was
   shown for invalid URLs.

 - Pressing the "Submit" button focuses the first input field with an error

 - Validation issues with the input field are shown when changes are committed
   (eg. when the field is blurred), not just when it loses focus.

This is done by:

 - Integrating custom constraint validation errors with the native validation
   API, so we can use `HTMLFormElement.checkValidity` at the point of submission

 - Doing validation in the "change" event of the input, instead of the form's
   "submit" event. Note that when the user commits and submits at the same time
   by pressing enter when the input has focus, the layout effect that sets
   the validity runs before the "submit" event.

 - Setting `noValidate` on the form to disable the browser's own UI messages.
   This disables both the UI message but also the behavior of focusing the
   first input with an error, which we want to keep.

 - Re-implementing the behavior of focusing the first field with an error
   ourselves.

All the above aligns with how eg. React Aria handles communicating validation
state to the browser while displaying a custom message. See
https://react-spectrum.adobe.com/react-aria/forms.html.

Part of hypothesis/product-backlog#1535
robertknight added a commit to hypothesis/lms that referenced this issue Apr 26, 2024
Revise how validation for the URL input works so that:

 - Validation errors due to the `required` property on the input and the custom
   URL validation are handled the same way. Previously a native form validation
   error would be presented if `required` was missing and a custom error was
   shown for invalid URLs.

 - Pressing the "Submit" button focuses the first input field with an error

 - Validation issues with the input field are shown when changes are committed
   (eg. when the field is blurred), not just when it loses focus.

This is done by:

 - Integrating custom constraint validation errors with the native validation
   API, by using the `Input.error` prop.

 - Doing validation in the "change" event of the input, instead of the form's
   "submit" event. Note that when the user commits and submits at the same time
   by pressing enter when the input has focus, the layout effect that sets
   the validity runs before the "submit" event.

 - Setting `noValidate` on the form to disable the browser's own UI messages.
   This disables both the UI message but also the behavior of focusing the
   first input with an error, which we want to keep.

 - Use the `useValidateOnSubmit` hook to focus the first field with an
   error on submission.

All the above aligns with how eg. React Aria handles communicating validation
state to the browser while displaying a custom message. See
https://react-spectrum.adobe.com/react-aria/forms.html.

Part of hypothesis/product-backlog#1535
@robertknight robertknight self-assigned this Apr 29, 2024
robertknight added a commit to hypothesis/lms that referenced this issue Apr 29, 2024
Revise how validation for the URL input works so that:

 - Validation errors due to the `required` property on the input and the custom
   URL validation are handled the same way. Previously a native form validation
   error would be presented if `required` was missing and a custom error was
   shown for invalid URLs.

 - Pressing the "Submit" button focuses the first input field with an error

 - Validation issues with the input field are shown when changes are committed
   (eg. when the field is blurred), not just when it loses focus.

This is done by:

 - Integrating custom constraint validation errors with the native validation
   API, by using the `Input.error` prop.

 - Doing validation in the "change" event of the input, instead of the form's
   "submit" event. Note that when the user commits and submits at the same time
   by pressing enter when the input has focus, the layout effect that sets
   the validity runs before the "submit" event.

 - Setting `noValidate` on the form to disable the browser's own UI messages.
   This disables both the UI message but also the behavior of focusing the
   first input with an error, which we want to keep.

 - Use the `useValidateOnSubmit` hook to focus the first field with an
   error on submission.

All the above aligns with how eg. React Aria handles communicating validation
state to the browser while displaying a custom message. See
https://react-spectrum.adobe.com/react-aria/forms.html.

Part of hypothesis/product-backlog#1535
robertknight added a commit to hypothesis/lms that referenced this issue Apr 29, 2024
Revise how validation for the URL input works so that:

 - Validation errors due to the `required` property on the input and the custom
   URL validation are handled the same way. Previously a native form validation
   error would be presented if `required` was missing and a custom error was
   shown for invalid URLs.

 - Pressing the "Submit" button focuses the first input field with an error

 - Validation issues with the input field are shown when changes are committed
   (eg. when the field is blurred), not just when it loses focus.

This is done by:

 - Integrating custom constraint validation errors with the native validation
   API, by using the `Input.error` prop.

 - Doing validation in the "change" event of the input, instead of the form's
   "submit" event. Note that when the user commits and submits at the same time
   by pressing enter when the input has focus, the layout effect that sets
   the validity runs before the "submit" event.

 - Setting `noValidate` on the form to disable the browser's own UI messages.
   This disables both the UI message but also the behavior of focusing the
   first input with an error, which we want to keep.

 - Use the `useValidateOnSubmit` hook to focus the first field with an
   error on submission.

All the above aligns with how eg. React Aria handles communicating validation
state to the browser while displaying a custom message. See
https://react-spectrum.adobe.com/react-aria/forms.html.

Part of hypothesis/product-backlog#1535
robertknight added a commit to hypothesis/lms that referenced this issue Apr 29, 2024
Revise how validation for the URL input works so that:

 - Validation errors due to the `required` property on the input and the custom
   URL validation are handled the same way. Previously a native form validation
   error would be presented if `required` was missing and a custom error was
   shown for invalid URLs.

 - Pressing the "Submit" button focuses the first input field with an error

 - Validation issues with the input field are shown when changes are committed
   (eg. when the field is blurred), not just when it loses focus.

This is done by:

 - Integrating custom constraint validation errors with the native validation
   API, by using the `Input.error` prop.

 - Doing validation in the "change" event of the input, instead of the form's
   "submit" event. Note that when the user commits and submits at the same time
   by pressing enter when the input has focus, the layout effect that sets
   the validity runs before the "submit" event.

 - Setting `noValidate` on the form to disable the browser's own UI messages.
   This disables both the UI message but also the behavior of focusing the
   first input with an error, which we want to keep.

 - Use the `useValidateOnSubmit` hook to focus the first field with an
   error on submission.

All the above aligns with how eg. React Aria handles communicating validation
state to the browser while displaying a custom message. See
https://react-spectrum.adobe.com/react-aria/forms.html.

Part of hypothesis/product-backlog#1535
robertknight added a commit to hypothesis/lms that referenced this issue Apr 29, 2024
Revise how validation for the URL input works so that:

 - Validation errors due to the `required` property on the input and the custom
   URL validation are handled the same way. Previously a native form validation
   error would be presented if `required` was missing and a custom error was
   shown for invalid URLs.

 - Pressing the "Submit" button focuses the first input field with an error

 - Validation issues with the input field are shown when changes are committed
   (eg. when the field is blurred), not just when it loses focus.

This is done by:

 - Integrating custom constraint validation errors with the native validation
   API, by using the `Input.error` prop.

 - Doing validation in the "change" event of the input, instead of the form's
   "submit" event. Note that when the user commits and submits at the same time
   by pressing enter when the input has focus, the layout effect that sets
   the validity runs before the "submit" event.

 - Setting `noValidate` on the form to disable the browser's own UI messages.
   This disables both the UI message but also the behavior of focusing the
   first input with an error, which we want to keep.

 - Use the `useValidateOnSubmit` hook to focus the first field with an
   error on submission.

All the above aligns with how eg. React Aria handles communicating validation
state to the browser while displaying a custom message. See
https://react-spectrum.adobe.com/react-aria/forms.html.

Part of hypothesis/product-backlog#1535
@robertknight
Copy link
Member

I'll respond to this comment to clarify what we've changed:

I think the crux of the issue here is that if one enters invalid data and presses the submit button, nothing happens for non-sighted users. No announcement is made and one has to navigate back into the form to find that there’s an error.

We have now modified our form controls so that pressing the submit button (or otherwise submitting the form) focuses the first field with an error, if there is one. This will cause screen readers to announce the error as part of describing the field. This mirrors how native HTML validation works. We adopted the approach from React Aria. Behind the scenes the visually presented validation error is also communicated to the browser via the native form validation API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants