Skip to content

Commit 4a7872d

Browse files
Add missing aria-labels to ListBox, Menu, Tabs items in RAC (#5796)
* Add missing aria-labels to ListBox and Menu items also remove it from gridlist items since the hook will never use it * fixing aria properties for tabs as well --------- Co-authored-by: Robert Snow <[email protected]>
1 parent bcb5cc0 commit 4a7872d

File tree

7 files changed

+35
-7
lines changed

7 files changed

+35
-7
lines changed

packages/react-aria-components/src/GridList.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,7 @@ export interface GridListItemProps<T = object> extends RenderProps<GridListItemR
228228
/** The object value that this item represents. When using dynamic collections, this is set automatically. */
229229
value?: T,
230230
/** A string representation of the item's contents, used for features like typeahead. */
231-
textValue?: string,
232-
/** An accessibility label for this item. */
233-
'aria-label'?: string
231+
textValue?: string
234232
}
235233

236234
function GridListItem<T extends object>(props: GridListItemProps<T>, ref: ForwardedRef<HTMLDivElement>): JSX.Element | null {

packages/react-aria-components/src/ListBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ function Option<T>({item}: OptionProps<T>) {
362362
let state = useContext(ListStateContext)!;
363363
let {dragAndDropHooks, dragState, dropState} = useContext(DragAndDropContext)!;
364364
let {optionProps, labelProps, descriptionProps, ...states} = useOption(
365-
{key: item.key},
365+
{key: item.key, 'aria-label': item.props?.['aria-label']},
366366
state,
367367
ref
368368
);

packages/react-aria-components/src/Menu.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ interface MenuItemInnerProps<T> {
287287
function MenuItemInner<T>({item}: MenuItemInnerProps<T>) {
288288
let state = useContext(MenuStateContext)!;
289289
let ref = useObjectRef<any>(item.props.ref);
290-
let {menuItemProps, labelProps, descriptionProps, keyboardShortcutProps, ...states} = useMenuItem({key: item.key}, state, ref);
290+
let {menuItemProps, labelProps, descriptionProps, keyboardShortcutProps, ...states} = useMenuItem({key: item.key, 'aria-label': item.props?.['aria-label']}, state, ref);
291291

292292
let props: MenuItemProps<T> = item.props;
293293
let {isFocusVisible, focusProps} = useFocusRing();

packages/react-aria-components/src/Tabs.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,9 +263,8 @@ const _Tab = /*#__PURE__*/ (forwardRef as forwardRefType)(Tab);
263263
export {_Tab as Tab};
264264

265265
function TabInner({item, state}: {item: Node<object>, state: TabListState<object>}) {
266-
let {key} = item;
267266
let ref = useObjectRef<any>(item.props.ref);
268-
let {tabProps, isSelected, isDisabled, isPressed} = useTab({key}, state, ref);
267+
let {tabProps, isSelected, isDisabled, isPressed} = useTab({key: item.key, ...item.props}, state, ref);
269268
let {focusProps, isFocused, isFocusVisible} = useFocusRing();
270269
let {hoverProps, isHovered} = useHover({
271270
isDisabled

packages/react-aria-components/test/ListBox.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ describe('ListBox', () => {
8686
}
8787
});
8888

89+
it('should support aria-label on the listbox items', () => {
90+
let {getAllByRole} = renderListbox({}, {'aria-label': 'test'});
91+
92+
for (let option of getAllByRole('option')) {
93+
expect(option).toHaveAttribute('aria-label', 'test');
94+
}
95+
});
96+
8997
it('should support the slot prop', () => {
9098
let {getByRole} = render(
9199
<ListBoxContext.Provider value={{slots: {test: {'aria-label': 'test'}}}}>

packages/react-aria-components/test/Menu.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,14 @@ describe('Menu', () => {
9090
}
9191
});
9292

93+
it('should support aria-label on the menu items', () => {
94+
let {getAllByRole} = renderMenu({}, {'aria-label': 'test'});
95+
96+
for (let menuitem of getAllByRole('menuitem')) {
97+
expect(menuitem).toHaveAttribute('aria-label', 'test');
98+
}
99+
});
100+
93101
it('should support the slot prop', () => {
94102
let {getByRole} = render(
95103
<MenuContext.Provider value={{slots: {test: {'aria-label': 'test'}}}}>

packages/react-aria-components/test/Tabs.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,21 @@ describe('Tabs', () => {
7979
expect(tabpanel).toHaveAttribute('data-test', 'tabpanel');
8080
});
8181

82+
it('should support aria props on the tabs', () => {
83+
let {getAllByRole} = renderTabs({}, {}, {
84+
'aria-label': 'label',
85+
'aria-labelledby': 'labelledby',
86+
'aria-describedby': 'describedby',
87+
'aria-details': 'details'
88+
}, {});
89+
for (let tab of getAllByRole('tab')) {
90+
expect(tab).toHaveAttribute('aria-label', 'label');
91+
expect(tab).toHaveAttribute('aria-labelledby', 'labelledby');
92+
expect(tab).toHaveAttribute('aria-describedby', 'describedby');
93+
expect(tab).toHaveAttribute('aria-details', 'details');
94+
}
95+
});
96+
8297
it('should support render props', () => {
8398
let {getByRole} = render(
8499
<Tabs orientation="horizontal">

0 commit comments

Comments
 (0)