From 96f378d108274bbff01b425345bc847989f04050 Mon Sep 17 00:00:00 2001 From: Oliver Sand Date: Thu, 4 Feb 2021 10:54:58 +0100 Subject: [PATCH] Add support for custom empty state of `Table` components --- .changeset/violet-maps-occur.md | 8 ++ .../src/components/Table/Table.stories.tsx | 77 ++++++++++++++++--- .../core/src/components/Table/Table.test.tsx | 12 +++ packages/core/src/components/Table/Table.tsx | 21 +++++ 4 files changed, 109 insertions(+), 9 deletions(-) create mode 100644 .changeset/violet-maps-occur.md diff --git a/.changeset/violet-maps-occur.md b/.changeset/violet-maps-occur.md new file mode 100644 index 0000000000..e746ca3323 --- /dev/null +++ b/.changeset/violet-maps-occur.md @@ -0,0 +1,8 @@ +--- +'@backstage/core': patch +--- + +Add support for custom empty state of `Table` components. + +You can now optionally pass `emptyComponent` to `Table` that is displayed +if the table has now rows. diff --git a/packages/core/src/components/Table/Table.stories.tsx b/packages/core/src/components/Table/Table.stories.tsx index 4be85e494f..fe3fe89941 100644 --- a/packages/core/src/components/Table/Table.stories.tsx +++ b/packages/core/src/components/Table/Table.stories.tsx @@ -14,8 +14,10 @@ * limitations under the License. */ +import { makeStyles } from '@material-ui/core'; import React from 'react'; -import { Table, SubvalueCell, TableColumn } from './'; +import { Link } from '../Link'; +import { SubvalueCell, Table, TableColumn } from './'; import { TableFilter } from './Table'; export default { @@ -23,7 +25,16 @@ export default { component: Table, }; -const containerStyle = { width: 850 }; +const useStyles = makeStyles(theme => ({ + container: { + width: 850, + }, + empty: { + padding: theme.spacing(2), + display: 'flex', + justifyContent: 'center', + }, +})); const generateTestData: (number: number) => Array<{}> = (rows = 10) => { const data: Array<{}> = []; @@ -43,6 +54,7 @@ const generateTestData: (number: number) => Array<{}> = (rows = 10) => { const testData10 = generateTestData(10); export const DefaultTable = () => { + const classes = useStyles(); const columns: TableColumn[] = [ { title: 'Column 1', @@ -66,7 +78,7 @@ export const DefaultTable = () => { ]; return ( -
+
{ ); }; -export const SubtitleTable = () => { +export const EmptyTable = () => { + const classes = useStyles(); const columns: TableColumn[] = [ { title: 'Column 1', @@ -101,7 +114,49 @@ export const SubtitleTable = () => { ]; return ( -
+
+
+ No data was added yet,  + learn how to add data. + + } + title="Backstage Table" + /> + + ); +}; + +export const SubtitleTable = () => { + const classes = useStyles(); + const columns: TableColumn[] = [ + { + title: 'Column 1', + field: 'col1', + highlight: true, + }, + { + title: 'Column 2', + field: 'col2', + }, + { + title: 'Numeric value', + field: 'number', + type: 'numeric', + }, + { + title: 'A Date', + field: 'date', + type: 'date', + }, + ]; + + return ( +
{ }; export const HiddenSearchTable = () => { + const classes = useStyles(); const columns: TableColumn[] = [ { title: 'Column 1', @@ -137,7 +193,7 @@ export const HiddenSearchTable = () => { ]; return ( -
+
{ }; export const SubvalueTable = () => { + const classes = useStyles(); const columns: TableColumn[] = [ { title: 'Column 1', @@ -181,13 +238,14 @@ export const SubvalueTable = () => { ]; return ( -
+
); }; export const DenseTable = () => { + const classes = useStyles(); const columns: TableColumn[] = [ { title: 'Column 1', @@ -211,7 +269,7 @@ export const DenseTable = () => { ]; return ( -
+
{ }; export const FilterTable = () => { + const classes = useStyles(); const columns: TableColumn[] = [ { title: 'Column 1', @@ -261,7 +320,7 @@ export const FilterTable = () => { ]; return ( -
+
', () => { ); expect(rendered.getByText('subtitle')).toBeInTheDocument(); }); + + it('renders custom empty component if empty', async () => { + const rendered = await renderInTestApp( +
EMPTY} + columns={minProps.columns} + data={[]} + />, + ); + expect(rendered.getByText('EMPTY')).toBeInTheDocument(); + }); }); diff --git a/packages/core/src/components/Table/Table.tsx b/packages/core/src/components/Table/Table.tsx index dbb2964845..033ec01d3c 100644 --- a/packages/core/src/components/Table/Table.tsx +++ b/packages/core/src/components/Table/Table.tsx @@ -42,6 +42,7 @@ import MTable, { Column, Icons, MaterialTableProps, + MTableBody, MTableHeader, MTableToolbar, Options, @@ -202,6 +203,7 @@ export interface TableProps subtitle?: string; filters?: TableFilter[]; initialState?: TableState; + emptyComponent?: JSX.Element; onStateChange?: (state: TableState) => any; } @@ -212,6 +214,7 @@ export function Table({ subtitle, filters, initialState, + emptyComponent, onStateChange, ...props }: TableProps) { @@ -423,6 +426,23 @@ export function Table({ ], ); + const Body = useCallback( + bodyProps => { + if (emptyComponent && data.length === 0) { + return ( + + + + + + ); + } + + return ; + }, + [data, emptyComponent, columns], + ); + return (
{filtersOpen && data && filters?.length && ( @@ -438,6 +458,7 @@ export function Table({ ), Toolbar, + Body, }} options={{ ...defaultOptions, ...options }} columns={MTColumns}
{emptyComponent}