-
Notifications
You must be signed in to change notification settings - Fork 357
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
Table: Add ability to specify sticky columns #1395
Conversation
Deploy preview for gestalt ready! Built with commit 8d9143c |
Looking good! |
ce9482d
to
5c23992
Compare
698be6d
to
6fcc898
Compare
There was a problem hiding this 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. 🙂
docs/src/Table.doc.js
Outdated
name="Example: Sticky Column" | ||
description="Try scrolling horizontally to see the first column remain in place." | ||
defaultCode={` | ||
<Box width={"50%"} overflow="auto"> |
There was a problem hiding this comment.
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)
docs/src/Table.doc.js
Outdated
description="Try scrolling horizontally to see the first column remain in place." | ||
defaultCode={` | ||
<Box width={"50%"} overflow="auto"> | ||
<Table maxHeight={200} stickyColumns={1}> |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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" |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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! :)
packages/gestalt/src/Table.js
Outdated
|}; | ||
|
||
export default function Table(props: Props): Node { | ||
const { borderStyle, children, maxHeight } = props; | ||
const { borderStyle, children, maxHeight, stickyColumns } = props; | ||
const [showShadowScroll, setShowShadowScroll] = useState(null); |
There was a problem hiding this comment.
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')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
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)
packages/gestalt/src/TableRow.js
Outdated
|
||
const renderCellsWithIndex = () => { | ||
const cells = []; | ||
const tableRowChildrenArray = Children.toArray(props.children); |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) => { |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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) => { |
There was a problem hiding this comment.
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
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 |
packages/gestalt/src/Table.js
Outdated
}; | ||
}, [updateShadows]); | ||
|
||
useEffect(() => { |
There was a problem hiding this comment.
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?
packages/gestalt/src/Table.js
Outdated
return ( | ||
<Box | ||
overflow="auto" | ||
{...(borderStyle === 'sm' ? { borderStyle: 'sm', rounding: 1 } : {})} | ||
maxHeight={maxHeight} | ||
ref={contentRef} |
There was a problem hiding this comment.
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
?
packages/gestalt/src/TableRow.js
Outdated
|
||
type Props = {| | ||
children: Node, | ||
|}; | ||
|
||
export default function TableRow(props: Props): Node { | ||
return <tr>{props.children}</tr>; | ||
const { stickyColumns } = useContext(TableContext); |
There was a problem hiding this comment.
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()
;
packages/gestalt/src/TableRow.js
Outdated
const [columnWidths, setColumnWidths] = useState([]); | ||
|
||
useEffect(() => { | ||
if (rowRef && rowRef.current && stickyColumns) { |
There was a problem hiding this comment.
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
packages/gestalt/src/TableRow.js
Outdated
}); | ||
setColumnWidths(colWidths); | ||
} | ||
}, [rowRef, stickyColumns]); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. Some Flow issues here and there! |
There was a problem hiding this 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!
Adds ability to specify sticky column(s)
Test Plan
Added some snapshot tests