diff --git a/api-generator/components/datatable.js b/api-generator/components/datatable.js index f795221da6..2146a6bcaf 100644 --- a/api-generator/components/datatable.js +++ b/api-generator/components/datatable.js @@ -197,6 +197,12 @@ const DataTableProps = [ default: 'null', description: 'Selected row in single mode or an array of values in multiple mode.' }, + { + name: 'selectionAriaLabel', + type: 'string', + default: 'null', + description: 'A field property from the row to add "Select {field}" and "Unselect {field}" ARIA labels to checkbox/radio buttons.' + }, { name: 'contextMenuSelection', type: 'any', diff --git a/components/doc/datatable/index.js b/components/doc/datatable/index.js index f0db1ba70f..cd82901cfd 100644 --- a/components/doc/datatable/index.js +++ b/components/doc/datatable/index.js @@ -1,9 +1,9 @@ -import React, { memo } from 'react'; import Link from 'next/link'; -import { TabView, TabPanel } from '../../lib/tabview/TabView'; -import { useLiveEditorTabs } from '../common/liveeditor'; +import React, { memo } from 'react'; +import { TabPanel, TabView } from '../../lib/tabview/TabView'; import { CodeHighlight } from '../common/codehighlight'; import { DevelopmentSection } from '../common/developmentsection'; +import { useLiveEditorTabs } from '../common/liveeditor'; const DataTableDoc = memo(() => { const sources = { @@ -229,7 +229,7 @@ export class DataTableDemo extends Component { filters={this.state.filters} filterDisplay="menu" loading={this.state.loading} responsiveLayout="scroll" globalFilterFields={['name', 'country.name', 'representative.name', 'balance', 'status']} emptyMessage="No customers found." currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"> - + { filters={filters} filterDisplay="menu" loading={loading} responsiveLayout="scroll" globalFilterFields={['name', 'country.name', 'representative.name', 'balance', 'status']} emptyMessage="No customers found." currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"> - + { filters={filters} filterDisplay="menu" loading={loading} responsiveLayout="scroll" globalFilterFields={['name', 'country.name', 'representative.name', 'balance', 'status']} emptyMessage="No customers found." currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"> - + { filters={filters} filterDisplay="menu" loading={loading} responsiveLayout="scroll" globalFilterFields={['name', 'country.name', 'representative.name', 'balance', 'status']} emptyMessage="No customers found." currentPageReportTemplate="Showing {first} to {last} of {totalRecords} entries"> - + { null Selected row in single mode or an array of values in multiple mode. + + selectionAriaLabel + string + null + + A field property from the row to add "Select {field}" and "Unselect {field}" ARIA labels to checkbox/radio buttons. + + contextMenuSelection any diff --git a/components/lib/api/Locale.js b/components/lib/api/Locale.js index f094b7b2b1..40f4de08fb 100644 --- a/components/lib/api/Locale.js +++ b/components/lib/api/Locale.js @@ -9,6 +9,7 @@ let locales = { equals: 'Equals', notEquals: 'Not equals', noFilter: 'No Filter', + filter: 'Filter', lt: 'Less than', lte: 'Less than or equal to', gt: 'Greater than', @@ -52,7 +53,9 @@ let locales = { firstPageLabel: 'First Page', lastPageLabel: 'Last Page', nextPageLabel: 'Next Page', - previousPageLabel: 'Previous Page' + previousPageLabel: 'Previous Page', + selectLabel: 'Select', + unselectLabel: 'Unselect' } } }; diff --git a/components/lib/datatable/BodyCell.js b/components/lib/datatable/BodyCell.js index e31f8ab262..d29a3d969b 100644 --- a/components/lib/datatable/BodyCell.js +++ b/components/lib/datatable/BodyCell.js @@ -1,4 +1,5 @@ import * as React from 'react'; +import { ariaLabel } from '../api/Api'; import { useEventListener, useUnmountEffect, useUpdateEffect } from '../hooks/Hooks'; import { OverlayService } from '../overlayservice/OverlayService'; import { Ripple } from '../ripple/Ripple'; @@ -504,11 +505,17 @@ export const BodyCell = React.memo((props) => { if (selectionMode) { const showSelection = props.showSelectionElement ? props.showSelectionElement(props.rowData, { rowIndex: props.rowIndex, props: props.tableProps }) : true; + let label; + if (showSelection) { + const ariaLabelField = props.selectionAriaLabel || props.tableProps.dataKey; + const ariaLabelText = ObjectUtils.resolveFieldData(props.rowData, ariaLabelField); + label = `${props.selected ? ariaLabel('unselectLabel') : ariaLabel('selectLabel')} ${ariaLabelText}`; + } content = showSelection && ( <> - {selectionMode === 'single' && } - {selectionMode === 'multiple' && } + {selectionMode === 'single' && } + {selectionMode === 'multiple' && } ); } else if (rowReorder) { diff --git a/components/lib/datatable/BodyRow.js b/components/lib/datatable/BodyRow.js index 0b7e2d3b5e..68079fb768 100644 --- a/components/lib/datatable/BodyRow.js +++ b/components/lib/datatable/BodyRow.js @@ -304,6 +304,7 @@ export const BodyRow = React.memo((props) => { onEditingMetaChange={props.onEditingMetaChange} onRowToggle={props.onRowToggle} selection={props.selection} + selectionAriaLabel={props.tableProps.selectionAriaLabel} allowCellSelection={props.allowCellSelection} compareSelectionBy={props.compareSelectionBy} selectOnEdit={props.selectOnEdit} diff --git a/components/lib/datatable/ColumnFilter.js b/components/lib/datatable/ColumnFilter.js index 7770f49c98..e7f56b02e9 100644 --- a/components/lib/datatable/ColumnFilter.js +++ b/components/lib/datatable/ColumnFilter.js @@ -368,6 +368,10 @@ export const ColumnFilter = React.memo((props) => { ]; }; + const filterLabel = () => { + return localeOption('filter'); + }; + const noFilterLabel = () => { return localeOption('noFilter'); }; @@ -450,12 +454,9 @@ export const ColumnFilter = React.memo((props) => { 'p-column-filter-menu-button-open': overlayVisibleState, 'p-column-filter-menu-button-active': hasFilter() }); + const label = filterLabel(); - return ( - - ); + return - ); + return