Skip to content

Commit c778a17

Browse files
author
Hector Arce De Las Heras
committed
Enable setting labels for listbox in InputSearch and InputDropdown components
This commit allows for setting labels to the listbox in the InputSearch and InputDropdown components, enhancing accessibility. For InputSearch, labels can be set for all lists using optionsListDefaultArias or for individual lists using aria-label or aria-labelledby in each IOptionGroup of the optionList. For InputDropdown, labels can be set using aria-label or aria-labelledby in the optionList prop.
1 parent 33987df commit c778a17

File tree

14 files changed

+177
-118
lines changed

14 files changed

+177
-118
lines changed

src/components/inputDropdown/__tests__/inputDropdown.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ const mockProps = {
2525
value: 'string',
2626
},
2727
],
28+
['aria-label']: 'input dropdown',
2829
},
29-
label: { content: 'input search' },
30+
label: { content: 'input dropdown' },
3031
closeIcon: { icon: 'CLOSE_ICON', ['aria-label']: 'Close icon' },
3132
dataTestId: 'testid',
3233
handleOpenOptions: jest.fn(),

src/components/inputDropdown/components/optionsList.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ export const OptionsListComponent = (
4040
id={props['aria-controls']}
4141
optionVariant={props.stylesListOption.optionVariant}
4242
options={props.optionList.options}
43+
optionsContainerArias={{
44+
['aria-label']: props.optionList['aria-label'],
45+
['aria-labelledby']: props.optionList['aria-labelledby'],
46+
}}
4347
roveFocus={roveFocusProps}
4448
selectedValue={props.value}
4549
variant={props.stylesListOption.variant}

src/components/inputSearch/__tests__/helpers.test.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,6 @@ describe('Input Search Helpers', () => {
5656
expect(result.optionsFiltered).toEqual([{ options: ['test1'] }]);
5757
});
5858

59-
test('should return original options when no match is found', () => {
60-
const options = [{ options: ['test1', 'test2', 'test3'] }];
61-
const result = filterOptions('test4', options);
62-
expect(result.optionsFiltered).toEqual(options);
63-
});
64-
6559
test('check match', () => {
6660
const options = ['first', 'second', 'thrid'];
6761
const correctValue = 'first';

src/components/inputSearch/__tests__/inputSearch.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const mockProps = {
2121
optionList: [
2222
{
2323
options: ['string'],
24+
['aria-label']: 'input search',
2425
},
2526
],
2627
rightIcon: {

src/components/inputSearch/components/optionsList.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ export const OptionsListComponent = (
5353
id={props['aria-controls']}
5454
optionVariant={props.optionVariant ?? props.stylesListOption?.optionVariant}
5555
options={_options}
56+
optionsContainerArias={{
57+
['aria-label']: props['aria-label'],
58+
['aria-labelledby']: props['aria-labelledby'],
59+
}}
5660
roveFocus={roveFocusProps}
5761
selectedValue={props.value}
5862
title={props.title}

src/components/inputSearch/components/popoverSearchList.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ export const PopoverSearchListComponent = (
6464
<OptionsList
6565
key={index}
6666
ref={ref}
67-
aria-controls={`${props['aria-controls']}${index}`}
67+
aria-controls={props['aria-controls']}
68+
aria-label={section?.['aria-label'] ?? props.optionsListDefaultArias?.['aria-label']}
69+
aria-labelledby={
70+
section?.['aria-labelledby'] ?? props.optionsListDefaultArias?.['aria-labelledby']
71+
}
6872
caseSensitive={props.caseSensitive}
6973
dataTestId={`${props.dataTestId}OptionsList${index}`}
7074
hightlightedOption={showTextWritten || showHighlightedOption}
@@ -161,7 +165,6 @@ export const PopoverSearchListComponent = (
161165
variant={props.styles?.[props.state]?.popoverVariant?.[props.device]}
162166
onCloseInternally={() => {
163167
props.onOpenOptions(false);
164-
refInput?.current?.focus();
165168
}}
166169
>
167170
{useActionBottomSheet ? (
@@ -172,6 +175,7 @@ export const PopoverSearchListComponent = (
172175
onClick: event => {
173176
props.onOpenOptions(false);
174177
props.closeIcon?.onClick?.(event);
178+
refInput?.current?.focus();
175179
},
176180
}}
177181
dataTestId={`${props.dataTestId}ActionBottomSheet`}

src/components/inputSearch/helpers/filterOptions.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { structuredClone } from '@/utils';
22

33
import { IOptionGroup, InputSearchFilterOptionReturnValue } from '../types';
44

5-
// eslint-disable-next-line complexity
65
export const filterOptions = (
76
value: string | number | undefined,
87
options: IOptionGroup[],
@@ -35,11 +34,7 @@ export const filterOptions = (
3534
optionsFiltered[i].options = optionsAvailable;
3635
}
3736

38-
const hasValue = optionsFiltered.some(option => option.options.length > 0);
39-
40-
return {
41-
optionsFiltered: hasValue ? optionsFiltered : options,
42-
};
37+
return { optionsFiltered };
4338
};
4439

4540
export const hasMatchWithOptions = (

src/components/inputSearch/stories/argtypes.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ export const argtypes = (variants: IThemeObjectVariants, themeSelected: string):
6060
category: CATEGORY_CONTROL.CONTENT,
6161
},
6262
},
63+
optionsListDefaultArias: {
64+
description: 'Arias for the options list',
65+
type: { name: 'object' },
66+
control: { type: 'object' },
67+
table: {
68+
type: {
69+
summary: 'OptionGroupAriasTypes',
70+
},
71+
category: CATEGORY_CONTROL.ACCESIBILITY,
72+
},
73+
},
6374
elementsToShow: {
6475
description: 'Number of elements to show in the list',
6576
control: { type: 'text' },

src/components/inputSearch/stories/inputSearch.stories.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const commonArgs: IInputSearch = {
4949
inputPopoverIcon: { icon: 'CLOSE' },
5050
titleActionBottomSheet: 'Title List',
5151
optionList: options,
52+
optionsListDefaultArias: { ['aria-label']: 'Label' },
5253
errorMessage: { content: 'Error message' },
5354
errorIcon: { icon: ICONS.ICON_PLACEHOLDER, altText: 'error' },
5455
loadingText: { content: 'Loading results' },

src/components/inputSearch/types/inputSearch.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ export type InputSearchOptionType = ListOptionsOptionType;
2424
export type InputSearchTitleType = Omit<IText<string>, 'children'> & {
2525
content?: string | number;
2626
};
27-
export interface IOptionGroup {
27+
28+
export type OptionGroupAriasTypes = Pick<React.AriaAttributes, 'aria-label' | 'aria-labelledby'>;
29+
30+
export interface IOptionGroup extends OptionGroupAriasTypes {
2831
options: string[];
2932
title?: InputSearchTitleType;
3033
optionVariant?: string;
@@ -75,6 +78,7 @@ export interface IPopoverSearchList {
7578
loadingText?: InputSearchLoadingTextType;
7679
open: boolean;
7780
optionList: IOptionGroup[];
81+
optionsListDefaultArias?: OptionGroupAriasTypes;
7882
preventCloseOnClickElements?: (HTMLElement | null | undefined)[];
7983
searchText?: string;
8084
hasResultTextWrittenByUser?: boolean;
@@ -90,7 +94,7 @@ export interface IPopoverSearchList {
9094
onOptionsListKeyDown?: (event: React.KeyboardEvent<HTMLDivElement>) => void;
9195
}
9296

93-
export interface IOptionsListSearchList {
97+
export interface IOptionsListSearchList extends OptionGroupAriasTypes {
9498
caseSensitive?: boolean;
9599
index?: number;
96100
stylesListOption?: InputSearchListOptionsProps;
@@ -155,6 +159,7 @@ export interface IInputSearchStandAlone extends Omit<IInputStandAlone, propsToOm
155159
caseSensitive?: boolean;
156160
listOptionsHeight: string;
157161
optionList: IOptionGroup[];
162+
optionsListDefaultArias?: OptionGroupAriasTypes;
158163
loadingList?: boolean;
159164
loadingText?: InputSearchLoadingTextType;
160165
elementsToShow?: number;

0 commit comments

Comments
 (0)