Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Table: Add ability to specify sticky columns #1395

Merged
merged 19 commits into from
Apr 7, 2021

Conversation

ayeshakmaz
Copy link
Contributor

@ayeshakmaz ayeshakmaz commented Feb 23, 2021

Adds ability to specify sticky column(s)

Test Plan

Added some snapshot tests

@netlify
Copy link

netlify bot commented Feb 23, 2021

Deploy preview for gestalt ready!

Built with commit 8d9143c

https://deploy-preview-1395--gestalt.netlify.app

@AlbertCarreras
Copy link
Contributor

Looking good!

@dangerismycat dangerismycat self-assigned this Mar 23, 2021
@ayeshakmaz ayeshakmaz marked this pull request as ready for review March 31, 2021 23:40
@ayeshakmaz ayeshakmaz requested a review from a team as a code owner March 31, 2021 23:40
@ayeshakmaz ayeshakmaz changed the title [Prototyping] Table: Add ability to freeze columns Table: Add ability to specify sticky columns Mar 31, 2021
Copy link
Contributor

@dangerismycat dangerismycat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks awesome!! The UI is 100% there. 🙂

name="Example: Sticky Column"
description="Try scrolling horizontally to see the first column remain in place."
defaultCode={`
<Box width={"50%"} overflow="auto">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use string props directly, no need for the curlies (here and throughout)

description="Try scrolling horizontally to see the first column remain in place."
defaultCode={`
<Box width={"50%"} overflow="auto">
<Table maxHeight={200} stickyColumns={1}>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These code examples are pretty hefty; can you break things up with some whitespace for readability? Since they start collapsed, I'm not really concerned with taking up more real estate

card(
<Example
id="stickyColumn3"
name="Example: Sticky header and sticky columns"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This UI looks so good!! Nice work!

image={
<Avatar
name="tony avatar"
src="https://i.ibb.co/8948ym5/avenge.png"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These examples are great, but are there copyright issues with using these images? Or is this considered fair use?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That be a good PR stunt for our gestalt open source library! :)

|};

export default function Table(props: Props): Node {
const { borderStyle, children, maxHeight } = props;
const { borderStyle, children, maxHeight, stickyColumns } = props;
const [showShadowScroll, setShowShadowScroll] = useState(null);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think Flow will be able to properly infer the type here, so you may want to add it. Looks like it's an optional enum? ?('left' | 'right')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

Copy link
Contributor

@AlbertCarreras AlbertCarreras Apr 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, I think ryan was suggesting here useState<('left' | 'right'| null)>(null)


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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be simplified with Children.map:

const renderCellsWithIndex = () => Children.map(props.children, (item) => {
  ...
  return cloneElement(...);
});

Another idea to prevent needing this separate faux-render method would be to extract the map function to a helper, so the component return is something like

  return <tr ref={rowRef}>{stickyColumns > 0 ? Children.map(props.children, renderCellsWithIndex) : props.children}</tr>;

@@ -35,6 +44,9 @@ export default function TableRowExpandable(props: Props): Node {
const [expanded, setExpanded] = useState(false);
const hoverStyle = props.hoverStyle || 'gray';
const cs = hoverStyle === 'gray' ? cx(styles.hoverShadeGray) : null;
const { stickyColumns } = useContext(TableContext);
const rowRef = React.useRef();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same nit here about importing directly

@@ -35,6 +44,9 @@ export default function TableRowExpandable(props: Props): Node {
const [expanded, setExpanded] = useState(false);
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This always makes me nervous…we should use functional updates for this sort of toggling to prevent using stale values: https://reactjs.org/docs/hooks-reference.html#functional-updates

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for pointing to this... I feel we do that across many cmps.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's unrelated to these changes, I'll make a separate ticket to look at this across our cmps

if (rowRef && rowRef.current && stickyColumns) {
const colWidths = [];
const tableRowChildrenArray = [...rowRef.current.children];
tableRowChildrenArray.forEach((child) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same feedback here re: .map

Copy link
Contributor

@AlbertCarreras AlbertCarreras Apr 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if some of this repeated logic could be extracted out into a helper file to share and make it dryier.

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

tableRowChildrenArray.forEach((child, index) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same feedback here re: Children.map

@AlbertCarreras
Copy link
Contributor

AlbertCarreras commented Apr 1, 2021

I really value your work on this shadow... but I must admit it doesn't feel good to me. I feel like a thicker borderline could bring me more peace. haha

};
}, [updateShadows]);

useEffect(() => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this useEffect?

can we merge wth previous?

return (
<Box
overflow="auto"
{...(borderStyle === 'sm' ? { borderStyle: 'sm', rounding: 1 } : {})}
maxHeight={maxHeight}
ref={contentRef}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very stupid nit,,, what about tableRef?


type Props = {|
children: Node,
|};

export default function TableRow(props: Props): Node {
return <tr>{props.children}</tr>;
const { stickyColumns } = useContext(TableContext);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import { useTableContext } from './TableContext.js';
then

const { stickyColumns } = useTableContext();

const [columnWidths, setColumnWidths] = useState([]);

useEffect(() => {
if (rowRef && rowRef.current && stickyColumns) {
Copy link
Contributor

@AlbertCarreras AlbertCarreras Apr 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rowRef && rowRef.current >> rowRef?.current

});
setColumnWidths(colWidths);
}
}, [rowRef, stickyColumns]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is needed rowRef? rowRef.current aint needed. I'm not sure about this, just asking a question to discuss and learn.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't actually, this was left over from a previous attempt, good catch!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlbertCarreras
Copy link
Contributor

Looking good. Some Flow issues here and there!

@ayeshakmaz ayeshakmaz added the minor release Minor release label Apr 6, 2021
@AlbertCarreras AlbertCarreras self-requested a review April 6, 2021 23:37
Copy link
Contributor

@AlbertCarreras AlbertCarreras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome job! Sticky power!

@ayeshakmaz ayeshakmaz merged commit 0b7eb05 into pinterest:master Apr 7, 2021
@ayeshakmaz ayeshakmaz deleted the ayesha/table-col-locking branch April 7, 2021 00:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor release Minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants