Skip to content

Commit

Permalink
fix(Datagrid): expandable/nested review fixes, custom hook for keepin…
Browse files Browse the repository at this point in the history
…g expander focus (v1) (#3864)

* chore(Datagrid): keep expander focus, remove feat flags

* chore: update snapshot

* chore: remove all padding from expanded area td
  • Loading branch information
matthewgallo authored Dec 1, 2023
1 parent 7994c5c commit 0048ef8
Show file tree
Hide file tree
Showing 13 changed files with 147 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2963,6 +2963,16 @@ th.c4p--datagrid__select-all-toggle-on.button {
background: var(--cds-layer-hover, #e5e5e5);
}
.c4p--datagrid .bx--data-table tbody tr:hover td.c4p--datagrid__expanded-row-cell-wrapper,
.c4p--datagrid .bx--data-table td.c4p--datagrid__expanded-row-cell-wrapper,
.c4p--datagrid .bx--data-table .c4p--datagrid__carbon-row-expanded td.c4p--datagrid__expandable-row-cell {
border: none;
}
.c4p--datagrid .bx--data-table td.c4p--datagrid__expanded-row-cell-wrapper {
padding: 0;
}
.c4p--datagrid__draggable-handleStyle {
display: flex;
align-items: center;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,16 @@ const DatagridExpandedRow =
onMouseEnter={(event) => toggleParentHoverClass(event, 'enter')}
onMouseLeave={(event) => toggleParentHoverClass(event)}
>
<div
className={`${blockClass}__expanded-row-content`}
style={{
height: expandedContentHeight && expandedContentHeight,
}}
>
<ExpandedRowContentComponent {...datagridState} />
</div>
<td className={`${blockClass}__expanded-row-cell-wrapper`}>
<div
className={`${blockClass}__expanded-row-content`}
style={{
height: expandedContentHeight && expandedContentHeight,
}}
>
<ExpandedRowContentComponent {...datagridState} />
</div>
</td>
</tr>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const HeaderRow = (datagridState, headRef, headerGroup) => {

const handleOnMouseDownResize = (event, resizeProps) => {
const { onMouseDown } = { ...resizeProps() };
event.target.focus();
// When event.button is 2, that is a right click
// and we do not want to resize
if (event.button === 2 || event.ctrlKey) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/*
* Licensed Materials - Property of IBM
* 5724-Q36
* (c) Copyright IBM Corp. 2020
* US Government Users Restricted Rights - Use, duplication or disclosure
* restricted by GSA ADP Schedule Contract with IBM Corp.
/**
* Copyright IBM Corp. 2020, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
// @flow

import React from 'react';
import { DataTable, SkeletonText } from 'carbon-components-react';
import { px } from '@carbon/layout';
Expand All @@ -27,7 +26,15 @@ const rowHeights = {

// eslint-disable-next-line react/prop-types
const DatagridRow = (datagridState) => {
const { row, rowSize, withNestedRows, prepareRow, key } = datagridState;
const {
row,
rowSize,
withNestedRows,
prepareRow,
key,
tableId,
withExpandedRows,
} = datagridState;

const getVisibleNestedRowCount = ({ isExpanded, subRows }) => {
let size = 0;
Expand Down Expand Up @@ -70,7 +77,7 @@ const DatagridRow = (datagridState) => {

const focusRemover = () => {
const elements = document.querySelectorAll(
`.${blockClass}__carbon-row-expanded`
`#${tableId} .${blockClass}__carbon-row-expanded`
);
elements.forEach((el) => {
el.classList.remove(`${blockClass}__carbon-row-expanded-hover-active`);
Expand Down Expand Up @@ -110,6 +117,15 @@ const DatagridRow = (datagridState) => {
[`${carbon.prefix}--data-table--selected`]: row.isSelected,
});

const setAdditionalRowProps = () => {
if (withNestedRows || withExpandedRows) {
return {
'data-nested-row-id': row.id,
};
}
return {};
};

return (
<React.Fragment key={key}>
<TableRow
Expand All @@ -121,6 +137,7 @@ const DatagridRow = (datagridState) => {
onFocus={hoverHandler}
onBlur={focusRemover}
onKeyUp={handleOnKeyUp}
{...setAdditionalRowProps()}
>
{row.cells.map((cell, index) => {
const cellProps = cell.getCellProps({ role: false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import { DatagridActions } from '../../utils/DatagridActions';
import { DatagridPagination } from '../../utils/DatagridPagination';
import { makeData } from '../../utils/makeData';
import { ARG_TYPES } from '../../utils/getArgTypes';
import { pkg } from '../../../../settings';
import { usePrefix } from '../../../../global/js/hooks';

export default {
Expand All @@ -30,13 +29,6 @@ export default {
styles,
docs: { page: mdx },
},
argTypes: {
featureFlags: {
table: {
disable: true,
},
},
},
};

const defaultHeader = [
Expand Down Expand Up @@ -154,11 +146,10 @@ const sharedDatagridProps = {
};

const ExpansionRenderer = ({ row, expandedContentAlign }) => {
console.log(row);
const prefix = usePrefix();
return (
<div
className={`expanded-content ${prefix}--test-hook-from-expanded-row-class`}
className={`expanded-content ${prefix}--test-hook-from-expanded-row-class--${row.id}`}
style={{ justifyContent: `${expandedContentAlign}` }}
>
<div className="expanded-content__child">
Expand Down Expand Up @@ -208,12 +199,6 @@ const ExpandedRows = ({ ...args }) => {
const [data] = useState(makeData(10));
const rows = React.useMemo(() => data, [data]);

// Warnings are ordinarily silenced in storybook, add this to test.
pkg._silenceWarnings(false);
// Enable feature flag for `useExpandedRow` hook
pkg.feature['Datagrid.useExpandedRow'] = true;
pkg._silenceWarnings(true);

const datagridState = useDatagrid(
{
columns,
Expand Down Expand Up @@ -256,6 +241,5 @@ export const ExpandableRowStory = prepareStory(BasicTemplateWrapper, {
},
args: {
...expandableRowControlProps,
featureFlags: ['Datagrid.useExpandedRow'],
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import mdx from '../../Datagrid.mdx';
import { DatagridActions } from '../../utils/DatagridActions';
import { makeData } from '../../utils/makeData';
import { ARG_TYPES } from '../../utils/getArgTypes';
import { pkg } from '../../../../settings';

export default {
title: `${getStoryTitle(Datagrid.displayName)}/Extensions/NestedRows`,
Expand All @@ -28,13 +27,6 @@ export default {
styles,
docs: { page: mdx },
},
argTypes: {
featureFlags: {
table: {
disable: true,
},
},
},
};

const defaultHeader = [
Expand Down Expand Up @@ -175,12 +167,6 @@ const SingleLevelNestedRows = ({ ...args }) => {
useNestedRows
);

// Warnings are ordinarily silenced in storybook, add this to test
pkg._silenceWarnings(false);
// Enable feature flag for `useNestedRows` hook
pkg.feature['Datagrid.useNestedRows'] = true;
pkg._silenceWarnings(true);

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

Expand All @@ -205,7 +191,6 @@ export const SingleLevelNestedRowsUsageStory = prepareStory(
},
args: {
...nestedRowsControlProps,
featureFlags: ['Datagrid.useNestedRows'],
},
}
);
Expand All @@ -214,12 +199,6 @@ const NestedRows = ({ ...args }) => {
const columns = React.useMemo(() => defaultHeader, []);
const [data] = useState(makeData(10, 5, 2, 2));

// Warnings are ordinarily silenced in storybook, add this to test
pkg._silenceWarnings(false);
// Enable feature flag for `useNestedRows` hook
pkg.feature['Datagrid.useNestedRows'] = true;
pkg._silenceWarnings(true);

const datagridState = useDatagrid(
{
columns,
Expand Down Expand Up @@ -252,6 +231,5 @@ export const NestedRowsUsageStory = prepareStory(BasicTemplateWrapper, {
},
args: {
...nestedRowsControlProps,
featureFlags: ['Datagrid.useNestedRows'],
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,24 @@
.#{$block-class} .#{$block-class}__expandable-row--hover td {
background: $layer-hover;
}

.#{$block-class}
.#{$carbon-prefix}--data-table
tbody
tr:hover
td.#{$block-class}__expanded-row-cell-wrapper,
.#{$block-class}
.#{$carbon-prefix}--data-table
td.#{$block-class}__expanded-row-cell-wrapper,
.#{$block-class}
.#{$carbon-prefix}--data-table
.#{$block-class}__carbon-row-expanded
td.#{$block-class}__expandable-row-cell {
border: none;
}

.#{$block-class}
.#{$carbon-prefix}--data-table
td.#{$block-class}__expanded-row-cell-wrapper {
padding: 0;
}
13 changes: 6 additions & 7 deletions packages/ibm-products/src/components/Datagrid/useExpandedRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@
* LICENSE file in the root directory of this source tree.
*/

import { useEffect, useState } from 'react';
import { pkg } from '../../settings';
import { useState } from 'react';
import DatagridExpandedRow from './Datagrid/DatagridExpandedRow';
import useRowExpander from './useRowExpander';

const useExpandedRow = (hooks) => {
useEffect(() => {
pkg.checkReportFeatureEnabled('Datagrid.useExpandedRow');
}, []);

useRowExpander(hooks);
const useInstance = (instance) => {
const { rows, expandedContentHeight, ExpandedRowContentComponent } =
Expand All @@ -29,7 +24,11 @@ const useExpandedRow = (hooks) => {
expandedRowsHeight[row.index] || expandedContentHeight,
RowExpansionRenderer: DatagridExpandedRow(ExpandedRowContentComponent),
}));
Object.assign(instance, { rows: rowsWithExpand, setExpandedRowHeight });
Object.assign(instance, {
rows: rowsWithExpand,
setExpandedRowHeight,
withExpandedRows: true,
});
};
hooks.useInstance.push(useInstance);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/**
* Copyright IBM Corp. 2023, 2023
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

import { useEffect } from 'react';

// Focuses the row expander after a nested/expandable row state change.
// We have to add this workaround because react-table is re-rendering the entire row
// which removes the focus from the expander and interrupts the keyboard navigation
// flow.
export const useFocusRowExpander = ({
instance,
lastExpandedRowIndex,
blockClass,
activeElement,
}) => {
useEffect(() => {
// We need to return at this point so that the focus is not stolen from
// other interactive elements in the Datagrid
if (!activeElement.classList.contains(`${blockClass}__row-expander`)) {
return;
}
const tableId = instance?.tableId;
const rowElements = document.querySelectorAll(`#${tableId} tbody tr`);
if (lastExpandedRowIndex) {
const rowElementsArray = Array.from(rowElements);
const activeRow = rowElementsArray.filter((r) => {
if (r.getAttribute('data-nested-row-id') === lastExpandedRowIndex) {
return r;
}
return null;
});
if (activeRow.length) {
const rowExpander = activeRow[0].querySelector(
`.${blockClass}__row-expander`
);
rowExpander.focus();
}
}
}, [
instance?.tableId,
instance?.expandedRows,
lastExpandedRowIndex,
blockClass,
activeElement,
]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,23 @@ import React, { useRef } from 'react';
import { ChevronRight16 } from '@carbon/icons-react';
import cx from 'classnames';
import { pkg, carbon } from '../../settings';
import { useFocusRowExpander } from './useFocusRowExpander';

const blockClass = `${pkg.prefix}--datagrid`;
const useNestedRowExpander = (hooks) => {
const tempState = useRef();
const lastExpandedRowIndex = useRef();
const useInstance = (instance) => {
tempState.current = instance;
};

useFocusRowExpander({
instance: tempState?.current,
lastExpandedRowIndex: lastExpandedRowIndex?.current,
blockClass,
activeElement: document.activeElement,
});

const visibleColumns = (columns) => {
const expanderColumn = {
id: 'expander',
Expand All @@ -27,6 +37,7 @@ const useNestedRowExpander = (hooks) => {
// Prevents `onRowClick` from being called if `useOnRowClick` is included
event.stopPropagation();
row.toggleRowExpanded();
lastExpandedRowIndex.current = row.id;
},
};
const {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,13 @@
* LICENSE file in the root directory of this source tree.
*/

import { useEffect } from 'react';
import { pkg } from '../../settings';
import cx from 'classnames';
import useNestedRowExpander from './useNestedRowExpander';

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

const useNestedRows = (hooks) => {
useEffect(() => {
pkg.checkReportFeatureEnabled('Datagrid.useNestedRows');
}, []);

useNestedRowExpander(hooks);
const marginLeft = 24;

Expand Down
Loading

0 comments on commit 0048ef8

Please sign in to comment.