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

[terra-table] Allow consumers to hide table column headers #1843

Merged
merged 21 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions packages/terra-framework-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

* Added
* Added documentation for the new `terra-table` component.
* Added test to cover enabling zebra striping for the `terra-table` component.

## 1.41.0 - (October 17, 2023)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import TableWithoutHeaders from './TableWithoutHeaders?dev-site-example';

<TableWithoutHeaders title='Table Without Column Headers' />
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React from 'react';
import Table from 'terra-table';

const tableDataJSON = {
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' },
{ id: 'Column-10', displayName: 'Not Selectable', isSelectable: false },
adoroshk marked this conversation as resolved.
Show resolved Hide resolved
],
rows: [
{
id: '1',
cells: [
{ content: 'Fleck, Arthur' },
{ content: '1007-MTN' },
{ content: 'Unstable' },
{ content: 'Inpatient, 2 months' },
{ content: '' },
{ content: 'Quinzell, Harleen' },
{ content: '' },
{ isMasked: true },
{ isMasked: true },
{ content: 'Admitting Physician' },
{ content: '', isSelectable: false },
],
},
{
id: '2',
isSelected: true,
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' },
{ content: '', isSelectable: false },
],
},
{
id: '3',
cells: [
{ content: 'Parker, Peter' },
{ content: '1018-MTN-DR' },
{ content: 'Severe' },
{ content: 'Inpatient, 2 days' },
{ content: 'Aspirin' },
{ content: 'Grayson, Richard' },
{ content: '' },
{ content: '' },
{ isMasked: true },
{ content: 'Primary Care Physician' },
{ content: '', isSelectable: false },
],
},
],
};

const TableWithoutHeaders = () => {
const { cols, rows } = tableDataJSON;

return (
<Table
id="table-without-headers"
overflowColumns={cols}
rows={rows}
hasColumnHeaders={false}
/>
);
};

export default TableWithoutHeaders;
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React from 'react';
import Table from 'terra-table';

const tableDataJSON = {
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' },
{ id: 'Column-10', displayName: 'Not Selectable', isSelectable: false },
],
rows: [
{
id: '1',
cells: [
{ content: 'Fleck, Arthur' },
{ content: '1007-MTN' },
{ content: 'Unstable' },
{ content: 'Inpatient, 2 months' },
{ content: '' },
{ content: 'Quinzell, Harleen' },
{ content: '' },
{ isMasked: true },
{ isMasked: true },
{ content: 'Admitting Physician' },
{ content: '', isSelectable: false },
],
},
{
id: '2',
isSelected: true,
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' },
{ content: '', isSelectable: false },
],
},
{
id: '3',
cells: [
{ content: 'Parker, Peter' },
{ content: '1018-MTN-DR' },
{ content: 'Severe' },
{ content: 'Inpatient, 2 days' },
{ content: 'Aspirin' },
{ content: 'Grayson, Richard' },
{ content: '' },
{ content: '' },
{ isMasked: true },
{ content: 'Primary Care Physician' },
{ content: '', isSelectable: false },
],
},
],
};

const TableWithoutHeaders = () => {
const { cols, rows } = tableDataJSON;

return (
<Table
id="table-without-headers"
overflowColumns={cols}
rows={rows}
hasColumnHeaders={false}
/>
);
};

export default TableWithoutHeaders;
1 change: 1 addition & 0 deletions packages/terra-table/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

* Changed
* Updated the table component so that the cell dive-in logic would not execute when not in the grid context.
* Updated the table component to allow consumers to control the visibility of column headers in the table.

## 5.0.0-alpha.0 - (October 17, 2023)

Expand Down
19 changes: 18 additions & 1 deletion packages/terra-table/src/Table.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ const propTypes = {
hasSelectableRows: PropTypes.bool,

/**
* Boolean indicating whether or not the table should allow entire rows to be selectable. An additional column will be
* rendered to allow for row selection to occur.
*/
hasColumnHeaders: PropTypes.bool,

/*
* Boolean specifying whether or not the table should have zebra striping for rows.
*/
isStriped: PropTypes.bool,
Expand All @@ -116,6 +122,7 @@ const defaultProps = {
pinnedColumns: [],
overflowColumns: [],
rows: [],
hasColumnHeaders: true,
};

const defaultColumnMinimumWidth = 60;
Expand All @@ -136,6 +143,7 @@ function Table(props) {
onColumnSelect,
onCellSelect,
hasSelectableRows,
hasColumnHeaders,
isStriped,
rowHeaderIndex,
} = props;
Expand Down Expand Up @@ -291,19 +299,28 @@ function Table(props) {
role={gridContext.role}
aria-labelledby={ariaLabelledBy}
aria-label={ariaLabel}
className={cx('table', theme.className)}
className={cx('table', theme.className, { headerless: !hasColumnHeaders })}
{...(activeIndex != null && { onMouseUp, onMouseMove, onMouseLeave: onMouseUp })}
>
<ColumnContext.Provider
value={columnContextValue}
>
<colgroup>
{tableColumns.map((column) => (
// eslint-disable-next-line react/forbid-dom-props
<col key={column.id} style={{ width: `${column.width}px` }} />
))}
</colgroup>

{hasColumnHeaders && (
<ColumnHeader
columns={tableColumns}
headerHeight={columnHeaderHeight}
tableHeight={tableHeight}
onResizeMouseDown={onResizeMouseDown}
onColumnSelect={handleColumnSelect}
/>
)}
<tbody>
{rows.map((row, index) => (
<Row
Expand Down
11 changes: 11 additions & 0 deletions packages/terra-table/src/Table.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,15 @@
outline-offset: var(--terra-table-cell-focus-outline-offset, -2px);
}
}

/* stylelint-disable selector-max-compound-selectors */
.headerless {
tr:first-child {
td,
th {
border-top: var(--terra-table-headerless-first-row-border-top, 1px solid #dedfe0);
}
}
}
/* stylelint-enable selector-max-compound-selectors */
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
.clinical-lowlight-theme {
--terra-table-cell-focus-outline: 3px dashed #fff;
--terra-table-cell-focus-outline-offset: -2px;
--terra-table-headerless-first-row-border-top: 1px solid #181b1d;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
.orion-fusion-theme {
--terra-table-cell-focus-outline: 3px dashed #000;
--terra-table-cell-focus-outline-offset: -2px;
--terra-table-headerless-first-row-border-top: 1px solid #c8cacb;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ const ColumnHeaderCell = (props) => {
onMouseDown={isSelectable && onColumnSelect ? handleMouseDown : undefined}
onKeyDown={isSelectable && onColumnSelect ? handleKeyDown : undefined}
// eslint-disable-next-line react/forbid-dom-props
style={{ width: `${width}px`, height: headerHeight, left: cellLeftEdge }}
style={{ height: headerHeight, left: cellLeftEdge }}
>
<div className={cx('header-container')} role={displayName && 'button'}>
{errorIcon}
Expand Down
7 changes: 0 additions & 7 deletions packages/terra-table/tests/jest/ColumnHeaderCell.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ describe('ColumnHeaderCell', () => {
expect(columnHeader.props().role).toBe('columnheader');
expect(columnHeader.props().scope).toBe('col');
expect(columnHeader.props().tabIndex).toEqual(undefined);
expect(columnHeader.props().style.width).toBe('100px');
expect(columnHeader.props().style.height).toBe('150px');

const headerContainer = columnHeader.find('.header-container[role="button"]');
Expand Down Expand Up @@ -69,7 +68,6 @@ describe('ColumnHeaderCell', () => {
expect(columnHeader.props().scope).toBe('col');
expect(columnHeader.props().tabIndex).toEqual(undefined);
expect(columnHeader.props()['aria-sort']).toBe('ascending');
expect(columnHeader.props().style.width).toBe('100px');
expect(columnHeader.props().style.height).toBe('150px');

const headerContainer = columnHeader.find('.header-container[role="button"]');
Expand Down Expand Up @@ -104,7 +102,6 @@ describe('ColumnHeaderCell', () => {
expect(columnHeader.props().scope).toBe('col');
expect(columnHeader.props().tabIndex).toEqual(undefined);
expect(columnHeader.props()['aria-sort']).toBe('descending');
expect(columnHeader.props().style.width).toBe('100px');
expect(columnHeader.props().style.height).toBe('150px');

const headerContainer = columnHeader.find('.header-container[role="button"]');
Expand Down Expand Up @@ -139,7 +136,6 @@ describe('ColumnHeaderCell', () => {
expect(columnHeader.props().scope).toBe('col');
expect(columnHeader.props().tabIndex).toEqual(undefined);
expect(columnHeader.props()['aria-sort']).toBeUndefined();
expect(columnHeader.props().style.width).toBe('100px');
expect(columnHeader.props().style.height).toBe('150px');

const headerContainer = columnHeader.find('.header-container[role="button"]');
Expand Down Expand Up @@ -175,7 +171,6 @@ describe('ColumnHeaderCell', () => {
expect(columnHeader.props().scope).toBe('col');
expect(columnHeader.props().tabIndex).toEqual(undefined);
expect(columnHeader.props()['aria-sort']).toBe('ascending');
expect(columnHeader.props().style.width).toBe('100px');
expect(columnHeader.props().style.height).toBe('150px');

const headerContainer = columnHeader.find('.header-container[role="button"]');
Expand Down Expand Up @@ -217,7 +212,6 @@ describe('ColumnHeaderCell', () => {
expect(columnHeader.props().tabIndex).toEqual(0);
expect(columnHeader.props()['aria-sort']).toBe('ascending');
expect(columnHeader.props().onMouseDown).toBeDefined();
expect(columnHeader.props().style.width).toBe('100px');
expect(columnHeader.props().style.height).toBe('150px');

const headerContainer = columnHeader.find('.header-container[role="button"]');
Expand Down Expand Up @@ -259,7 +253,6 @@ describe('ColumnHeaderCell', () => {
expect(columnHeader.props().tabIndex).toEqual(undefined);
expect(columnHeader.props()['aria-sort']).toBe('ascending');
expect(columnHeader.props().onMouseDown).toBeUndefined();
expect(columnHeader.props().style.width).toBe('100px');
expect(columnHeader.props().style.height).toBe('150px');

const headerContainer = columnHeader.find('.header-container[role="button"]');
Expand Down
38 changes: 38 additions & 0 deletions packages/terra-table/tests/jest/Table.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,44 @@ describe('Table', () => {

expect(wrapper).toMatchSnapshot();
});

it('verifies that the hasColumnHeaders prop hides the table column headers', () => {
const wrapper = shallowWithIntl(
<IntlProvider locale="en">
<Table
id="test-terra-table"
overflowColumns={tableData.cols}
rows={tableData.rows}
hasColumnHeaders={false}
/>
</IntlProvider>,
).dive().dive();

// Verify that column headers are not present
const columnHeader = wrapper.find(ColumnHeader);
expect(columnHeader).toHaveLength(0);

expect(wrapper).toMatchSnapshot();
});

it('verifies that the hasColumnHeaders prop hides the table column headers', () => {
const wrapper = shallowWithIntl(
<IntlProvider locale="en">
<Table
id="test-terra-table"
overflowColumns={tableData.cols}
rows={tableData.rows}
defaultColumnWidth={150}
/>
</IntlProvider>,
).dive().dive();

// Verify that column headers are not present
const column = wrapper.find('col').get(0);
expect(column.props.style.width).toBe('150px');

expect(wrapper).toMatchSnapshot();
});
});

describe('with pinned columns', () => {
Expand Down
Loading
Loading