Skip to content
This repository has been archived by the owner on May 24, 2024. It is now read-only.

[terra-table] Allow table to have no row header #2053

Merged
merged 2 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/terra-framework-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

* Added
* Added examples and tests for a large menu in the `terra-menu`.
* Added examples for `table-table` with no row headers.

## 1.70.0 - (February 29, 2024)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Badge } from "terra-table/package.json?dev-site-package";
import TableWithoutRowHeader from "./TableWithoutRowHeader?dev-site-example";

# Default Table without row header

### Description

This example demonstrates a basic [Table](/components/cerner-terra-framework-docs/table/about) component implementation without row header.

<TableWithoutRowHeader />
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';
import Table from 'terra-table';

const tableData = {
cols: [
{ id: 'Column-0', displayName: 'Patient' },
{ id: 'Column-1', displayName: 'Location' },
{ id: 'Column-2', displayName: 'Illness Severity' },
{ id: 'Column-3', displayName: 'Visit' },
{ id: 'Column-4', displayName: 'Allergy' },
{ id: 'Column-5', displayName: 'Primary Contact' },
{ id: 'Column-6', displayName: 'Generic Order Counts' },
{ id: 'Column-7', displayName: 'Patient Age' },
{ id: 'Column-8', displayName: 'Medication History' },
{ id: 'Column-9', displayName: 'My Relationship' },
],
rows: [
{
id: '1',
cells: [
{ content: 'Fleck, Arthur' },
{ content: '1007-MTN' },
{ content: 'Unstable' },
{ content: 'Inpatient, 2 months' },
{ content: '' },
{ content: 'Quinzell, Harleen' },
{ content: '' },
{ isMasked: true, maskedLabel: 'Age Hidden' },
{ isMasked: true },
{ content: 'Admitting Physician' },
],
},
{
id: '2',
cells: [
{ content: 'Wayne, Bruce' },
{ content: '1007-MTN-DR' },
{ content: 'Stable' },
{ content: 'Outpatient, 2 days' },
{ content: 'Phytochemicals' },
{ content: 'Grayson, Richard' },
{ content: '' },
{ content: '' },
{ isMasked: true },
{ content: 'Admitting Physician' },
],
},
],
};

const TableWithoutRowHeader = () => (
<Table
id="table-without-row-header"
overflowColumns={tableData.cols}
rows={tableData.rows}
rowHeaderIndex={-1}
ariaLabel="Table"
/>
);

export default TableWithoutRowHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import Table from 'terra-table';
import tableData from './mockTableData.json';

const TableWithoutRowHeader = () => {
const { cols, rows } = tableData;

return (
<Table
id="table-without-row-header"
overflowColumns={cols}
rows={rows}
rowHeaderIndex={-1}
columnHeaderHeight="50px"
ariaLabel="table"
/>
);
};

export default TableWithoutRowHeader;
3 changes: 3 additions & 0 deletions packages/terra-table/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Added
* Added support for table with no row headers.

## 5.9.0 - (February 28, 2024)

* Added
Expand Down
1 change: 1 addition & 0 deletions packages/terra-table/src/Table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const propTypes = {

/**
* A number indicating the index of the column that represents the row header. The index is based on 0 and cannot exceed one less than the number of columns on the table.
* Index can be set to -1 if row headers are not required.
*/
rowHeaderIndex: validateRowHeaderIndex,

Expand Down
4 changes: 2 additions & 2 deletions packages/terra-table/src/proptypes/validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ const validateRowHeaderIndex = (props) => {
return new Error(ERRORS.ROW_HEADER_INDEX_NOT_AN_INTEGER);
}

if (props.rowHeaderIndex < 0) {
return new Error(ERRORS.ROW_HEADER_INDEX_LESS_THAN_ZERO);
if (props.rowHeaderIndex < -1) {
return new Error(ERRORS.ROW_HEADER_INDEX_LESS_THAN_MINUS_ONE);
}

if (props.pinnedColumns.length && props.rowHeaderIndex >= props.pinnedColumns.length) {
Expand Down
9 changes: 8 additions & 1 deletion packages/terra-table/src/subcomponents/Cell.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ const propTypes = {
* With this property the height of the cell will grow to fit the cell content.
*/
rowMinimumHeight: PropTypes.string,

/**
* A zero-based index indicating which column represents the row header.
* Index can be set to -1 if row headers are not required.
*/
rowHeaderIndex: PropTypes.number,
};

const defaultProps = {
Expand Down Expand Up @@ -141,6 +147,7 @@ function Cell(props) {
height,
intl,
rowMinimumHeight,
rowHeaderIndex,
} = props;

const cellRef = useRef();
Expand Down Expand Up @@ -310,7 +317,7 @@ function Cell(props) {

// Determine table cell header attribute values
const sectionHeaderId = sectionId ? `${tableId}-${sectionId} ` : '';
const rowHeaderId = !isRowHeader ? `${tableId}-rowheader-${rowId} ` : '';
const rowHeaderId = !isRowHeader && rowHeaderIndex !== -1 ? `${tableId}-rowheader-${rowId} ` : '';
const columnHeaderId = `${tableId}-${columnId}-headerCell`;

return (
Expand Down
4 changes: 3 additions & 1 deletion packages/terra-table/src/subcomponents/Row.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const propTypes = {

/**
* A zero-based index indicating which column represents the row header.
* Index can be set to -1 if row headers are not required.
*/
rowHeaderIndex: PropTypes.number,
};
Expand Down Expand Up @@ -171,11 +172,12 @@ function Row(props) {
isMasked={cellData.isMasked}
maskedLabel={cellData.maskedLabel}
isSelectable={cellData.isSelectable}
isRowHeader={cellColumnIndex === (rowHeaderIndex + columnIndexOffSet)}
isRowHeader={rowHeaderIndex !== -1 && cellColumnIndex === (rowHeaderIndex + columnIndexOffSet)}
isHighlighted={isHovered || isSelected}
onCellSelect={onCellSelect}
height={height}
rowMinimumHeight={rowMinimumHeight}
rowHeaderIndex={rowHeaderIndex}
>
{cellData.content}
</Cell>
Expand Down
1 change: 1 addition & 0 deletions packages/terra-table/src/subcomponents/Section.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const propTypes = {

/**
* A zero-based index indicating which column represents the row header.
* Index can be set to -1 if row headers are not required.
*/
rowHeaderIndex: PropTypes.number,

Expand Down
2 changes: 1 addition & 1 deletion packages/terra-table/src/utils/constants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const ERRORS = {
ROW_HEADER_INDEX_EXCEEDS_PINNED: 'Prop rowHeaderIndex exceeds the size of pinnedColumns.',
ROW_HEADER_INDEX_LESS_THAN_ZERO: 'Prop rowHeaderIndex must be a positive integer.',
ROW_HEADER_INDEX_LESS_THAN_MINUS_ONE: 'Prop rowHeaderIndex must be either -1 or a positive integer.',
ROW_HEADER_INDEX_NOT_AN_INTEGER: 'Prop rowHeaderIndex must be an integer.',
ACTION_LABEL_MISSING: 'Column action must have label property.',
ACTION_ONCLICK_MISSING: 'Column action must have onClick callback.',
Expand Down
23 changes: 23 additions & 0 deletions packages/terra-table/tests/jest/Row.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,29 @@ describe('Row', () => {
expect(wrapper).toMatchSnapshot();
});

it('creates a row with no row header', () => {
const rowData = tableData.rows[0];

const wrapper = enzyme.shallow(
<Row
rowIndex={99}
id={rowData.id}
tableId="test-table"
height="25px"
cells={rowData.cells}
rowSelectionMode={tableData.rows[0].hasSelectableRows ? 'multiple' : undefined}
displayedColumns={tableData.cols}
rowHeaderIndex={-1}
onCellSelect={jest.fn}
onRowSelect={jest.fn}
/>,
);

const tableRow = wrapper.find('tr.row');
const renderedCells = tableRow.find(Cell);
expect(renderedCells.get(0).props.isRowHeader).toEqual(false);
});

it('verifies the cell is created with the right props', () => {
const rowIndex = 2;

Expand Down
22 changes: 20 additions & 2 deletions packages/terra-table/tests/jest/Table.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import GridContext, { GridConstants } from '../../src/utils/GridContext';
import ERRORS from '../../src/utils/constants';
import Row from '../../src/subcomponents/Row';
import Table from '../../src/Table';
import Cell from '../../src/subcomponents/Cell';

// Source data for tests
const tableData = {
Expand Down Expand Up @@ -182,6 +183,22 @@ describe('Table', () => {
expect(columnHeader).toHaveLength(1);
});

it('verifies that the table created has no row headers', () => {
const wrapper = enzymeIntl.mountWithIntl(
<Table
id="test-terra-table"
pinnedColumns={tableData.cols.slice(0, 2)}
overflowColumns={tableData.cols.slice(2)}
rows={tableData.rows}
rowHeaderIndex={-1}
/>,
);

const firstRow = wrapper.find(Row).at(0);
const firstCell = firstRow.find(Cell).at(0);
expect(firstCell.props().isRowHeader).toEqual(false);
});

it('verifies row selection column header selection', () => {
const mockColumnSelect = jest.fn();

Expand Down Expand Up @@ -340,6 +357,7 @@ describe('Table', () => {

// Validate rows of the first section
const section1Row1 = section1.find('.row').at(0);

expect(section1Row1.props()['aria-rowindex']).toBe(3);
expect(section1Row1.props()['data-row-id']).toBe('1');
const section1Row2 = section1.find('.row').at(1);
Expand Down Expand Up @@ -910,12 +928,12 @@ describe('Error handling - prop types', () => {
<Table
id="test-terra-table"
rows={tableData.rows}
rowHeaderIndex={-1}
rowHeaderIndex={-2}
/>
</IntlProvider>,
).dive();

expect(console.error).toHaveBeenCalledWith(expect.stringContaining(ERRORS.ROW_HEADER_INDEX_LESS_THAN_ZERO)); // eslint-disable-line no-console
expect(console.error).toHaveBeenCalledWith(expect.stringContaining(ERRORS.ROW_HEADER_INDEX_LESS_THAN_MINUS_ONE)); // eslint-disable-line no-console
});

it('throws an error if rowHeaderIndex is greater than the length of pinned columns', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ exports[`Row creates a row with the correct number of cells 1`] = `
isRowHeader={true}
key="1_Column-0"
onCellSelect={[Function]}
rowHeaderIndex={0}
rowId="1"
rowIndex={99}
tableId="test-table"
Expand All @@ -33,6 +34,7 @@ exports[`Row creates a row with the correct number of cells 1`] = `
isRowHeader={false}
key="1_Column-1"
onCellSelect={[Function]}
rowHeaderIndex={0}
rowId="1"
rowIndex={99}
tableId="test-table"
Expand All @@ -46,6 +48,7 @@ exports[`Row creates a row with the correct number of cells 1`] = `
isRowHeader={false}
key="1_Column-2"
onCellSelect={[Function]}
rowHeaderIndex={0}
rowId="1"
rowIndex={99}
tableId="test-table"
Expand Down Expand Up @@ -74,6 +77,7 @@ exports[`Row verifies the cell is created with the right props 1`] = `
isRowHeader={true}
key="3_Column-0"
onCellSelect={[Function]}
rowHeaderIndex={0}
rowId="3"
rowIndex={2}
tableId="test-table"
Expand All @@ -88,6 +92,7 @@ exports[`Row verifies the cell is created with the right props 1`] = `
isRowHeader={false}
key="3_Column-1"
onCellSelect={[Function]}
rowHeaderIndex={0}
rowId="3"
rowIndex={2}
tableId="test-table"
Expand All @@ -103,6 +108,7 @@ exports[`Row verifies the cell is created with the right props 1`] = `
isRowHeader={false}
key="3_Column-2"
onCellSelect={[Function]}
rowHeaderIndex={0}
rowId="3"
rowIndex={2}
tableId="test-table"
Expand Down
Loading
Loading