Skip to content

Commit

Permalink
sticky columns with shadow
Browse files Browse the repository at this point in the history
  • Loading branch information
ayeshakmaz committed Mar 31, 2021
1 parent 781ac10 commit 6fcc898
Show file tree
Hide file tree
Showing 11 changed files with 591 additions and 101 deletions.
472 changes: 415 additions & 57 deletions docs/src/Table.doc.js

Large diffs are not rendered by default.

45 changes: 10 additions & 35 deletions packages/gestalt/src/Table.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,59 +17,30 @@
position: relative;
}

td div{
z-index: 1;
position: relative;
}

.sticky tr th {
background-color: var(--g-colorGray0);
position: sticky;
top: 0;
z-index: 6;
z-index: 2;
}

.columnSticky {
background-color: var(--g-colorGray0);
position:sticky;
left: 0;
z-index: 3;
}

.columnSticky div {
z-index: 5;
z-index: 1;
}

.columnStickyShadow div {
.sticky .columnSticky {
z-index: 3;
position: relative;
}


.columnStickyShadow::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
.horizontalScrollRight .columnStickyShadow {
box-shadow: 8px 0px 8px -8px var(--g-colorGray150);
}

.columnStickyShadow + td::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: 4;
background-color: transparent;
box-shadow: inset 8px -8px white;
}

.sticky th.columnSticky {
z-index: 7;
.horizontalScrollLeft .columnStickyShadow {
box-shadow: -8px 0px 8px -8px var(--g-colorGray150);
}

.thead tr:last-child th {
Expand All @@ -83,3 +54,7 @@ td div{
.hoverShadeGray:hover {
background-color: var(--g-colorGray100);
}

.hoverShadeGray:hover .columnSticky {
background-color: var(--g-colorGray100);
}
22 changes: 16 additions & 6 deletions packages/gestalt/src/Table.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @flow strict
import React, { type Node, useState, useCallback, useEffect, useRef } from 'react';
import cx from 'classnames';
import Box from './Box.js';
import styles from './Table.css';
import TableCell from './TableCell.js';
Expand All @@ -21,21 +22,26 @@ type Props = {|

export default function Table(props: Props): Node {
const { borderStyle, children, maxHeight, stickyColumns } = props;
const [showShadowScroll, setShowShadowScroll] = useState(false);
const [showShadowScroll, setShowShadowScroll] = useState(null);
const contentRef = useRef<?HTMLDivElement>(null);

const updateShadows = useCallback(() => {
console.log('update shadows');
const target = contentRef.current;
if (!target) {
return;
}
console.log(target.scrollHeight);
if (target.scrollLeft > 0) {
setShowShadowScroll('right');
} else if (target.scrollLeft < 0) {
setShowShadowScroll('left');
} else {
setShowShadowScroll(null);
}
}, []);

useEffect(() => {
const target = contentRef.current;
target.addEventListener('scroll', updateShadows);
target?.addEventListener('scroll', updateShadows);
return () => {
target.removeEventListener('scroll', updateShadows);
};
Expand All @@ -45,15 +51,19 @@ export default function Table(props: Props): Node {
updateShadows();
}, [updateShadows]);

const classNames = cx(
styles.table,
showShadowScroll === 'right' && styles.horizontalScrollRight,
showShadowScroll === 'left' && styles.horizontalScrollLeft,
);
return (
<Box
id="testing"
overflow="auto"
{...(borderStyle === 'sm' ? { borderStyle: 'sm', rounding: 1 } : {})}
maxHeight={maxHeight}
ref={contentRef}
>
<table className={styles.table}>
<table className={classNames}>
<TableContext.Provider value={{ stickyColumns }}>{children}</TableContext.Provider>
</table>
</Box>
Expand Down
11 changes: 11 additions & 0 deletions packages/gestalt/src/Table.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,14 @@ test('renders correctly with maxHeight', () => {
.toJSON();
expect(tree).toMatchSnapshot();
});

test('renders correctly with stickyColumns', () => {
const tree = renderer
.create(
<Table stickyColumns={2}>
<div>rest of table</div>
</Table>,
)
.toJSON();
expect(tree).toMatchSnapshot();
});
11 changes: 11 additions & 0 deletions packages/gestalt/src/TableCell.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,14 @@ test('renders correctly with colSpan and rowSpan', () => {
.toJSON();
expect(tree).toMatchSnapshot();
});

test('renders correctly when sticky and with shadows', () => {
const tree = renderer
.create(
<TableCell shouldBeSticky shouldHaveShadow previousTotalWidth={120}>
cell content
</TableCell>,
)
.toJSON();
expect(tree).toMatchSnapshot();
});
44 changes: 41 additions & 3 deletions packages/gestalt/src/TableRowExpandable.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
// @flow strict
import React, { Children, Fragment, type Node, useState, useContext } from 'react';
import React, {
Children,
Fragment,
type Node,
useState,
useContext,
useEffect,
cloneElement,
} from 'react';
import cx from 'classnames';
import styles from './Table.css';
import Box from './Box.js';
Expand Down Expand Up @@ -37,6 +45,8 @@ export default function TableRowExpandable(props: Props): Node {
const hoverStyle = props.hoverStyle || 'gray';
const cs = hoverStyle === 'gray' ? cx(styles.hoverShadeGray) : null;
const { stickyColumns } = useContext(TableContext);
const rowRef = React.useRef();
const [columnWidths, setColumnWidths] = useState([]);

const handleButtonClick = ({ event }) => {
setExpanded(!expanded);
Expand All @@ -45,9 +55,37 @@ export default function TableRowExpandable(props: Props): Node {
}
};

useEffect(() => {
if (rowRef && rowRef.current && stickyColumns) {
const colWidths = [];
const tableRowChildrenArray = [...rowRef.current.children];
tableRowChildrenArray.forEach((child) => {
colWidths.push(child.clientWidth);
});
setColumnWidths(colWidths);
}
}, [rowRef, stickyColumns]);

const renderCellsWithIndex = () => {
const cells = [];
const tableRowChildrenArray = Children.toArray(props.children);

tableRowChildrenArray.forEach((child, index) => {
// Account for the extra first column
const adjustedIndex = index + 1;
const shouldBeSticky = stickyColumns >= 0 && adjustedIndex < stickyColumns;
const shouldHaveShadow = stickyColumns - 1 === adjustedIndex;
const previousWidths = columnWidths.slice(0, adjustedIndex);
const previousTotalWidth =
previousWidths.length > 0 ? previousWidths.reduce((a, b) => a + b) : 0;
cells.push(cloneElement(child, { shouldBeSticky, previousTotalWidth, shouldHaveShadow }));
});
return cells;
};

return (
<Fragment>
<tr className={cs}>
<tr className={cs} ref={rowRef}>
<TableCell shouldBeSticky={stickyColumns > 0} previousTotalWidth={0}>
<IconButton
accessibilityExpanded={expanded}
Expand All @@ -59,7 +97,7 @@ export default function TableRowExpandable(props: Props): Node {
size="xs"
/>
</TableCell>
{children}
{stickyColumns > 0 ? renderCellsWithIndex() : children}
</tr>
{expanded && (
<tr id={id}>
Expand Down
19 changes: 19 additions & 0 deletions packages/gestalt/src/__snapshots__/Table.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,22 @@ exports[`renders correctly with maxHeight 1`] = `
</table>
</div>
`;

exports[`renders correctly with stickyColumns 1`] = `
<div
className="box overflowAuto"
style={
Object {
"maxHeight": undefined,
}
}
>
<table
className="table"
>
<div>
rest of table
</div>
</table>
</div>
`;
26 changes: 26 additions & 0 deletions packages/gestalt/src/__snapshots__/TableCell.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,26 @@
exports[`renders correctly 1`] = `
<td
className="td"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
cell content
</td>
`;

exports[`renders correctly when sticky and with shadows 1`] = `
<td
className="td columnSticky columnStickyShadow"
style={
Object {
"left": 120,
"right": 120,
}
}
>
cell content
</td>
Expand All @@ -13,6 +33,12 @@ exports[`renders correctly with colSpan and rowSpan 1`] = `
className="td"
colSpan={3}
rowSpan={2}
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
cell content
</td>
Expand Down
12 changes: 12 additions & 0 deletions packages/gestalt/src/__snapshots__/TableHeaderCell.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ exports[`renders correctly 1`] = `
<th
className="th"
scope="col"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
column name
</th>
Expand All @@ -15,6 +21,12 @@ exports[`renders correctly with props 1`] = `
colSpan={3}
rowSpan={2}
scope="row"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
row name
</th>
Expand Down
18 changes: 18 additions & 0 deletions packages/gestalt/src/__snapshots__/TableRowExpandable.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ exports[`renders correctly 1`] = `
>
<td
className="td"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
<button
aria-controls="expandableRow"
Expand Down Expand Up @@ -63,6 +69,12 @@ exports[`renders correctly with explicit hover 1`] = `
>
<td
className="td"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
<button
aria-controls="expandableRow"
Expand Down Expand Up @@ -120,6 +132,12 @@ exports[`renders correctly without hover 1`] = `
>
<td
className="td"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
<button
aria-controls="expandableRow"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ exports[`renders correctly when active 1`] = `
<th
className="th"
scope="col"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
<div
className="box xsDisplayInlineBlock"
Expand Down Expand Up @@ -63,6 +69,12 @@ exports[`renders correctly when inactive 1`] = `
<th
className="th"
scope="col"
style={
Object {
"left": undefined,
"right": undefined,
}
}
>
<div
className="box xsDisplayInlineBlock"
Expand Down

0 comments on commit 6fcc898

Please sign in to comment.