diff --git a/CHANGELOG.md b/CHANGELOG.md index 3e346240b73..f8844605c86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Added `tableCaption` prop to `EuiBasicTable` and improved the default one ([#2782](https://github.com/elastic/eui/pull/2782)) - Changed SASS comments to non-compiled comments in invisibles files ([#2807](https://github.com/elastic/eui/pull/2807)) +- Added `rowHeader` prop to `EuiBasicTable` to allow consumers to set the identifying cell in a row ([#2802](https://github.com/elastic/eui/pull/2802)) ## [`18.3.0`](https://github.com/elastic/eui/tree/v18.3.0) diff --git a/src-docs/src/views/tables/basic/basic.js b/src-docs/src/views/tables/basic/basic.js index bd104ed0918..746500eb0ca 100644 --- a/src-docs/src/views/tables/basic/basic.js +++ b/src-docs/src/views/tables/basic/basic.js @@ -121,6 +121,7 @@ export const Table = () => { return ( void' }, }, + rowHeader: { + description: + 'Indicates which column should be used as the identifying cell in each row. Should match a "field" prop in FieldDataColumn', + required: false, + type: { name: 'string' }, + }, tableCaption: { description: 'Describes the content of the table. If not specified, the caption will be "This table contains {itemCount} rows."', diff --git a/src-docs/src/views/tables/selection/selection.js b/src-docs/src/views/tables/selection/selection.js index 4a199a8584e..ed26a21bdd0 100644 --- a/src-docs/src/views/tables/selection/selection.js +++ b/src-docs/src/views/tables/selection/selection.js @@ -215,6 +215,7 @@ export class Table extends Component { isSelectable={true} selection={selection} onChange={this.onTableChange} + rowHeader="firstName" /> ); diff --git a/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap b/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap index e8b98946ae7..45c31a06558 100644 --- a/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap +++ b/src/components/basic_table/__snapshots__/basic_table.test.tsx.snap @@ -69,6 +69,7 @@ exports[`EuiBasicTable cellProps renders cells with custom props from a callback } } onClick={[Function]} + setScopeRow={false} textOnly={true} > name1 @@ -89,6 +90,7 @@ exports[`EuiBasicTable cellProps renders cells with custom props from a callback } } onClick={[Function]} + setScopeRow={false} textOnly={true} > name2 @@ -109,6 +111,7 @@ exports[`EuiBasicTable cellProps renders cells with custom props from a callback } } onClick={[Function]} + setScopeRow={false} textOnly={true} > name3 @@ -189,6 +192,7 @@ exports[`EuiBasicTable cellProps renders rows with custom props from an object 1 } } onClick={[Function]} + setScopeRow={false} textOnly={true} > name1 @@ -209,6 +213,7 @@ exports[`EuiBasicTable cellProps renders rows with custom props from an object 1 } } onClick={[Function]} + setScopeRow={false} textOnly={true} > name2 @@ -229,6 +234,7 @@ exports[`EuiBasicTable cellProps renders rows with custom props from an object 1 } } onClick={[Function]} + setScopeRow={false} textOnly={true} > name3 @@ -531,6 +537,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -544,6 +551,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > 1 @@ -557,6 +565,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > 20 @@ -574,6 +583,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -587,6 +597,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > 2 @@ -600,6 +611,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > 21 @@ -617,6 +629,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -630,6 +643,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > 3 @@ -643,6 +657,7 @@ exports[`EuiBasicTable footers do not render without a column footer definition "render": undefined, } } + setScopeRow={false} textOnly={true} > 22 @@ -780,6 +795,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -793,6 +809,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > 1 @@ -806,6 +823,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > 20 @@ -834,6 +852,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -847,6 +866,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > 2 @@ -860,6 +880,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > 21 @@ -888,6 +909,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -901,6 +923,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > 3 @@ -914,6 +937,7 @@ exports[`EuiBasicTable footers render with pagination, selection, sorting, and f "render": undefined, } } + setScopeRow={false} textOnly={true} > 22 @@ -1031,6 +1055,7 @@ exports[`EuiBasicTable itemIdToExpandedRowMap renders an expanded row 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -1061,6 +1086,7 @@ exports[`EuiBasicTable itemIdToExpandedRowMap renders an expanded row 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -1078,6 +1104,7 @@ exports[`EuiBasicTable itemIdToExpandedRowMap renders an expanded row 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -1159,6 +1186,7 @@ exports[`EuiBasicTable rowProps renders rows with custom props from a callback 1 "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -1181,6 +1209,7 @@ exports[`EuiBasicTable rowProps renders rows with custom props from a callback 1 "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -1203,6 +1232,7 @@ exports[`EuiBasicTable rowProps renders rows with custom props from a callback 1 "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -1285,6 +1315,7 @@ exports[`EuiBasicTable rowProps renders rows with custom props from an object 1` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -1307,6 +1338,7 @@ exports[`EuiBasicTable rowProps renders rows with custom props from an object 1` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -1329,6 +1361,7 @@ exports[`EuiBasicTable rowProps renders rows with custom props from an object 1` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -1408,6 +1441,7 @@ exports[`EuiBasicTable with pagination - 2nd page 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -1425,6 +1459,7 @@ exports[`EuiBasicTable with pagination - 2nd page 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -1514,6 +1549,7 @@ exports[`EuiBasicTable with pagination 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -1531,6 +1567,7 @@ exports[`EuiBasicTable with pagination 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -1548,6 +1585,7 @@ exports[`EuiBasicTable with pagination 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -1738,6 +1776,7 @@ exports[`EuiBasicTable with pagination and selection 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -1766,6 +1805,7 @@ exports[`EuiBasicTable with pagination and selection 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -1794,6 +1834,7 @@ exports[`EuiBasicTable with pagination and selection 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -1883,6 +1924,7 @@ exports[`EuiBasicTable with pagination, hiding the per page options 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -1900,6 +1942,7 @@ exports[`EuiBasicTable with pagination, hiding the per page options 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -1917,6 +1960,7 @@ exports[`EuiBasicTable with pagination, hiding the per page options 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -2052,6 +2096,7 @@ exports[`EuiBasicTable with pagination, selection and sorting 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -2080,6 +2125,7 @@ exports[`EuiBasicTable with pagination, selection and sorting 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -2108,6 +2154,7 @@ exports[`EuiBasicTable with pagination, selection and sorting 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -2249,6 +2296,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and a single record a "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -2306,6 +2354,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and a single record a "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -2363,6 +2412,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and a single record a "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -2525,6 +2575,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and column dataType 1 "render": undefined, } } + setScopeRow={false} textOnly={true} > 1 @@ -2553,6 +2604,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and column dataType 1 "render": undefined, } } + setScopeRow={false} textOnly={true} > 2 @@ -2581,6 +2633,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and column dataType 1 "render": undefined, } } + setScopeRow={false} textOnly={true} > 3 @@ -2715,6 +2768,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and column renderer 1 "render": undefined, } } + setScopeRow={false} textOnly={false} > NAME1 @@ -2743,6 +2797,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and column renderer 1 "render": undefined, } } + setScopeRow={false} textOnly={false} > NAME2 @@ -2771,6 +2826,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and column renderer 1 "render": undefined, } } + setScopeRow={false} textOnly={false} > NAME3 @@ -2912,6 +2968,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and multiple record a "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -2975,6 +3032,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and multiple record a "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -3038,6 +3096,7 @@ exports[`EuiBasicTable with pagination, selection, sorting and multiple record a "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -3206,6 +3265,7 @@ exports[`EuiBasicTable with pagination, selection, sorting, column renderer and "render": undefined, } } + setScopeRow={false} textOnly={false} > x @@ -3234,6 +3294,7 @@ exports[`EuiBasicTable with pagination, selection, sorting, column renderer and "render": undefined, } } + setScopeRow={false} textOnly={false} > xx @@ -3262,6 +3323,7 @@ exports[`EuiBasicTable with pagination, selection, sorting, column renderer and "render": undefined, } } + setScopeRow={false} textOnly={false} > xxx @@ -3350,6 +3412,7 @@ exports[`EuiBasicTable with sortable columns and sorting disabled 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -3367,6 +3430,7 @@ exports[`EuiBasicTable with sortable columns and sorting disabled 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -3384,6 +3448,7 @@ exports[`EuiBasicTable with sortable columns and sorting disabled 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 @@ -3478,6 +3543,7 @@ exports[`EuiBasicTable with sorting 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name1 @@ -3495,6 +3561,7 @@ exports[`EuiBasicTable with sorting 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name2 @@ -3512,6 +3579,7 @@ exports[`EuiBasicTable with sorting 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > name3 diff --git a/src/components/basic_table/__snapshots__/in_memory_table.test.tsx.snap b/src/components/basic_table/__snapshots__/in_memory_table.test.tsx.snap index 4e021fa7798..82cc6ec84f3 100644 --- a/src/components/basic_table/__snapshots__/in_memory_table.test.tsx.snap +++ b/src/components/basic_table/__snapshots__/in_memory_table.test.tsx.snap @@ -193,6 +193,7 @@ exports[`EuiInMemoryTable behavior pagination 1`] = ` "render": undefined, } } + setScopeRow={false} textOnly={true} > extends Omit { columns: Array>; error?: string; tableCaption?: string; + rowHeader?: string; hasActions?: boolean; isExpandable?: boolean; isSelectable?: boolean; @@ -441,6 +442,7 @@ export class EuiBasicTable extends Component< rowProps, cellProps, tableCaption, + rowHeader, tableLayout, ...rest } = this.props; @@ -826,6 +828,7 @@ export class EuiBasicTable extends Component< selection, isSelectable, hasActions, + rowHeader, itemIdToExpandedRowMap = {}, isExpandable, } = this.props; @@ -861,12 +864,14 @@ export class EuiBasicTable extends Component< ); calculatedHasActions = true; } else if ((column as EuiTableFieldDataColumnType).field) { + const fieldDataColumn = column as EuiTableFieldDataColumnType; cells.push( this.renderItemFieldDataCell( itemId, item, column as EuiTableFieldDataColumnType, - columnIndex + columnIndex, + fieldDataColumn.field === rowHeader ) ); } else { @@ -1051,7 +1056,8 @@ export class EuiBasicTable extends Component< itemId: ItemId, item: T, column: EuiTableFieldDataColumnType, - columnIndex: number + columnIndex: number, + setScopeRow: boolean ) { const { field, render, dataType } = column; @@ -1060,7 +1066,7 @@ export class EuiBasicTable extends Component< const value = get(item, field as string); const content = contentRenderer(value, item); - return this.renderItemCell(item, column, key, content); + return this.renderItemCell(item, column, key, content, setScopeRow); } renderItemComputedCell( @@ -1075,14 +1081,15 @@ export class EuiBasicTable extends Component< const contentRenderer = render || this.getRendererForDataType(); const content = contentRenderer(item); - return this.renderItemCell(item, column, key, content); + return this.renderItemCell(item, column, key, content, false); } renderItemCell( item: T, column: EuiBasicTableColumn, key: string | number, - content: ReactNode + content: ReactNode, + setScopeRow: boolean ) { const { align, @@ -1112,6 +1119,7 @@ export class EuiBasicTable extends Component< align={columnAlign} isExpander={isExpander} textOnly={textOnly || !render} + setScopeRow={setScopeRow} mobileOptions={{ ...mobileOptions, render: diff --git a/src/components/table/_mixins.scss b/src/components/table/_mixins.scss index 0bd10b89acc..30d65d88d84 100644 --- a/src/components/table/_mixins.scss +++ b/src/components/table/_mixins.scss @@ -2,6 +2,8 @@ vertical-align: middle; border-top: $euiBorderThin; border-bottom: $euiBorderThin; + font-weight: inherit; + text-align: inherit; } @mixin euiTableCellCheckbox { diff --git a/src/components/table/table_row_cell.tsx b/src/components/table/table_row_cell.tsx index 856a119e2c7..92edc63c41d 100644 --- a/src/components/table/table_row_cell.tsx +++ b/src/components/table/table_row_cell.tsx @@ -109,6 +109,10 @@ interface EuiTableRowCellProps { */ mobileOptions?: EuiTableRowCellMobileOptionsShape & EuiTableRowCellSharedPropsShape; + /** + * Indicates whether the cell should be marked as the heading for its row + */ + setScopeRow?: boolean; } type Props = CommonProps & @@ -121,6 +125,7 @@ export const EuiTableRowCell: FunctionComponent = ({ children, className, truncateText, + setScopeRow, showOnHover, textOnly = true, hasActions, @@ -202,20 +207,23 @@ export const EuiTableRowCell: FunctionComponent = ({ const hideForMobileClasses = 'euiTableRowCell--hideForMobile'; const showForMobileClasses = 'euiTableRowCell--hideForDesktop'; - let cellRender; - + const Element = setScopeRow ? 'th' : 'td'; + const sharedProps = { + scope: setScopeRow ? 'row' : undefined, + style: styleObj, + ...rest, + }; if (mobileOptions.show === false || hideForMobile) { - cellRender = ( - + {...sharedProps}>
{childrenNode}
- + ); } else { - cellRender = ( - + return ( + {/* Mobile-only header */} {(mobileOptions.header || header) && !isMobileHeader && (
= ({ ) : (
{childrenNode}
)} - + ); } - - return cellRender; };