From aa43dfb03ea0032b46016feac42b885fdbd62b6f Mon Sep 17 00:00:00 2001 From: Michael Taranto Date: Tue, 16 Jan 2024 11:46:45 +1100 Subject: [PATCH] Autosuggest: Fix `aria-label` and `aria-labelledby` features (#1420) --- .changeset/wet-cows-bake.md | 12 +++++ .../Autosuggest/Autosuggest.docs.tsx | 48 +++++++++++++++++++ .../Autosuggest/Autosuggest.test.tsx | 37 ++++++++++++++ .../components/Autosuggest/Autosuggest.tsx | 3 +- .../Autosuggest/createAccessbilityProps.ts | 12 +++-- .../src/lib/components/Dropdown/Dropdown.tsx | 3 +- .../components/MonthPicker/MonthPicker.tsx | 2 - .../PasswordField/PasswordField.tsx | 3 +- .../lib/components/TextField/TextField.tsx | 3 +- .../src/lib/components/Textarea/Textarea.tsx | 3 +- .../lib/components/private/Field/Field.tsx | 3 -- 11 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 .changeset/wet-cows-bake.md diff --git a/.changeset/wet-cows-bake.md b/.changeset/wet-cows-bake.md new file mode 100644 index 00000000000..4cff1fecf07 --- /dev/null +++ b/.changeset/wet-cows-bake.md @@ -0,0 +1,12 @@ +--- +'braid-design-system': patch +--- + +--- +updated: + - Autosuggest +--- + +**Autosuggest:** Fix aria-label and aria-labelledby features + +Fixes an issue where the `aria-label` and `aria-labelledby` props provided by a consumer were being overidden internally by the `Autosuggest` component. diff --git a/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.docs.tsx b/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.docs.tsx index 8c13da5a88e..17d720d524c 100644 --- a/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.docs.tsx +++ b/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.docs.tsx @@ -11,6 +11,7 @@ import { Alert, List, Stack, + Heading, } from '../'; import { IconHelp, IconLanguage } from '../icons'; @@ -662,6 +663,53 @@ const docs: ComponentDocs = { , ), }, + { + label: 'Indirect or hidden field labels', + description: ( + + In some cases it may be necessary for a field to be labelled by + another element or even not to have a visual label. Instead of + providing a label either aria-label{' '} + or aria-labelledby can be provided. + + ), + Example: ({ id, getState, setState, resetState }) => + source( + + + Custom field label + + + resetState('value')} + suggestions={filterSuggestions([ + { text: 'Apples', value: 1 }, + { text: 'Bananas', value: 2 }, + { text: 'Broccoli', value: 3 }, + { text: 'Carrots', value: 4 }, + ])} + /> + + resetState('value')} + suggestions={filterSuggestions([ + { text: 'Apples', value: 1 }, + { text: 'Bananas', value: 2 }, + { text: 'Broccoli', value: 3 }, + { text: 'Carrots', value: 4 }, + ])} + /> + , + ), + }, ], }; diff --git a/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.test.tsx b/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.test.tsx index 9f0f3294250..6c1099e9979 100644 --- a/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.test.tsx +++ b/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.test.tsx @@ -395,6 +395,43 @@ describe('Autosuggest', () => { expect(result).toBe(input); }); + it('associates field with aria-label correctly', () => { + const { getByLabelText } = render( + + {}} + suggestions={[]} + /> + , + ); + + expect(getByLabelText('Hidden field label').tagName).toBe('INPUT'); + expect( + getByLabelText('Hidden field label').getAttribute('aria-labelledby'), + ).toBeNull(); + }); + + it('associates field with aria-labelledby correctly', () => { + const { getByLabelText } = render( + +
My field
+ {}} + suggestions={[]} + /> +
, + ); + + expect(getByLabelText('My field').tagName).toBe('INPUT'); + expect(getByLabelText('My field').getAttribute('aria-label')).toBeNull(); + }); + it('should support standard suggestions', async () => { const { input, queryByLabelText } = renderAutosuggest({ value: { text: '' }, diff --git a/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.tsx b/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.tsx index fa9dc6052a5..bfc4f594c29 100644 --- a/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.tsx +++ b/packages/braid-design-system/src/lib/components/Autosuggest/Autosuggest.tsx @@ -276,7 +276,7 @@ interface LegacyMessageSuggestion { export type AutosuggestBaseProps = Omit< FieldBaseProps, - 'value' | 'autoComplete' | 'labelId' | 'prefix' + 'value' | 'autoComplete' | 'prefix' > & { value: AutosuggestValue; suggestions: @@ -728,7 +728,6 @@ export const Autosuggest = forwardRef(function ( { const menuId = `${id}-menu`; - const labelId = `${id}-label`; const assistiveDescriptionId = `${id}-aria-description`; return { - labelProps: { - id: labelId, - }, inputProps: { id, role: 'combobox', @@ -25,7 +28,6 @@ export const createAccessbilityProps = ({ 'aria-owns': isOpen ? menuId : undefined, // backwards compatibility for screenreaders implementing ARIA 1.0 'aria-controls': menuId, 'aria-expanded': isOpen, - 'aria-labelledby': labelId, 'aria-autocomplete': 'list', 'aria-activedescendant': typeof highlightedIndex === 'number' diff --git a/packages/braid-design-system/src/lib/components/Dropdown/Dropdown.tsx b/packages/braid-design-system/src/lib/components/Dropdown/Dropdown.tsx index 12f04dd9c3f..bde8fba9d7c 100644 --- a/packages/braid-design-system/src/lib/components/Dropdown/Dropdown.tsx +++ b/packages/braid-design-system/src/lib/components/Dropdown/Dropdown.tsx @@ -15,7 +15,7 @@ type ValidDropdownChildren = AllHTMLAttributes< type SelectProps = AllHTMLAttributes; export type DropdownBaseProps = Omit< FieldBaseProps, - 'value' | 'labelId' | 'secondaryMessage' | 'prefix' + 'value' | 'secondaryMessage' | 'prefix' > & { children: ValidDropdownChildren[] | ValidDropdownChildren; value: NonNullable; @@ -44,7 +44,6 @@ export const Dropdown = forwardRef( void; export type MonthPickerBaseProps = Omit< FieldGroupBaseProps, | 'value' - | 'labelId' | 'aria-describedby' | 'name' | 'autoComplete' @@ -204,7 +203,6 @@ const MonthPicker = ({ {...restProps} icon={undefined} prefix={undefined} - labelId={undefined} name={undefined} autoComplete={undefined} secondaryMessage={null} diff --git a/packages/braid-design-system/src/lib/components/PasswordField/PasswordField.tsx b/packages/braid-design-system/src/lib/components/PasswordField/PasswordField.tsx index ea2c8bcf079..96fca98e732 100644 --- a/packages/braid-design-system/src/lib/components/PasswordField/PasswordField.tsx +++ b/packages/braid-design-system/src/lib/components/PasswordField/PasswordField.tsx @@ -21,7 +21,7 @@ type InputProps = AllHTMLAttributes; export type PasswordFieldBaseProps = Omit< FieldBaseProps, - 'value' | 'labelId' | 'secondaryMessage' | 'icon' | 'prefix' + 'value' | 'secondaryMessage' | 'icon' | 'prefix' > & { value: NonNullable; onChange: NonNullable; @@ -82,7 +82,6 @@ export const PasswordField = forwardRef( value={value} icon={undefined} prefix={undefined} - labelId={undefined} disabled={disabled} secondaryMessage={null} alwaysShowSecondaryIcon={!disabled} diff --git a/packages/braid-design-system/src/lib/components/TextField/TextField.tsx b/packages/braid-design-system/src/lib/components/TextField/TextField.tsx index d4892a189ce..d75edbed452 100644 --- a/packages/braid-design-system/src/lib/components/TextField/TextField.tsx +++ b/packages/braid-design-system/src/lib/components/TextField/TextField.tsx @@ -40,7 +40,7 @@ type InputProps = AllHTMLAttributes; export type TextFieldBaseProps = Omit< FieldBaseProps, - 'value' | 'labelId' | 'secondaryMessage' + 'value' | 'secondaryMessage' > & { value: NonNullable; type?: keyof typeof validTypes; @@ -93,7 +93,6 @@ export const TextField = forwardRef( {...restProps} id={id} value={value} - labelId={undefined} secondaryMessage={ characterLimit ? getCharacterLimitStatus({ diff --git a/packages/braid-design-system/src/lib/components/Textarea/Textarea.tsx b/packages/braid-design-system/src/lib/components/Textarea/Textarea.tsx index f0c8dcca59b..6ee957e01db 100644 --- a/packages/braid-design-system/src/lib/components/Textarea/Textarea.tsx +++ b/packages/braid-design-system/src/lib/components/Textarea/Textarea.tsx @@ -21,7 +21,7 @@ type NativeTextareaProps = AllHTMLAttributes; export type TextareaBaseProps = Omit< FieldBaseProps, - 'value' | 'labelId' | 'secondaryMessage' | 'icon' | 'prefix' + 'value' | 'secondaryMessage' | 'icon' | 'prefix' > & { value: NonNullable; onChange: NonNullable; @@ -122,7 +122,6 @@ export const Textarea = forwardRef( value={value} icon={undefined} prefix={undefined} - labelId={undefined} secondaryMessage={ characterLimit ? getCharacterLimitStatus({ diff --git a/packages/braid-design-system/src/lib/components/private/Field/Field.tsx b/packages/braid-design-system/src/lib/components/private/Field/Field.tsx index 0791d47c133..7384ae1adc2 100644 --- a/packages/braid-design-system/src/lib/components/private/Field/Field.tsx +++ b/packages/braid-design-system/src/lib/components/private/Field/Field.tsx @@ -41,7 +41,6 @@ export type FieldLabelVariant = export interface FieldBaseProps { id: NonNullable; value?: FormElementProps['value']; - labelId?: string; name?: FormElementProps['name']; disabled?: FormElementProps['disabled']; autoComplete?: FormElementProps['autoComplete']; @@ -94,7 +93,6 @@ type InternalFieldProps = FieldBaseProps & export const Field = ({ id, value, - labelId, name, disabled, autoComplete, @@ -156,7 +154,6 @@ export const Field = ({ {hasVisualLabelOrDescription ? (