Skip to content
Permalink
Browse files

Merge pull request #3211 from salesforce-ux/fix/data-table-checkbox-r…

…adiogroup

Fix(data-table): checkbox and radio button grouping in data tables
  • Loading branch information...
SiTaggart committed Apr 20, 2018
2 parents abfed04 + 7951b8a commit f8f880195e3e0d06e612d258dcbd7d6d3068d4f0
@@ -90,14 +90,14 @@ const a11y = withName('a11y')(done => {

const vnu = withName('vnu')(() => accessibility.vnu(getComponents()));

// gulp lint:a11y
// gulp lint:a11y --components path
// gulp lint:a11y --components path,tabs,data-tables
// npm run gulp -- lint:a11y
// npm run gulp -- lint:a11y --components path
// npm run gulp -- lint:a11y --components path,tabs,data-tables
gulp.task('lint:a11y', gulp.series('generate:examples:wrapped', a11y));

// gulp lint:vnu
// gulp lint:vnu --components path
// gulp lint:vnu --components path,tabs,data-tables
// npm run gulp -- lint:vnu
// npm run gulp -- lint:vnu --components path
// npm run gulp -- lint:vnu --components path,tabs,data-tables
gulp.task('lint:vnu', gulp.series('generate:examples:wrapped', vnu));

gulp.task('lint:sass', lint.sass);
@@ -60,10 +60,16 @@ export let Checkbox = props => {
defaultChecked={props.checked}
aria-describedby={props.errorId}
tabIndex={props.tabIndex}
aria-labelledby={
props.labelId && props.groupId
? props.labelId + ' ' + props.groupId
: null
}
/>
<label
className={classNames('slds-checkbox__label')}
htmlFor={props.id ? props.id : uniqueId}
id={props.labelId}
>
<span className="slds-checkbox_faux" />
{props.label && (

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -82,19 +82,14 @@ it('renders a product table', () =>
it('renders an advanced data table with radio group', () =>
matchesMarkupAndStyle(
<AdvancedDataTable>
<Thead
columns={columns}
hasNoSelectability
radioGroupId="radio-group-header"
label="Choose a Row to Select"
/>
<Thead columns={columns} isSingleSelect />
<tbody>
{_.times(rows.length, i => (
<AdvancedDataTableTr
key={i}
index={i + 1}
{...rows[i]}
radioGroupId="radio-group-header"
isSingleSelect
/>
))}
</tbody>
@@ -345,19 +345,14 @@ export let examples = [
label: 'Radio Group',
element: (
<Table>
<Thead
columns={columns}
hasNoSelectability
radioGroupId={radioGroupCommonId}
label="Choose a Row to Select"
/>
<Thead columns={columns} isSingleSelect />
<tbody>
{_.times(rows.length, i => (
<AdvancedDataTableTr
key={i}
index={i + 1}
{...rows[i]}
radioGroupId={radioGroupCommonId}
isSingleSelect
/>
))}
</tbody>
@@ -18,6 +18,8 @@ import { Score } from '../dynamic-icons/score/example';
import SvgIcon from '../../shared/svg-icon';
import { Radio } from '../radio-group/base/example';

const checkboxRadioGroupHeaderId = 'check-group-header';

export const InlineEditTableContainer = props => (
<div className="slds-table_edit_container slds-is-relative">
{props.children}
@@ -51,18 +53,18 @@ export const AdvancedDataTable = props => (
/**
* @name Thead - thead block for advanced, inline, and product edit grids
* @param {*} props
* @prop {array} columnHeaderIcons - List of column names->icon name blocks which show an icon
* @prop {array} columns - Grid columns
* @prop {boolean} actionableMode - Specifies whether the grid is in actionable or navigation mode
* @prop {array} columnHeaderIcons - List of column names->icon name blocks which show an icon
* @prop {boolean} hasErrorColumn - Specifies whether the grid has a errors column
* @prop {boolean} hasFocus - Specifies whether a cell in the thead is in user focus
* @prop {boolean} hasNoSelectability - Specifies whether the thead should not contain a "select all" checkbox
* @prop {boolean} hasMenus - Specifies whether the cells in the thead have a menu button
* @prop {boolean} hasNoSelectability - Specifies whether the thead should not contain a "select all" checkbox
* @prop {boolean} isSingleSelect - Specifies if the row selection uses radio buttons
* @prop {boolean} selectAll - Specifies whether the select all checkbox is marked
* @prop {string} mainColumnWidth - Specifies width of main columns
* @prop {string} singleColumnWidth - Specifies width of a specific column
* @prop {string} sortDirection - Specifies the sort direction of a specific column
* @prop {string} radioGroupId - common id of radio group
*/
export const Thead = props => {
const selectAllColumnWidth = props.hasErrorColumn ? '2rem' : '3.25rem';
@@ -73,7 +75,7 @@ export const Thead = props => {
<tr className="slds-line-height_reset">
{props.hasErrorColumn ? <ErrorsTh /> : null}

{props.hasNoSelectability ? null : (
{props.hasNoSelectability || props.isSingleSelect ? null : (
<SelectAllTh
actionableMode={props.actionableMode}
checked={props.selectAll}
@@ -82,13 +84,9 @@ export const Thead = props => {
/>
)}

{props.radioGroupId ? (
<RadioGroupTh
style={{ width: selectAllColumnWidth }}
radioGroupId={props.radioGroupId}
label={props.label}
/>
) : null}
{props.isSingleSelect && (
<RadioGroupTh style={{ width: selectAllColumnWidth }} />
)}

{_.times(props.columns.length, i => (
<Th
@@ -278,12 +276,17 @@ export let Th = props => {
*/
export const SelectAllTh = props => (
<th style={props.style} className={props.className} scope="col">
<span id={checkboxRadioGroupHeaderId} className="slds-assistive-text">
Choose a row
</span>
<div className="slds-th__action slds-th__action_form">
<Checkbox
tabIndex={props.actionableMode ? '0' : '-1'}
labelId="check-select-all-label"
label="Select All"
hideLabel
checked={props.checked ? true : null}
groupId={checkboxRadioGroupHeaderId}
/>
</div>
</th>
@@ -293,17 +296,12 @@ export const SelectAllTh = props => (
* @name RadioGroupTh - Radio group column header
* @param {*} props
* @prop {object} style - React style object
* @prop {string} radioGroupId - common id of radio group
* @prop {string} label - header text for radio group column
*/
export const RadioGroupTh = props => (
<th
className={props.className}
scope="col"
style={props.style}
id={props.radioGroupId}
>
<span className="slds-assistive-text">{props.label}</span>
<th className={props.className} scope="col" style={props.style}>
<span id="radio-group-header" className="slds-assistive-text">
Choose a row to select
</span>
</th>
);

@@ -337,6 +335,7 @@ export const ErrorsTh = props => (
* @prop {boolean} actionableMode - Specifies whether the grid is in actionable or navigation mode
* @prop {boolean} hasFocus - Specifies whether a specific cell is in focus
* @prop {boolean} hasScore - Specifies whether a row has a score cell
* @prop {boolean} isSingleSelect - Specifies whether to use a radio button for selection or not
* @prop {boolean} rowSelected
* @prop {integer} index - Row index in the Grid
* @prop {string} accountName
@@ -349,7 +348,6 @@ export const ErrorsTh = props => (
* @prop {string} contact
* @prop {string} recordName
* @prop {string} stage
* @prop {string} radioGroupId - common id of radio group
*/
export const AdvancedDataTableTr = props => (
<AdvancedDataTableTrElement
@@ -361,7 +359,7 @@ export const AdvancedDataTableTr = props => (
inputTabIndex={props.actionableMode ? '0' : '-1'}
checked={props.rowSelected}
index={props.index}
radioGroupId={props.radioGroupId}
isSingleSelect={props.isSingleSelect}
/>
<ReadOnlyBodyTh
actionableMode={props.actionableMode}
@@ -484,11 +482,11 @@ export const AdvancedDataTableBodyTh = props => {
* @prop {boolean} checked - Set checked on the cell checkbox
* @prop {boolean} hasFocus - Determines whether the cell is in user focus
* @prop {boolean} isEditable - Determines whether the cell is editable
* @prop {boolean} isSingleSelect - Specifies whether to use a radio button for selection or not
* @prop {integer} cellTabIndex - Set tabindex on the cell
* @prop {integer} inputTabIndex - Set tabindex on the checkbox
* @prop {integer} index - Grid row index
* @prop {integer} inputTabIndex - Set tabindex on the checkbox
* @prop {string} className
* @prop {string} radioGroupId - common id of radio group
*/
export const SelectRowTd = props => (
<AdvancedDataTableTd
@@ -497,22 +495,24 @@ export const SelectRowTd = props => (
isEditable={props.isEditable}
tabIndex={props.cellTabIndex}
>
{props.radioGroupId ? (
{props.isSingleSelect ? (
<Radio
checked={props.checked}
hideLabel
id={`radio-0${props.index}`}
labelId={`radio-button-label-0${props.index}`}
label={`Select item ${props.index}`}
radioGroupId={props.radioGroupId}
groupId="radio-group-header"
tabIndex={props.inputTabIndex}
/>
) : (
<Checkbox
checked={props.checked}
hideLabel
labelId={`check-button-label-0${props.index}`}
id={`checkbox-0${props.index}`}
label={`Select item ${props.index}`}
groupId={checkboxRadioGroupHeaderId}
tabIndex={props.inputTabIndex}
/>
)}
@@ -4,12 +4,15 @@
import React from 'react';
import ButtonIcon from '../../button-icons/';
import SvgIcon from '../../../shared/svg-icon';
import { Checkbox } from '../../checkbox/base/example';
import classNames from 'classnames';

/// ////////////////////////////////////////
// Partial(s)
/// ////////////////////////////////////////

const checkboxRadioGroupHeaderId = 'check-group-header';

let Table = props => (
<table
className={classNames('slds-table slds-table_bordered', props.className)}
@@ -18,23 +21,20 @@ let Table = props => (
</table>
);

let Checkbox = props => (
<label className="slds-checkbox">
<input
type="checkbox"
name="options"
disabled={props.disabled}
defaultChecked={props.checked}
/>
<span className="slds-checkbox_faux" />
<span className="slds-assistive-text">{props.label}</span>
</label>
);

let HeadRowData = props => (
<tr className="slds-text-title_caps">
<th className="slds-cell-shrink" scope="col">
<Checkbox label="Select All" checked={props.checked} />
<span className="slds-assistive-text" id={checkboxRadioGroupHeaderId}>
Choose a row to select
</span>
<Checkbox
hideLabel
labelId={'check-button-label-all'}
id={'checkbox-all'}
label={'Select all'}
groupId={checkboxRadioGroupHeaderId}
checked={props.checked}
/>
</th>
<th scope="col">
<div className="slds-truncate" title="Close Date">
@@ -127,7 +127,14 @@ let HeadRowData = props => (
let RowData = props => (
<tr className="slds-hint-parent">
<td className="slds-cell-shrink" data-label="Select Row">
<Checkbox label="Select Row" checked={props.checked} />
<Checkbox
hideLabel
labelId={`check-button-label-0${props.index}`}
id={`checkbox-0${props.index}`}
label={`Select item ${props.index}`}
groupId={checkboxRadioGroupHeaderId}
checked={props.checked}
/>
</td>
<th scope="row" data-label="Opportunity Name">
<div className="slds-truncate" title={props.title}>
@@ -187,8 +194,8 @@ let Overflow = props => (
<HeadRowData />
</thead>
<tbody>
<RowData title="Cloudhub" />
<RowData title="Cloudhub + Anypoint Connectors" />
<RowData index="1" title="Cloudhub" />
<RowData index="2" title="Cloudhub + Anypoint Connectors" />
</tbody>
</Table>
</div>
@@ -200,8 +207,8 @@ let Stacked = props => (
<HeadRowData />
</thead>
<tbody>
<RowData title="Cloudhub" />
<RowData title="Cloudhub + Anypoint Connectors" />
<RowData index="1" title="Cloudhub" />
<RowData index="2" title="Cloudhub + Anypoint Connectors" />
</tbody>
</Table>
);
@@ -212,8 +219,8 @@ let Horizontal = props => (
<HeadRowData />
</thead>
<tbody>
<RowData title="Cloudhub" />
<RowData title="Cloudhub + Anypoint Connectors" />
<RowData index="1" title="Cloudhub" />
<RowData index="2" title="Cloudhub + Anypoint Connectors" />
</tbody>
</Table>
);
@@ -47,8 +47,8 @@ export let Radio = props => {
tabIndex={props.tabIndex}
aria-describedby={props.errorId}
aria-labelledby={
props.labelId && props.radioGroupId
? props.labelId + ' ' + props.radioGroupId
props.labelId && props.groupId
? props.labelId + ' ' + props.groupId
: null
}
/>

0 comments on commit f8f8801

Please sign in to comment.
You can’t perform that action at this time.