diff --git a/docs/src/Table.doc.js b/docs/src/Table.doc.js index e17a9d6f1d..56021b9621 100644 --- a/docs/src/Table.doc.js +++ b/docs/src/Table.doc.js @@ -263,6 +263,7 @@ card( @@ -275,13 +276,13 @@ card( Name - House + Super Name - Favorite Spell + Favorite Food - Patronus + Best Friend Birthday @@ -294,55 +295,57 @@ card( - Luna Lovegood - Ravenclaw - Expelliarmus - Hare - June 25, 1993 + Tony Stark + Iron Man + Shwarma + Spiderman + May 29, 1970 - Draco Malfoy - Slytherin - Slytherin - + Peter Parker + Spiderman + Sandwiches + Iron Man + December 28, 1995 - Neville Longbottom - Gryffindor - Gryffindor - + T'Challa + Black Panther + Beef suya + Shuri + November 28, 1977
@@ -355,7 +358,8 @@ card( card( @@ -368,25 +372,22 @@ card( Name - House - - - jfh + Super Name - fgreg + Best Friend - yrwey + Favorite Food - jfh + Super Powers - fgreg + Home - yrwey + Aliases @@ -396,20 +397,42 @@ card( - Luna Lovegood - Ravenclaw - Ravenclaw - Ravenclaw - Ravenclaw - Ravenclaw + Tony Stark + Iron Man + Spiderman + Shwarma + Flight, Super strength + New York + N/A + + + + + + + + + + Peter Parker + Spiderman + Iron Man + Sandwiches + Spidey senses, super strength, web shooters + Brooklyn + Friendly Neighborhood Spiderman @@ -417,43 +440,173 @@ card( - Draco Malfoy - Slytherin - Slytherin - Slytherin - Slytherin - Slytherin + Wanda Maximoff + Scarlet Witch + Vision + Chicken paprikash + Chaos magic, spells, reality warping + Sokovia + N/A + + + + + + + + + + T'Challa + Black Panther + Shuri + Beef suya + Enhanced strength, speed, reflexes + Vibranium suit + Wakanda + King of the Dead + + +
+ + +`} + />, +); +card( + + + + + + Image + + + Name + + + Super Name + + + Best Friend + + + Favorite Food + + + Super Powers + + + Home + + + Aliases + + + - Neville Longbottom - Gryffindor - Gryffindor - Gryffindor - Gryffindor - Gryffindor + Tony Stark + Iron Man + Spiderman + Shwarma + Flight, Super strength + New York + N/A + + + + + + + + + + Peter Parker + Spiderman + Iron Man + Sandwiches + Spidey senses, super strength, web shooters + Brooklyn + Friendly Neighborhood Spiderman + + + + + + + + + Wanda Maximoff + Scarlet Witch + Vision + Chicken paprikash + Chaos magic, spells, reality warping + Sokovia + N/A + + + + + + + + + + T'Challa + Black Panther + Shuri + Beef suya + Enhanced strength, speed, reflexes + Vibranium suit + Wakanda + King of the Dead +
@@ -579,7 +732,7 @@ card( return( - +
@@ -774,6 +927,211 @@ card( />, ); +card( + { + return Row expanded; + }; + + return( + +
+ + + + + Open/Close row + + + + Name + + + Super Name + + + Best Friend + + + Favorite Food + + + Home + + + Alias + + + + + setTextShown(!textShown)} + expandedContents={ + + + } + > + + + + Tony's Info + + + + {textShown && showTextOnExpand()} + + + } + > + + Tony Stark + + + Iron Man + + + Spiderman + + + Shwarma + + + New York City + + + N/A + + + + + + + Name + + + Relationship + + + + + + + Vision + + + Husband + + + + + Wiccan + + + Child + + + + + Speed + + + Child + + + +
+ } + > + + Wanda Maximoff + + + Scarlet Witch + + + Vision + + + Chicken paprikash + + + Sokovia + + + Wanda Frank + + + + + } + > + + + + Black Panther's Info + + + + +
+ } + > + + T'Challa + + + Black Panther + + + Shuri + + + Beef suya + + + Wakana + + + King of the Dead + + + + + + ); + } + `} + />, +); + card( (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); }; @@ -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 ( - +
{children}
diff --git a/packages/gestalt/src/Table.test.js b/packages/gestalt/src/Table.test.js index ffbb5bfb6a..338ff7466a 100644 --- a/packages/gestalt/src/Table.test.js +++ b/packages/gestalt/src/Table.test.js @@ -35,3 +35,14 @@ test('renders correctly with maxHeight', () => { .toJSON(); expect(tree).toMatchSnapshot(); }); + +test('renders correctly with stickyColumns', () => { + const tree = renderer + .create( + +
rest of table
+
, + ) + .toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/packages/gestalt/src/TableCell.test.js b/packages/gestalt/src/TableCell.test.js index cbb367bdca..70f4eb445f 100644 --- a/packages/gestalt/src/TableCell.test.js +++ b/packages/gestalt/src/TableCell.test.js @@ -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( + + cell content + , + ) + .toJSON(); + expect(tree).toMatchSnapshot(); +}); diff --git a/packages/gestalt/src/TableRowExpandable.js b/packages/gestalt/src/TableRowExpandable.js index c4bffe8b02..a331ca3e59 100644 --- a/packages/gestalt/src/TableRowExpandable.js +++ b/packages/gestalt/src/TableRowExpandable.js @@ -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'; @@ -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); @@ -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 ( - + 0} previousTotalWidth={0}> - {children} + {stickyColumns > 0 ? renderCellsWithIndex() : children} {expanded && ( diff --git a/packages/gestalt/src/__snapshots__/Table.test.js.snap b/packages/gestalt/src/__snapshots__/Table.test.js.snap index 81c0a603d7..008bb1bc00 100644 --- a/packages/gestalt/src/__snapshots__/Table.test.js.snap +++ b/packages/gestalt/src/__snapshots__/Table.test.js.snap @@ -56,3 +56,22 @@ exports[`renders correctly with maxHeight 1`] = ` `; + +exports[`renders correctly with stickyColumns 1`] = ` +
+ +
+ rest of table +
+
+
+`; diff --git a/packages/gestalt/src/__snapshots__/TableCell.test.js.snap b/packages/gestalt/src/__snapshots__/TableCell.test.js.snap index 9b49c124d4..35c7599e87 100644 --- a/packages/gestalt/src/__snapshots__/TableCell.test.js.snap +++ b/packages/gestalt/src/__snapshots__/TableCell.test.js.snap @@ -3,6 +3,26 @@ exports[`renders correctly 1`] = ` + cell content + +`; + +exports[`renders correctly when sticky and with shadows 1`] = ` + cell content @@ -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 diff --git a/packages/gestalt/src/__snapshots__/TableHeaderCell.test.js.snap b/packages/gestalt/src/__snapshots__/TableHeaderCell.test.js.snap index ebfda9e22e..cd1e6d87c8 100644 --- a/packages/gestalt/src/__snapshots__/TableHeaderCell.test.js.snap +++ b/packages/gestalt/src/__snapshots__/TableHeaderCell.test.js.snap @@ -4,6 +4,12 @@ exports[`renders correctly 1`] = ` column name @@ -15,6 +21,12 @@ exports[`renders correctly with props 1`] = ` colSpan={3} rowSpan={2} scope="row" + style={ + Object { + "left": undefined, + "right": undefined, + } + } > row name diff --git a/packages/gestalt/src/__snapshots__/TableRowExpandable.test.js.snap b/packages/gestalt/src/__snapshots__/TableRowExpandable.test.js.snap index e49a2896dc..cc783bfac3 100644 --- a/packages/gestalt/src/__snapshots__/TableRowExpandable.test.js.snap +++ b/packages/gestalt/src/__snapshots__/TableRowExpandable.test.js.snap @@ -6,6 +6,12 @@ exports[`renders correctly 1`] = ` >