diff --git a/packages/@adobe/react-spectrum/src/table/TableView.tsx b/packages/@adobe/react-spectrum/src/table/TableView.tsx index 13bfe9b5c94..7f5c3176adf 100644 --- a/packages/@adobe/react-spectrum/src/table/TableView.tsx +++ b/packages/@adobe/react-spectrum/src/table/TableView.tsx @@ -59,6 +59,11 @@ export interface SpectrumTableProps isQuiet?: boolean; /** Sets what the TableView should render when there is no content to display. */ renderEmptyState?: () => JSX.Element; + /** + * A custom accessibility label for the select all checkbox in the table header. + * If not provided, defaults to the standard localized "Select All" label. + */ + selectAllLabel?: string; /** * Whether `disabledKeys` applies to all interactions, or only selection. * diff --git a/packages/@adobe/react-spectrum/src/table/TableViewBase.tsx b/packages/@adobe/react-spectrum/src/table/TableViewBase.tsx index 1841f41b6d7..acd52518f71 100644 --- a/packages/@adobe/react-spectrum/src/table/TableViewBase.tsx +++ b/packages/@adobe/react-spectrum/src/table/TableViewBase.tsx @@ -161,6 +161,7 @@ export interface TableContextValue { headerMenuOpen: boolean; setHeaderMenuOpen: (val: boolean) => void; renderEmptyState?: () => ReactElement; + selectAllLabel?: string; } export const TableContext = React.createContext | null>(null); @@ -193,6 +194,7 @@ function TableViewBase(props: TableBaseProps, ref: DOMRef(props: TableBaseProps, ref: DOMRef (null); - let {state} = useTableContext(); + let {state, selectAllLabel} = useTableContext(); let isSingleSelectionMode = state.selectionManager.selectionMode === 'single'; let {columnHeaderProps} = useTableColumnHeader( { @@ -1159,7 +1162,7 @@ function TableSelectAllCell({column}) { ref ); - let {checkboxProps} = useTableSelectAllCheckbox(state); + let {checkboxProps} = useTableSelectAllCheckbox(state, {'aria-label': selectAllLabel}); let {hoverProps, isHovered} = useHover({}); return ( diff --git a/packages/@adobe/react-spectrum/stories/table/Table.stories.tsx b/packages/@adobe/react-spectrum/stories/table/Table.stories.tsx index 28afefb4c02..0765855011d 100644 --- a/packages/@adobe/react-spectrum/stories/table/Table.stories.tsx +++ b/packages/@adobe/react-spectrum/stories/table/Table.stories.tsx @@ -920,6 +920,44 @@ export const CustomRowHeaderLabeling: TableStory = { } }; +export const CustomSelectAllLabel: TableStory = { + args: { + 'aria-label': 'Items', + selectionMode: 'multiple', + selectAllLabel: 'Select all items', + width: 500, + height: 200 + }, + render: args => ( + + + Foo + Bar + Baz + + + + One + Two + Three + + + One + Two + Three + + + + ), + name: 'custom select all labeling', + parameters: { + description: { + content: + 'Overrides the accessible label of the select all checkbox in the table header via selectAllLabel.' + } + } +}; + export const CRUD: TableStory = { render: args => , name: 'CRUD' diff --git a/packages/@adobe/react-spectrum/test/table/TableTests.js b/packages/@adobe/react-spectrum/test/table/TableTests.js index c1649a821fa..6e14b842f1c 100644 --- a/packages/@adobe/react-spectrum/test/table/TableTests.js +++ b/packages/@adobe/react-spectrum/test/table/TableTests.js @@ -427,6 +427,42 @@ export let tableTests = () => { expect(cells[5]).toHaveAttribute('aria-colindex', '4'); }); + it('defaults the select all checkbox aria-label to "Select All" when selectAllLabel is not provided', function () { + let {getAllByRole} = render( + + + Foo + + + + Foo 1 + + + + ); + + let checkbox = getAllByRole('checkbox')[0]; + expect(checkbox).toHaveAttribute('aria-label', 'Select All'); + }); + + it('allows the select all checkbox aria-label to be overridden via selectAllLabel', function () { + let {getAllByRole} = render( + + + Foo + + + + Foo 1 + + + + ); + + let checkbox = getAllByRole('checkbox')[0]; + expect(checkbox).toHaveAttribute('aria-label', 'Select all items'); + }); + it('accepts a UNSAFE_className', function () { let {getByRole} = render( ( * @param props - Props for the select all checkbox. * @param state - State of the table, as returned by `useTableState`. */ -export function useTableSelectAllCheckbox(state: TableState): TableSelectAllCheckboxAria { +export function useTableSelectAllCheckbox( + state: TableState, + props: AriaTableSelectAllCheckboxProps = {} +): TableSelectAllCheckboxAria { let {isEmpty, isSelectAll, selectionMode} = state.selectionManager; const stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-aria/table'); return { checkboxProps: { - 'aria-label': stringFormatter.format(selectionMode === 'single' ? 'select' : 'selectAll'), + 'aria-label': + props['aria-label'] ?? + stringFormatter.format(selectionMode === 'single' ? 'select' : 'selectAll'), isSelected: isSelectAll, isDisabled: selectionMode !== 'multiple' ||