From 9d270c3768987c5800ec9d4f4f5d06ec33a79104 Mon Sep 17 00:00:00 2001 From: kalasgarov Date: Wed, 20 Nov 2024 11:50:45 -0800 Subject: [PATCH 1/2] feat: improve accessibility for single field components tckt-000 --- .../components/DateOfBirth/DateOfBirth.tsx | 41 +++++++++++++------ .../Form/components/EmailInput/EmailInput.tsx | 17 +++++--- .../components/PhoneNumber/PhoneNumber.tsx | 11 ++--- .../SelectDropdown/SelectDropdown.tsx | 23 +++++++---- 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx b/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx index 79f4432b6..6e43a5cbe 100644 --- a/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx +++ b/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import classNames from 'classnames'; import { useFormContext } from 'react-hook-form'; import { type DateOfBirthProps } from '@atj/forms'; import { type PatternComponent } from '../../index.js'; @@ -36,20 +37,33 @@ export const DateOfBirthPattern: PatternComponent = ({ {required && *} {hint && ( - + {hint} )} + {error && ( + + )}
@@ -81,22 +99,21 @@ export const DateOfBirthPattern: PatternComponent = ({ Year
- {error && ( - - {error.message} - - )} ); }; diff --git a/packages/design/src/Form/components/EmailInput/EmailInput.tsx b/packages/design/src/Form/components/EmailInput/EmailInput.tsx index 31588db45..b49e14f99 100644 --- a/packages/design/src/Form/components/EmailInput/EmailInput.tsx +++ b/packages/design/src/Form/components/EmailInput/EmailInput.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import classNames from 'classnames'; import { useFormContext } from 'react-hook-form'; import { type EmailInputProps } from '@atj/forms'; import { type PatternComponent } from '../../index.js'; @@ -10,6 +11,7 @@ export const EmailInputPattern: PatternComponent = ({ error, }) => { const { register } = useFormContext(); + const errorId = `input-error-message-${emailId}`; return (
@@ -18,20 +20,23 @@ export const EmailInputPattern: PatternComponent = ({ {label} {required && *} + {error && ( + + )} - {error && ( - - {error.message} - - )}
); }; diff --git a/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx b/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx index ee4adc1d7..ab4c471f6 100644 --- a/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx +++ b/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx @@ -13,6 +13,7 @@ export const PhoneNumberPattern: PatternComponent = ({ value, }) => { const { register } = useFormContext(); + const errorId = `input-error-message-${phoneId}`; return (
@@ -28,16 +29,12 @@ export const PhoneNumberPattern: PatternComponent = ({ {required && *} {hint && ( -
+
{hint}
)} {error && ( -
diff --git a/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx b/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx index ab9c34858..49cd0a6fd 100644 --- a/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx +++ b/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx @@ -1,6 +1,6 @@ import React from 'react'; +import classNames from 'classnames'; import { useFormContext } from 'react-hook-form'; - import { type SelectDropdownProps } from '@atj/forms'; import { type PatternComponent } from '../../index.js'; @@ -12,13 +12,27 @@ export const SelectDropdownPattern: PatternComponent = ({ error, }) => { const { register } = useFormContext(); + const errorId = `input-error-message-${selectId}`; + return (
- @@ -28,11 +42,6 @@ export const SelectDropdownPattern: PatternComponent = ({ ))} - {error && ( - - {error.message} - - )}
); }; From 81d49d22d53bfecb3c5a6a8f01f8f51dd79d982e Mon Sep 17 00:00:00 2001 From: kalasgarov Date: Wed, 27 Nov 2024 09:35:11 -0800 Subject: [PATCH 2/2] refactor: improve accessibility and error handling for single field components tckt-393 --- .../components/DateOfBirth/DateOfBirth.tsx | 47 ++++++++++++------- .../Form/components/EmailInput/EmailInput.tsx | 2 +- .../components/PhoneNumber/PhoneNumber.tsx | 9 ++-- .../SelectDropdown/SelectDropdown.tsx | 2 +- 4 files changed, 37 insertions(+), 23 deletions(-) diff --git a/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx b/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx index 6e43a5cbe..ff14afad0 100644 --- a/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx +++ b/packages/design/src/Form/components/DateOfBirth/DateOfBirth.tsx @@ -19,6 +19,14 @@ const months = [ { value: '12', label: 'December' }, ]; +const getAriaDescribedBy = ( + errorId: string | null, + hintId: string | null +): string | undefined => { + const ids = [errorId, hintId].filter(Boolean).join(' '); + return ids || undefined; +}; + export const DateOfBirthPattern: PatternComponent = ({ monthId, dayId, @@ -29,6 +37,8 @@ export const DateOfBirthPattern: PatternComponent = ({ error, }) => { const { register } = useFormContext(); + const errorId = `input-error-message-${monthId}`; + const hintId = `hint-${monthId}`; return (
@@ -37,16 +47,12 @@ export const DateOfBirthPattern: PatternComponent = ({ {required && *} {hint && ( - + {hint} )} {error && ( -
@@ -100,17 +110,18 @@ export const DateOfBirthPattern: PatternComponent = ({
diff --git a/packages/design/src/Form/components/EmailInput/EmailInput.tsx b/packages/design/src/Form/components/EmailInput/EmailInput.tsx index b49e14f99..2f2d9cc81 100644 --- a/packages/design/src/Form/components/EmailInput/EmailInput.tsx +++ b/packages/design/src/Form/components/EmailInput/EmailInput.tsx @@ -34,7 +34,7 @@ export const EmailInputPattern: PatternComponent = ({ autoCapitalize="off" autoCorrect="off" {...register(emailId, { required })} - aria-describedby={error ? `${emailId} ${errorId}}` : emailId} + aria-describedby={error ? errorId : undefined} />
diff --git a/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx b/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx index ab4c471f6..2661a3d23 100644 --- a/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx +++ b/packages/design/src/Form/components/PhoneNumber/PhoneNumber.tsx @@ -14,6 +14,7 @@ export const PhoneNumberPattern: PatternComponent = ({ }) => { const { register } = useFormContext(); const errorId = `input-error-message-${phoneId}`; + const hintId = `hint-${phoneId}`; return (
@@ -22,14 +23,13 @@ export const PhoneNumberPattern: PatternComponent = ({ className={classNames('usa-label', { 'usa-label--error': error, })} - id={`input-message-${phoneId}`} htmlFor={phoneId} > {label} {required && *} {hint && ( -
+
{hint}
)} @@ -46,7 +46,10 @@ export const PhoneNumberPattern: PatternComponent = ({ type="tel" defaultValue={value} {...register(phoneId, { required })} - aria-describedby={error ? `${phoneId} ${errorId}` : phoneId} + aria-describedby={ + `${hint ? `${hintId}` : ''}${error ? ` ${errorId}` : ''}`.trim() || + undefined + } />
diff --git a/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx b/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx index 49cd0a6fd..9ae3a59a3 100644 --- a/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx +++ b/packages/design/src/Form/components/SelectDropdown/SelectDropdown.tsx @@ -31,7 +31,7 @@ export const SelectDropdownPattern: PatternComponent = ({ })} id={selectId} {...register(selectId, { required })} - aria-describedby={error ? `${selectId} ${errorId}` : selectId} + aria-describedby={error ? errorId : undefined} >