Skip to content

Commit

Permalink
feat(Datagrid): add support for initially expanded nested rows (carbo…
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewgallo authored Jan 19, 2024
1 parent a164397 commit 58ea07f
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 44 deletions.
30 changes: 28 additions & 2 deletions packages/ibm-products/src/components/Datagrid/Datagrid.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -535,18 +535,19 @@ const CustomizingColumns = ({ ...rest } = {}) => {
);
};

const NestedRows = ({ ...rest } = {}) => {
const NestedRows = ({ initialState = {}, ...rest } = {}) => {
const columns = React.useMemo(() => defaultHeader, []);
const [data] = useState(makeData(10, 5, 2, 2));
const datagridState = useDatagrid(
{
columns,
data,
initialState,
},
useNestedRows
);

return <Datagrid datagridState={{ ...datagridState }} {...rest} />;
return <Datagrid datagridState={datagridState} {...rest} />;
};

const NestedTable = ({ ...rest } = {}) => {
Expand Down Expand Up @@ -1530,6 +1531,31 @@ describe(componentName, () => {
expect(nestedRow).toHaveClass(`${blockClass}__carbon-nested-row`);
});

it('should render nested rows with some initially expanded', async () => {
render(
<NestedRows
initialState={{
expandedRowIds: {
1: true,
3: true,
},
}}
/>
);
const gridRows = screen.getAllByRole('row');
const bodyRows = gridRows.filter(
(r) => !r.classList.contains(`${blockClass}__head`)
);
const rowId1 = bodyRows.filter(
(r) => r.getAttribute('data-nested-row-id') === '1'
);
const rowId3 = bodyRows.filter(
(r) => r.getAttribute('data-nested-row-id') === '3'
);
expect(rowId1[0]).toHaveClass(`${blockClass}__carbon-row-expanded`);
expect(rowId3[0]).toHaveClass(`${blockClass}__carbon-row-expanded`);
});

it('Nested Table', async () => {
render(<NestedTable data-testid={dataTestId}></NestedTable>);
const firstRowExpander = screen.getAllByLabelText('Expand row')[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,3 +269,27 @@ export const NestedRowsUsageStory = prepareStory(BasicTemplateWrapper, {
...nestedRowsControlProps,
},
});

const nestedRowsInitialStateStoryName = 'With initially expanded nested rows';
export const NestedRowsInitialUsageStory = prepareStory(BasicTemplateWrapper, {
storyName: nestedRowsInitialStateStoryName,
argTypes: {
gridTitle: ARG_TYPES.gridTitle,
gridDescription: ARG_TYPES.gridDescription,
useDenseHeader: ARG_TYPES.useDenseHeader,
rowSize: ARG_TYPES.rowSize,
rowSizes: ARG_TYPES.rowSizes,
onRowSizeChange: ARG_TYPES.onRowSizeChange,
expanderButtonTitleExpanded: 'Collapse row',
expanderButtonTitleCollapsed: 'Expand row',
},
args: {
...nestedRowsControlProps,
initialState: {
expandedRowIds: {
1: true,
3: true,
},
},
},
});
99 changes: 57 additions & 42 deletions packages/ibm-products/src/components/Datagrid/useNestedRows.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright IBM Corp. 2020, 2023
* Copyright IBM Corp. 2020, 2024
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
Expand All @@ -8,63 +8,78 @@
import cx from 'classnames';
import { pkg } from '../../settings';
import useNestedRowExpander from './useNestedRowExpander';
import { useEffect } from 'react';

const blockClass = `${pkg.prefix}--datagrid`;

const useNestedRows = (hooks) => {
useNestedRowExpander(hooks);
const marginLeft = 24;
const useInstance = (instance) => {
// This useEffect will expand rows if they exist in the initialState obj
useEffect(() => {
const { rows, initialState } = instance;
const { expandedRowIds } = initialState;
if (expandedRowIds) {
Object.keys(expandedRowIds).forEach((key) => {
const row = rows.filter((r) => r.id.toString() === key.toString());
if (row.length && key.toString() === row[0].id.toString()) {
row[0].toggleRowExpanded();
}
});
}
}, [instance]);

const getRowProps = (props, { row }) => {
return [
props,
{
className: cx({
[`${blockClass}__carbon-nested-row`]: row.depth > 0,
[`${blockClass}__carbon-row-expanded`]: row.isExpanded,
}),
},
];
};
const getRowStyles = (props, { row }) => [
props,
{
style: {
paddingLeft: `${
row.depth > 1
? marginLeft * 2 + (row.depth - 1) * (marginLeft + marginLeft / 3)
: row.depth === 1
? marginLeft * 2
: 0
}px`,
},
},
];
const getCellProps = (props, { cell, instance }) => {
// reduce the "first cell"s width to compensate added (left) margin
const isFirstCell =
instance.columns.findIndex((c) => c.id === cell.column.id) === 0;
return [
const marginLeft = 24;

const getRowProps = (props, { row }) => {
return [
props,
{
className: cx({
[`${blockClass}__carbon-nested-row`]: row.depth > 0,
[`${blockClass}__carbon-row-expanded`]: row.isExpanded,
}),
},
];
};
const getRowStyles = (props, { row }) => [
props,
{
style: {
marginRight: `${
isFirstCell && cell.row.depth > 0
? `${-32 * cell.row.depth - 18}px`
: ''
}`,
paddingLeft: `${
row.depth > 1
? marginLeft * 2 + (row.depth - 1) * (marginLeft + marginLeft / 3)
: row.depth === 1
? marginLeft * 2
: 0
}px`,
},
},
];
};
const getCellProps = (props, { cell, instance }) => {
// reduce the "first cell"s width to compensate added (left) margin
const isFirstCell =
instance.columns.findIndex((c) => c.id === cell.column.id) === 0;
return [
props,
{
style: {
marginRight: `${
isFirstCell && cell.row.depth > 0
? `${-32 * cell.row.depth - 18}px`
: ''
}`,
},
},
];
};

const useInstance = (instance) => {
Object.assign(instance, { withNestedRows: true });
hooks.getRowProps.push(getRowProps);
hooks.getRowProps.push(getRowStyles);
hooks.getCellProps.push(getCellProps);
};

hooks.getRowProps.push(getRowProps);
hooks.getRowProps.push(getRowStyles);
hooks.getCellProps.push(getCellProps);
hooks.useInstance.push(useInstance);
};

Expand Down

0 comments on commit 58ea07f

Please sign in to comment.