diff --git a/src/components/flat-table/flat-table-cell/flat-table-cell.style.js b/src/components/flat-table/flat-table-cell/flat-table-cell.style.js
index 020060b2d1..4ea8b82ee6 100644
--- a/src/components/flat-table/flat-table-cell/flat-table-cell.style.js
+++ b/src/components/flat-table/flat-table-cell/flat-table-cell.style.js
@@ -63,7 +63,6 @@ const StyledFlatTableCell = styled.td`
${makeCellSticky &&
css`
- top: auto;
left: ${leftPosition}px;
position: sticky;
`}
diff --git a/src/components/flat-table/flat-table-head/flat-table-head.component.js b/src/components/flat-table/flat-table-head/flat-table-head.component.js
index abc36b3275..ff853a3a37 100644
--- a/src/components/flat-table/flat-table-head/flat-table-head.component.js
+++ b/src/components/flat-table/flat-table-head/flat-table-head.component.js
@@ -1,9 +1,35 @@
-import React from "react";
+import React, { useEffect, useState } from "react";
import PropTypes from "prop-types";
import StyledFlatTableHead from "./flat-table-head.style";
+const getRefs = (length) => Array.from({ length }, () => React.createRef());
+
const FlatTableHead = ({ children }) => {
- return {children};
+ const [rowHeights, setRowHeights] = useState([]);
+ const refs = getRefs(React.Children.count(children));
+
+ useEffect(() => {
+ if (React.Children.count(children) > 1) {
+ setRowHeights(refs.map((ref) => ref.current.clientHeight));
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, []);
+
+ if (React.Children.count(children) === 1) {
+ return {children};
+ }
+
+ return (
+
+ {React.Children.map(children, (child, index) =>
+ React.cloneElement(child, {
+ ...child.props,
+ stickyOffset: rowHeights.slice(0, index).reduce((a, b) => a + b, 0),
+ ref: refs[index],
+ })
+ )}
+
+ );
};
FlatTableHead.propTypes = {
diff --git a/src/components/flat-table/flat-table-header/flat-table-header.style.js b/src/components/flat-table/flat-table-header/flat-table-header.style.js
index 54d24fcf98..5698856c64 100644
--- a/src/components/flat-table/flat-table-header/flat-table-header.style.js
+++ b/src/components/flat-table/flat-table-header/flat-table-header.style.js
@@ -42,7 +42,6 @@ const StyledFlatTableHeader = styled.th`
${makeCellSticky &&
css`
- top: auto;
left: ${leftPosition}px;
position: sticky;
diff --git a/src/components/flat-table/flat-table-row/flat-table-row.component.js b/src/components/flat-table/flat-table-row/flat-table-row.component.js
index c1c446ac5c..b6372b9f1e 100644
--- a/src/components/flat-table/flat-table-row/flat-table-row.component.js
+++ b/src/components/flat-table/flat-table-row/flat-table-row.component.js
@@ -25,6 +25,7 @@ const FlatTableRow = React.forwardRef(
expanded = false,
isSubRow,
isFirstSubRow,
+ stickyOffset,
highlighted,
selected,
subRows,
@@ -140,6 +141,7 @@ const FlatTableRow = React.forwardRef(
ref={rowRef}
rowHeaderIndex={rowHeaderIndex}
colorTheme={colorTheme}
+ stickyOffset={stickyOffset}
{...interactiveRowProps}
>
{React.Children.map(children, (child, index) => {
@@ -208,6 +210,8 @@ FlatTableRow.propTypes = {
isSubRow: PropTypes.bool,
/** @ignore @private */
isFirstSubRow: PropTypes.bool,
+ /** @ignore @private position in header if multiple rows */
+ stickyOffset: PropTypes.number,
};
export default FlatTableRow;
diff --git a/src/components/flat-table/flat-table-row/flat-table-row.style.js b/src/components/flat-table/flat-table-row/flat-table-row.style.js
index f6991c02f7..71b22277e7 100644
--- a/src/components/flat-table/flat-table-row/flat-table-row.style.js
+++ b/src/components/flat-table/flat-table-row/flat-table-row.style.js
@@ -55,6 +55,14 @@ const StyledFlatTableRow = styled.tr`
table-layout: fixed;
width: auto;
+ ${({ stickyOffset }) =>
+ stickyOffset > 0 &&
+ css`
+ && th {
+ top: ${stickyOffset}px;
+ }
+ `}
+
${({ isRowInteractive, theme, rowHeaderIndex }) =>
isRowInteractive &&
css`
@@ -87,8 +95,7 @@ const StyledFlatTableRow = styled.tr`
}
}
`}
-
- ${({ isFirstColumnInteractive, firstCellIndex, theme }) =>
+ ${({ isFirstColumnInteractive, firstCellIndex, theme }) =>
isFirstColumnInteractive &&
css`
td:nth-child(${firstCellIndex + 1}),
@@ -105,7 +112,6 @@ const StyledFlatTableRow = styled.tr`
}
}
`}
-
${({ colorTheme, rowHeaderIndex, theme }) =>
![-1, 0].includes(rowHeaderIndex) &&
css`
@@ -117,8 +123,7 @@ const StyledFlatTableRow = styled.tr`
border-left: 1px solid ${borderColor(colorTheme, theme)};
}
`}
-
- ${({
+ ${({
expandable,
selected,
highlighted,
@@ -237,7 +242,7 @@ const StyledFlatTableRow = styled.tr`
}
`}
`;
- }}
+ }};
`;
StyledFlatTableRow.defaultProps = {
diff --git a/src/components/flat-table/flat-table.spec.js b/src/components/flat-table/flat-table.spec.js
index d67698650e..ff658ad8b3 100644
--- a/src/components/flat-table/flat-table.spec.js
+++ b/src/components/flat-table/flat-table.spec.js
@@ -1,6 +1,8 @@
import React from "react";
import { mount } from "enzyme";
+import { act } from "react-dom/test-utils";
import TestRenderer from "react-test-renderer";
+
import FlatTable from "./flat-table.component";
import FlatTableHead from "./flat-table-head/flat-table-head.component";
import FlatTableBody from "./flat-table-body/flat-table-body.component";
@@ -138,6 +140,78 @@ describe("FlatTable", () => {
});
});
+ describe("when it has a sticky header with multiple rows", () => {
+ let wrapper;
+
+ const render = () => {
+ wrapper = mount(
+
+
+
+
+ header1
+ header2
+ header3
+ header4
+
+
+ header1
+ header2
+ header3
+ header4
+
+
+
+
+ row header
+ cell1
+ cell2
+ cell3
+
+
+ row header
+ cell1
+
+
+
+
+ );
+
+ jest
+ .spyOn(
+ wrapper.find(StyledFlatTableRow).at(0).getDOMNode(),
+ "clientHeight",
+ "get"
+ )
+ .mockImplementation(() => 40);
+ };
+
+ beforeEach(() => {
+ render();
+ });
+
+ afterEach(() => {
+ wrapper.unmount();
+ });
+
+ it("should set the correct 'top' css on each row", () => {
+ act(() => render());
+ wrapper.update();
+
+ expect(
+ wrapper.find(StyledFlatTableRow).at(1).props().stickyOffset
+ ).toEqual(40);
+
+ assertStyleMatch(
+ {
+ top: "40px",
+ },
+ wrapper.find(StyledFlatTableHead).find(StyledFlatTableRow).at(1),
+ { modifier: `&& th` }
+ );
+ });
+ });
+
describe("when FlatTable is a child of Sidebar", () => {
let wrapper;
beforeEach(() => {
diff --git a/src/components/flat-table/flat-table.stories.mdx b/src/components/flat-table/flat-table.stories.mdx
index 8b1d77e299..19128b58c5 100644
--- a/src/components/flat-table/flat-table.stories.mdx
+++ b/src/components/flat-table/flat-table.stories.mdx
@@ -1,54 +1,64 @@
-import { Meta, Props, Preview, Story } from '@storybook/addon-docs/blocks';
-import { useState, useRef } from 'react';
-import StyledSystemProps from '../../../.storybook/utils/styled-system-props';
-import {
- FlatTable,
- FlatTableHead,
- FlatTableBody,
- FlatTableRow,
+import { Meta, Props, Preview, Story } from "@storybook/addon-docs/blocks";
+import { useState, useRef } from "react";
+import StyledSystemProps from "../../../.storybook/utils/styled-system-props";
+import {
+ FlatTable,
+ FlatTableHead,
+ FlatTableBody,
+ FlatTableRow,
FlatTableHeader,
FlatTableRowHeader,
FlatTableCell,
FlatTableCheckbox,
- Sort
-} from '.';
-import BatchSelection from '../batch-selection';
-import IconButton from '../icon-button';
-import Icon from '../icon';
-import Textbox from '../../__experimental__/components/textbox';
-import Pager from '../pager'
-import { ActionPopover, ActionPopoverItem, ActionPopoverMenu } from '../action-popover';
-import { SidebarContext } from '../drawer';
-import Box from '../box';
-
-
+ Sort,
+} from ".";
+import BatchSelection from "../batch-selection";
+import IconButton from "../icon-button";
+import Icon from "../icon";
+import Textbox from "../../__experimental__/components/textbox";
+import Pager from "../pager";
+import {
+ ActionPopover,
+ ActionPopoverItem,
+ ActionPopoverMenu,
+} from "../action-popover";
+import { SidebarContext } from "../drawer";
+import Box from "../box";
+
+
# Flat Table
+
Logically structure content in a grid for the user to enter, view, or work with.
## Contents
+
- [Quick Start](#quick-start)
- [Examples](#examples)
- [Props](#props)
-## Quick Start
+## Quick Start
+
Import all the necessary components from the flat table folder
-```javascript
-import {
- FlatTable,
- FlatTableHead,
- FlatTableBody,
- FlatTableRow,
+```javascript
+import {
+ FlatTable,
+ FlatTableHead,
+ FlatTableBody,
+ FlatTableRow,
FlatTableHeader,
FlatTableRowHeader,
FlatTableCell,
FlatTableCheckbox,
- Sort
-} from 'carbon-react/lib/components/flat-table';
+ Sort,
+} from "carbon-react/lib/components/flat-table";
```
-## Examples
+## Examples
### Default
@@ -94,11 +104,12 @@ import {
### With row headers
+
Any cells preceding the `FlatTableRowHeader`s will automatically also be made sticky as seen in the example below.
-
-
+
+
@@ -145,6 +156,7 @@ Any cells preceding the `FlatTableRowHeader`s will automatically also be made st
### With custom cell paddings
+
Padding can be set on each cell individually by using the spacing props syntax. Check prop tables at the bottom of this document for more information.
@@ -152,27 +164,30 @@ Padding can be set on each cell individually by using the spacing props syntax.
- Name
+
+ Name
+
Location
Relationship Status
Dependents
- {[1,2,3,4].map((key) =>
+ {[1, 2, 3, 4].map((key) => (
John Doe
London
Single
5
- )}
+ ))}
### With custom column width
+
Column width can be set by passing number as a `width` prop to the column header or cell component.
**Column width can't be smaller than the sum of horizontal cell padding and content width.**
@@ -185,33 +200,40 @@ Column width can be set by passing number as a `width` prop to the column header
Location
Notes
-
+
- {[1,2,3,4].map((key) =>
+ {[1, 2, 3, 4].map((key) => (
John Doe
London
-
+
+
+
- {}} icon='graph'>Business
- {}} icon='email'>Email Invoice
+ {}} icon="graph">
+ Business
+
+ {}} icon="email">
+ Email Invoice
+
- )}
+ ))}
### With truncated cell content
-When setting column widths it is also possible to set the content to `truncate`: this will prevent the content from wrapping
-and add ellipsis to any content that overflows the given width. By default the `title` will be set to the children if it
-is a string. However, if the passed children are not a string it is possible to override it by passing in a different
+
+When setting column widths it is also possible to set the content to `truncate`: this will prevent the content from wrapping
+and add ellipsis to any content that overflows the given width. By default the `title` will be set to the children if it
+is a string. However, if the passed children are not a string it is possible to override it by passing in a different
`title` string.
@@ -225,13 +247,19 @@ is a string. However, if the passed children are not a string it is possible to
- {[1,2,3,4].map((key) =>
+ {[1, 2, 3, 4].map((key) => (
- John Doe
- London
-
+
+ John Doe
+
+
+ London
+
+
+
+
- )}
+ ))}
@@ -239,9 +267,11 @@ is a string. However, if the passed children are not a string it is possible to
### With stickyHead prop set to true
+It is possible to have one or any number of header rows set to sticky.
+
-
-
+
+
@@ -285,45 +315,48 @@ is a string. However, if the passed children are not a string it is possible to
### With stickyFooter prop set to true
-
+
{() => {
const rows = [
-
+
John Doe
London
Single
0
,
-
+
Jane Doe
York
Married
2
,
-
+
John Smith
Edinburgh
Single
1
,
-
+
Jane Smith
Newcastle
Married
5
,
-
+
Liz Anya
Stoke
Single
2
,
-
+
Karl Ickbred
Newcastle
Single
0
-
+ ,
];
const [recordsRange, setRecordsRange] = useState({ start: 0, end: 5 });
const [currentPage, setCurrentPage] = useState(1);
@@ -340,21 +373,24 @@ is a string. However, if the passed children are not a string it is possible to
setCurrentPage(newPage);
};
return (
-
-
handlePagination(next, size) }
- pageSizeSelectionOptions={
- [
- { id: '1', name: 1 },
- { id: '5', name: 5 },
+
+ handlePagination(next, size)}
+ pageSizeSelectionOptions={[
+ { id: "1", name: 1 },
+ { id: "5", name: 5 },
]}
- />
- }>
+ />
+ }
+ >
Name
@@ -363,13 +399,11 @@ is a string. However, if the passed children are not a string it is possible to
Dependents
-
- { renderRows() }
-
+ {renderRows()}
);
- }}
+ }}
@@ -378,21 +412,24 @@ of `180px`. There is not enough data to fill the flatTable but the style remains
remains sticky.
-
+
{() => {
const rows = [
-
+
John Doe
London
Single
0
,
-
+
Jane Doe
York
Married
2
-
+ ,
];
const [recordsRange, setRecordsRange] = useState({ start: 0, end: 5 });
const [currentPage, setCurrentPage] = useState(1);
@@ -409,21 +446,24 @@ remains sticky.
setCurrentPage(newPage);
};
return (
-
-
handlePagination(next, size) }
- pageSizeSelectionOptions={
- [
- { id: '1', name: 1 },
- { id: '5', name: 5 },
+
+ handlePagination(next, size)}
+ pageSizeSelectionOptions={[
+ { id: "1", name: 1 },
+ { id: "5", name: 5 },
]}
- />
- }>
+ />
+ }
+ >
Name
@@ -432,35 +472,37 @@ remains sticky.
Dependents
-
- { renderRows() }
-
+ {renderRows()}
);
- }}
+ }}
### With hasMaxHeight
+
By using the `hasMaxHeight` prop you can automatically apply a max-height of 100% to the FlatTable.
-
+
{() => {
const rows = [
-
+
John Doe
London
Single
0
,
-
+
Jane Doe
York
Married
2
-
+ ,
];
const [recordsRange, setRecordsRange] = useState({ start: 0, end: 5 });
const [currentPage, setCurrentPage] = useState(1);
@@ -477,21 +519,25 @@ By using the `hasMaxHeight` prop you can automatically apply a max-height of 100
setCurrentPage(newPage);
};
return (
-
-
handlePagination(next, size) }
- pageSizeSelectionOptions={
- [
- { id: '1', name: 1 },
- { id: '5', name: 5 },
+
+ handlePagination(next, size)}
+ pageSizeSelectionOptions={[
+ { id: "1", name: 1 },
+ { id: "5", name: 5 },
]}
- />
- }>
+ />
+ }
+ >
Name
@@ -500,20 +546,21 @@ By using the `hasMaxHeight` prop you can automatically apply a max-height of 100
Dependents
-
- { renderRows() }
-
+ {renderRows()}
);
- }}
+ }}
### With clickable rows
-
+
@@ -524,25 +571,25 @@ By using the `hasMaxHeight` prop you can automatically apply a max-height of 100
- {} }>
+ {}}>
John Doe
London
Single
0
- {} }>
+ {}}>
Jane Doe
York
Married
2
- {} }>
+ {}}>
John Smith
Edinburgh
Single
1
- {} }>
+ {}}>
Jane Smith
Newcastle
Married
@@ -573,13 +620,13 @@ By using the `hasMaxHeight` prop you can automatically apply a max-height of 100
Single
0
-
+
Jane Doe
York
Married
2
-
+
John Smith
Edinburgh
Single
@@ -599,28 +646,33 @@ By using the `hasMaxHeight` prop you can automatically apply a max-height of 100
### With sorting headers
-
+
-### With a cell spanning the whole row
+### With a cell spanning the whole row
-
-
-
- Name
- Location
- Relationship Status
- Dependents
-
-
-
-
- No results
-
-
-
+
+
+
+ Name
+ Location
+ Relationship Status
+ Dependents
+
+
+
+
+
+ No results
+
+
+
+
@@ -628,34 +680,35 @@ By using the `hasMaxHeight` prop you can automatically apply a max-height of 100
-
-
-
- Parent Name
- Child Name
- Child Age
-
-
-
-
- Jane Smith
- Tim Smith
- 8
-
-
- Chris Smith
- 8
-
-
- Alice Smith
- 12
-
-
-
+
+
+
+ Parent Name
+ Child Name
+ Child Age
+
+
+
+
+ Jane Smith
+ Tim Smith
+ 8
+
+
+ Chris Smith
+ 8
+
+
+ Alice Smith
+ 12
+
+
+
### With Selectable Rows
+
It is possible to use the selected prop on the FlatTableRow to handle the selection of multiple rows of data.
To take an action across multiple table rows, the user can first select relevant rows with their checkboxes, then apply an action at the top left of the table.
@@ -667,13 +720,20 @@ If a given action is available for some, but not all, selected rows, then the ac
Where icons are used for batch actions, they have text labels too, or tooltips to make their function clear. There are always confirmation dialogs for destructive actions, or those difficult to undo.
-
+
{() => {
const [selectAll, setSelectAll] = useState(false);
- const [selectedRows, setSelectedRows] = useState({ one: false, two: false, three: false, four: false });
+ const [selectedRows, setSelectedRows] = useState({
+ one: false,
+ two: false,
+ three: false,
+ four: false,
+ });
const handleSelectAllRows = () => {
const newState = {};
- Object.keys(selectedRows).forEach((key) => newState[key] = !selectAll);
+ Object.keys(selectedRows).forEach(
+ (key) => (newState[key] = !selectAll)
+ );
setSelectedRows({ ...newState });
setSelectAll(!selectAll);
};
@@ -683,21 +743,32 @@ Where icons are used for batch actions, they have text labels too, or tooltips t
}
setSelectedRows({ ...selectedRows, [id]: !selectedRows[id] });
};
- const selectedCount = Object.keys(selectedRows).filter(key => Boolean(selectedRows[key])).length;
+ const selectedCount = Object.keys(selectedRows).filter((key) =>
+ Boolean(selectedRows[key])
+ ).length;
return (
<>
-
- {} }>
- {} }>
- {} }>
+
+ {}}>
+
+
+ {}}>
+
+
+ {}}>
+
+
handleSelectAllRows() }
+ as="th"
+ checked={selectAll}
+ onChange={() => handleSelectAllRows()}
/>
Name
Location
@@ -706,29 +777,41 @@ Where icons are used for batch actions, they have text labels too, or tooltips t
-
- handleSelectRow('one')} />
+
+ handleSelectRow("one")}
+ />
John Doe
London
Single
0
-
- handleSelectRow('two')} />
+
+ handleSelectRow("two")}
+ />
Jane Doe
York
Married
2
-
- handleSelectRow('three')} />
+
+ handleSelectRow("three")}
+ />
John Smith
Edinburgh
Single
1
-
- handleSelectRow('four')} />
+
+ handleSelectRow("four")}
+ />
Jane Smith
Newcastle
Married
@@ -738,24 +821,28 @@ Where icons are used for batch actions, they have text labels too, or tooltips t
>
);
- }}
+ }}
### With Highlightable Rows
+
It is possible to utilise the selected and onClick props on the FlatTableRow to highlight single rows of data.
-
+
{() => {
- const [highlightedRow, setHighlightedRow] = useState('');
+ const [highlightedRow, setHighlightedRow] = useState("");
const handleHighlightRow = (id) => {
if (highlightedRow === id) {
- setHighlightedRow('')
+ setHighlightedRow("");
} else {
setHighlightedRow(id);
}
- }
+ };
return (
@@ -767,25 +854,37 @@ It is possible to utilise the selected and onClick props on the FlatTableRow to
- handleHighlightRow('one') } highlighted={ highlightedRow === 'one' }>
+ handleHighlightRow("one")}
+ highlighted={highlightedRow === "one"}
+ >
John Doe
London
Single
0
- handleHighlightRow('two') } highlighted={ highlightedRow === 'two' }>
+ handleHighlightRow("two")}
+ highlighted={highlightedRow === "two"}
+ >
Jane Doe
York
Married
2
- handleHighlightRow('three') }highlighted={ highlightedRow === 'three' }>
+ handleHighlightRow("three")}
+ highlighted={highlightedRow === "three"}
+ >
John Smith
Edinburgh
Single
1
- handleHighlightRow('four') } highlighted={ highlightedRow === 'four' }>
+ handleHighlightRow("four")}
+ highlighted={highlightedRow === "four"}
+ >
Jane Smith
Newcastle
Married
@@ -794,22 +893,33 @@ It is possible to utilise the selected and onClick props on the FlatTableRow to
);
- }}
+ }}
### With Selectable and Highlightable Rows
+
It is also possible to integrate selection of multiple rows and the highlighting of single rows.
-
+
{() => {
const [selectAll, setSelectAll] = useState(false);
- const [selectedRows, setSelectedRows] = useState({ one: false, two: false, three: false, four: false });
- const [highlightedRow, setHighlightedRow] = useState('');
+ const [selectedRows, setSelectedRows] = useState({
+ one: false,
+ two: false,
+ three: false,
+ four: false,
+ });
+ const [highlightedRow, setHighlightedRow] = useState("");
const handleSelectAllRows = () => {
const newState = {};
- Object.keys(selectedRows).forEach((key) => newState[key] = !selectAll);
+ Object.keys(selectedRows).forEach(
+ (key) => (newState[key] = !selectAll)
+ );
setSelectedRows({ ...newState });
setSelectAll(!selectAll);
};
@@ -819,28 +929,39 @@ It is also possible to integrate selection of multiple rows and the highlighting
}
setSelectedRows({ ...selectedRows, [id]: !selectedRows[id] });
};
- const selectedCount = Object.keys(selectedRows).filter(key => Boolean(selectedRows[key])).length;
+ const selectedCount = Object.keys(selectedRows).filter((key) =>
+ Boolean(selectedRows[key])
+ ).length;
const handleHighlightRow = (id) => {
if (highlightedRow === id) {
- setHighlightedRow('')
+ setHighlightedRow("");
} else {
setHighlightedRow(id);
}
- }
+ };
return (
<>
-
- {} }>
- {} }>
- {} }>
+
+ {}}>
+
+
+ {}}>
+
+
+ {}}>
+
+
handleSelectAllRows() }
+ as="th"
+ checked={selectAll}
+ onChange={() => handleSelectAllRows()}
/>
Name
Location
@@ -849,29 +970,57 @@ It is also possible to integrate selection of multiple rows and the highlighting
- handleHighlightRow('one') } selected={ selectedRows.one } highlighted={ highlightedRow === 'one' }>
- handleSelectRow('one')} />
+ handleHighlightRow("one")}
+ selected={selectedRows.one}
+ highlighted={highlightedRow === "one"}
+ >
+ handleSelectRow("one")}
+ />
John Doe
London
Single
0
- handleHighlightRow('two') } selected={ selectedRows.two } highlighted={ highlightedRow === 'two' }>
- handleSelectRow('two')} />
+ handleHighlightRow("two")}
+ selected={selectedRows.two}
+ highlighted={highlightedRow === "two"}
+ >
+ handleSelectRow("two")}
+ />
Jane Doe
York
Married
2
- handleHighlightRow('three') } selected={ selectedRows.three } highlighted={ highlightedRow === 'three' }>
- handleSelectRow('three')} />
+ handleHighlightRow("three")}
+ selected={selectedRows.three}
+ highlighted={highlightedRow === "three"}
+ >
+ handleSelectRow("three")}
+ />
John Smith
Edinburgh
Single
1
- handleHighlightRow('four') } selected={ selectedRows.four } highlighted={ highlightedRow === 'four' }>
- handleSelectRow('four')} />
+ handleHighlightRow("four")}
+ selected={selectedRows.four}
+ highlighted={highlightedRow === "four"}
+ >
+ handleSelectRow("four")}
+ />
Jane Smith
Newcastle
Married
@@ -881,11 +1030,12 @@ It is also possible to integrate selection of multiple rows and the highlighting
>
);
- }}
+ }}
### With Pagination
+
If pagination is needed, this can be shown at the bottom of the table.
Balance performance concerns with the convenience of the user being able to see more data - we suggest giving the user the option of showing 25, 50, and 100 table rows before pagination, with a default of 50. Whatever the user selects, make this sticky per user, per table, and between sessions.
@@ -894,42 +1044,42 @@ Balance performance concerns with the convenience of the user being able to see
{() => {
const rows = [
-
+
John Doe
London
Single
0
,
-
+
Jane Doe
York
Married
2
,
-
+
John Smith
Edinburgh
Single
1
,
-
+
Jane Smith
Newcastle
Married
5
,
-
+
Liz Anya
Stoke
Single
2
,
-
+
Karl Ickbred
Newcastle
Single
0
-
+ ,
];
const [recordsRange, setRecordsRange] = useState({ start: 0, end: 5 });
const [currentPage, setCurrentPage] = useState(1);
@@ -947,20 +1097,21 @@ Balance performance concerns with the convenience of the user being able to see
};
return (
<>
- handlePagination(next, size) }
- pageSizeSelectionOptions={
- [
- { id: '1', name: 1 },
- { id: '5', name: 5 },
+ handlePagination(next, size)}
+ pageSizeSelectionOptions={[
+ { id: "1", name: 1 },
+ { id: "5", name: 5 },
]}
- />
- }>
+ />
+ }
+ >
Name
@@ -969,152 +1120,161 @@ Balance performance concerns with the convenience of the user being able to see
Dependents
-
- { renderRows() }
-
+ {renderRows()}
>
);
- }}
+ }}
### Paginated with sticky header
-When using the `Pager` and a sticky `FlatTableHead` some of the child elements may have style properties that cause the
-overflow to exceed the height of the table. In the example below, the `ActionPopoverMenu` has absolute positioning meaning
-it is accounted for in the overflow. To avoid this it is possible to use the `placement` prop to render the menu on `top`
+
+When using the `Pager` and a sticky `FlatTableHead` some of the child elements may have style properties that cause the
+overflow to exceed the height of the table. In the example below, the `ActionPopoverMenu` has absolute positioning meaning
+it is accounted for in the overflow. To avoid this it is possible to use the `placement` prop to render the menu on `top`
of the button control.
-
+
{() => {
const [placementUp, setPlacementUp] = useState(true);
const rows = [
-
+
John Doe
London
Single
- {}}>
- action
-
+ {}}>action
,
-
+
Jane Doe
York
Married
- {}} submenu={
-
- {}}>
- CSV
-
- {}}>
- PDF
-
- }
+ {}}
+ submenu={
+
+ {}}>
+ CSV
+
+ {}}>
+ PDF
+
+
+ }
>
action
,
-
+
John Smith
Edinburgh
Single
- {}}>
- action
-
+ {}}>action
,
-
+
Jane Smith
Newcastle
Married
- {}}>
- action
-
+ {}}>action
,
-
+
Liz Anya
Stoke
Single
- {}} submenu={
-
- {}}>
- CSV
-
- {}}>
- PDF
-
-
- }
+ {}}
+ submenu={
+
+ {}}>
+ CSV
+
+ {}}>
+ PDF
+
+
+ }
>
action
- {}} submenu={
-
- {}}>
- CSV
-
- {}}>
- PDF
-
- }
+ {}}
+ submenu={
+
+ {}}>
+ CSV
+
+ {}}>
+ PDF
+
+
+ }
>
action
,
-
+
Karl Ickbred
Newcastle
Single
- {}} submenu={
-
- {}}>
- CSV
-
- {}}>
- PDF
-
- }
+ {}}
+ submenu={
+
+ {}}>
+ CSV
+
+ {}}>
+ PDF
+
+
+ }
>
action
- {}} submenu={
-
- {}}>
- CSV
-
- {}}>
- PDF
-
-
- }
+ {}}
+ submenu={
+
+ {}}>
+ CSV
+
+ {}}>
+ PDF
+
+
+ }
>
action
-
+ ,
];
const [recordsRange, setRecordsRange] = useState({ start: 0, end: 5 });
const [currentPage, setCurrentPage] = useState(1);
@@ -1132,24 +1292,24 @@ of the button control.
setCurrentPage(newPage);
};
return (
-
+
handlePagination(next, size) }
- pageSizeSelectionOptions={
- [
- { id: '1', name: 1 },
- { id: '5', name: 5 },
- ]}
+ pageSize={5}
+ currentPage={currentPage}
+ onPagination={(next, size) => handlePagination(next, size)}
+ pageSizeSelectionOptions={[
+ { id: "1", name: 1 },
+ { id: "5", name: 5 },
+ ]}
/>
- }>
+ }
+ >
Name
@@ -1158,27 +1318,35 @@ of the button control.
Dependents
-
- { renderRows() }
-
+ {renderRows()}
);
- }}
+ }}
### When a child of Sidebar
-
+
{() => {
const [selectAll, setSelectAll] = useState(false);
- const [selectedRows, setSelectedRows] = useState({ one: false, two: false, three: false, four: false });
- const [highlightedRow, setHighlightedRow] = useState('');
+ const [selectedRows, setSelectedRows] = useState({
+ one: false,
+ two: false,
+ three: false,
+ four: false,
+ });
+ const [highlightedRow, setHighlightedRow] = useState("");
const handleSelectAllRows = () => {
const newState = {};
- Object.keys(selectedRows).forEach((key) => newState[key] = !selectAll);
+ Object.keys(selectedRows).forEach(
+ (key) => (newState[key] = !selectAll)
+ );
setSelectedRows({ ...newState });
setSelectAll(!selectAll);
};
@@ -1188,29 +1356,40 @@ of the button control.
}
setSelectedRows({ ...selectedRows, [id]: !selectedRows[id] });
};
- const selectedCount = Object.keys(selectedRows).filter(key => Boolean(selectedRows[key])).length;
+ const selectedCount = Object.keys(selectedRows).filter((key) =>
+ Boolean(selectedRows[key])
+ ).length;
const handleHighlightRow = (id) => {
if (highlightedRow === id) {
- setHighlightedRow('')
+ setHighlightedRow("");
} else {
setHighlightedRow(id);
}
- }
+ };
return (
<>
-
- {} }>
- {} }>
- {} }>
+
+ {}}>
+
+
+ {}}>
+
+
+ {}}>
+
+
-
+
handleSelectAllRows() }
+ as="th"
+ checked={selectAll}
+ onChange={() => handleSelectAllRows()}
/>
Name
Location
@@ -1219,29 +1398,57 @@ of the button control.
- handleHighlightRow('one') } selected={ selectedRows.one } highlighted={ highlightedRow === 'one' }>
- handleSelectRow('one')} />
+ handleHighlightRow("one")}
+ selected={selectedRows.one}
+ highlighted={highlightedRow === "one"}
+ >
+ handleSelectRow("one")}
+ />
John Doe
London
Single
0
- handleHighlightRow('two') } selected={ selectedRows.two } highlighted={ highlightedRow === 'two' }>
- handleSelectRow('two')} />
+ handleHighlightRow("two")}
+ selected={selectedRows.two}
+ highlighted={highlightedRow === "two"}
+ >
+ handleSelectRow("two")}
+ />
Jane Doe
York
Married
2
- handleHighlightRow('three') } selected={ selectedRows.three } highlighted={ highlightedRow === 'three' }>
- handleSelectRow('three')} />
+ handleHighlightRow("three")}
+ selected={selectedRows.three}
+ highlighted={highlightedRow === "three"}
+ >
+ handleSelectRow("three")}
+ />
John Smith
Edinburgh
Single
1
- handleHighlightRow('four') } selected={ selectedRows.four } highlighted={ highlightedRow === 'four' }>
- handleSelectRow('four')} />
+ handleHighlightRow("four")}
+ selected={selectedRows.four}
+ highlighted={highlightedRow === "four"}
+ >
+ handleSelectRow("four")}
+ />
Jane Smith
Newcastle
Married
@@ -1252,7 +1459,7 @@ of the button control.
>
);
- }}
+ }}
@@ -1261,44 +1468,46 @@ of the button control.
- {["compact", "small", "medium", "large"].map(size =>
-
-
-
- Name
- Location
- Relationship Status
- Dependents
-
-
-
-
- John Doe
- London
- Single
- 0
-
-
- Jane Doe
- York
- Married
- 2
-
-
- John Smith
- Edinburgh
- Single
- 1
-
-
- Jane Smith
- Newcastle
- Married
- 5
-
-
-
- )}
+ {["compact", "small", "medium", "large"].map((size) => (
+
+
+
+
+ Name
+ Location
+ Relationship Status
+ Dependents
+
+
+
+
+ John Doe
+ London
+ Single
+ 0
+
+
+ Jane Doe
+ York
+ Married
+ 2
+
+
+ John Smith
+ Edinburgh
+ Single
+ 1
+
+
+ Jane Smith
+ Newcastle
+ Married
+ 5
+
+
+
+
+ ))}
@@ -1306,43 +1515,52 @@ of the button control.
## Props
### FlatTable
+
### FlatTableHead
+
### FlatTableBody
+
### FlatTableRow
+
### FlatTableHeader
+
### Sort
+
### FlatTableCell
+
### FlatTableRowHeader
+
### FlatTableCheckbox
+