-
Notifications
You must be signed in to change notification settings - Fork 289
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
Ability to provide custom scrollbars: #507
Conversation
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 the PR! This looks great, and inline with were we'd like to go. I added a few suggestions, but nothing major / blocking.
I also noticed that the Reorderable Columns example seems broken on this branch and doesn't show the unfrozen columns. Could you take a look and see what the issue might be? Thanks.
src/FixedDataTable.js
Outdated
@@ -467,6 +493,9 @@ class FixedDataTable extends React.Component { | |||
keyboardPageEnabled: false, | |||
touchScrollEnabled: false, | |||
stopScrollPropagation: false, | |||
defaultScrollbars: true, // For documentation purpose only |
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.
Was React complaining about these missing here? If not, I recommend we remove from here, and then update the PropTypes above with a comment like
TODO (jordan) Remove propType of defaultScrollbars without losing documentation (handled in FDTContainer.js)
That way it will be similar to other cases we have.
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.
intention was to show default values in documentation, I made suggested changes.
@@ -613,6 +642,10 @@ class FixedDataTable extends React.Component { | |||
this._contentHeight = contentHeight; | |||
} | |||
|
|||
shouldComponentUpdate(nextProps) { |
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.
Was this necessary to fix issues, or just a nice perf enhancement here?
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.
not specific to this PR, in general good to have.
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.
FixedDataTable has a few objects being passed as props. So I suggest removing the shouldComponentUpdate
check here, especially since it's not required by the PR.
If we are absolutely certain that the passed in objects are immutable and that they won't change in the future, then we could have this in.
scrollToY: this._scrollToY | ||
}; | ||
if (!shallowEqual(this.previousScrollState, newScrollState)) { | ||
this.props.onScrollBarsUpdate(newScrollState); |
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 is a lot to report to the callback here. Is all of this information necessary, or could we trim it down?
I'm concerned if we expose too many internal details, we won't be able to modify the API easily in the future. Not an issue if we do need to expose all this, but if there are any ways we could slim the API down, it's worth investigating.
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 believe we have to pass visbileRowsHeight
, allRowsHeight
to determine scrollbarY height and its thumb height. scrollY
to position scrollbarY thumb. scrollbarYOffsetTop
to position scrollbarY itself. Similarly for scrollbarX
We can avoid scrollToX
and scrollToY
as they can be achieved via scrollTo
, but I added them as browser native scrollbar has those methods. Please let me know your opinion here if its ok to have only scrollTo
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.
Okay sounds good. I think passing both scrollToX and scrollToY is fine.
I wish we didn't need to pass scrollbarXOffsetTop & scrollbarYOffsetTop... But understandable if there's no other way.
We also might want to consider renaming visibleRowsHeight & allRowsHeight. Maybe to viewportHeight & contentHeight? Likewise for columns / width.
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.
We also might want to consider renaming visibleRowsHeight & allRowsHeight. Maybe to viewportHeight & contentHeight? Likewise for columns / width.
This makes much more sense, renamed these.
Thanks for pointing out, missed passing |
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 good from my end. @pradeepnschrodinger & @mycrobe do you have any concerns?
no concerns from me |
@pradeepnschrodinger do you have any concerns here? If not can we go ahead and merge? Side note, does it make sense to start an 1.1 branch at target this for that so master can handle any v1.0 bug fixes? Or start a 1.0 branch for bug fixes? |
This looks very good. I think I'll take a deeper look by end of this week.
Yea, let's do a feature branch for custom scrollbars. This way we will also avoid the case where users complain about any API changes because they had already started using custom scrollbars in an early state through master. |
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.
Just a few comments.
src/plugins/ScrollContainer.js
Outdated
}; | ||
|
||
_onVerticalScroll = (/*number*/ scrollPos) => { | ||
if (this.state.scrollToY) { |
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.
Will this work if user scrolls to value 0 ?
I think it's better to check for undefined
instead (if the check is required at all).
(similar for _onHorizontalScroll
)
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.
will take care of this
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.
Actually we are checking this.state.scrollToY
and not scrollPos
, this should be fine but still took care of comparing with undefined
@@ -613,6 +642,10 @@ class FixedDataTable extends React.Component { | |||
this._contentHeight = contentHeight; | |||
} | |||
|
|||
shouldComponentUpdate(nextProps) { |
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.
FixedDataTable has a few objects being passed as props. So I suggest removing the shouldComponentUpdate
check here, especially since it's not required by the PR.
If we are absolutely certain that the passed in objects are immutable and that they won't change in the future, then we could have this in.
</ScrollContainer> | ||
); | ||
} | ||
return fdt; |
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'm a bit confused on how the custom scrollbars get "props" at this level.
When defaultScrollbars
is on, we pass this.props
to the default scrollbars by
if (this.props.defaultScrollbars) {
return (
<ScrollContainer {...this.props}>
{fdt}
</ScrollContainer>
);
}
Similarly shouldn't we somehow also pass it to the custom scrollbars? Maybe we should avoid passing of props alltogether at this level, and ensure that <FixedDataTable />
passes everything that's required through onScrollBarsUpdate
?
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.
here we are passing props to ScrollContainer
to render FDT and also pass touchScrollEnabled
and isRTL
prop
in case of custom scrollbar people will have access to these props (as they are the one passing them to FDT) and can pass directly to scrollbars if required.
@@ -259,6 +259,8 @@ function setStateFromProps(state, props) { | |||
newState.tableSize.useMaxHeight = | |||
newState.tableSize.height === undefined; | |||
|
|||
newState.scrollbarXHeight = props.scrollbarXHeight; |
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.
could you also add these entries to the getInitialState()
function in reducers/index.js?
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.
Should I keep default values as Scrollbar.SIZE
?
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.
took care of this
I'm a bit concerned on how the ScrollContainer component Whenever user scrolls, a redux action is dispatched and the store is updated. Now this is fine, but the FixedDataTable will again update ScrollContainer's underlying state as a sideeffect through
Instead of all this, can't we ensure a one directional render flow by rendering the scrollbars within FixedDataTable itself? |
@pradeepnschrodinger if we have FDT render the scrollbars itself, will that make it difficult to compose? Different scrollbar components will likely have different APIs and interactions. If we can hoist the composition outside of FDT and require the end user to compose them, then they can handle the integration between the details FDT exposes and the APIs of the scrollbars. I'm guessing the concerns you've raised around re-rendering are part of why we're looking to add shouldComponentUpdate. Could we take steps to address your concerns with adding shouldComponentUpdate checks? |
Regarding re-render concerns, can we extract out wrapper div With this, even if scrollbar state changes it doesn't re-render |
How about we include the shouldComponentUpdate check in FixedDataTable, but make it so it always returns true by default, but can be configured to do the comparison if the feature flag is set to use it? Would that work @pradeepnschrodinger ? It seems like it wouldn't break existing table users, but would let us move towards the more optimized approach and get testing of this new scrollbar API. |
@rtrg @pradeepnschrodinger anything remaining to be done here before we merge? |
Took care of minor comments from my side |
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.
Looks good to me. Apologies for the delays and thanks for follow ups :)
@wcjordan , as offlined some time ago, should we cut off master and make branch |
Yep. Although now that I think about it, maybe we should cut v1.0 and have 1.1 work go to master? That would reflect the branching model we use for LiveDesign and may be less confusing. |
To disable fdt default scrollbars, need to pass defaultScrollbars prop as false Can pass custom scrollbars by passing scrollbarX, scrollbarY. To update custom scrollbars state or trigger fdt scroll, pass onScrollBarsUpdate prop (function) which gets necessary arguments.
v1.0 branch has now been cut. Any concerns with me merging this to master? |
No concerns from my side, thanks. |
Awesome. I've merged! @rtrg any thoughts on what next steps we should look at? Should we look to add an example using native scroll? |
Thanks!
Yes, I will raise a PR for that soon. |
This is now released w/ v1.1. |
@rtrg any chance you have any documentation or an example putting this new API to use which we could add to the project? |
Description
This PR provides ability to pass custom scrollbars to FDT.
To disable fdt default scrollbars, need to pass
defaultScrollbars
prop as falseCan pass custom scrollbars by passing
scrollbarX
,scrollbarY
.To update custom scrollbars state or trigger fdt scroll, pass
onScrollBarsUpdate
prop (function) which gets necessary arguments.How Has This Been Tested?
Made sure all test cases are passing, by updating necessary tests.
Tested manually in examples that scrolling works.
Types of changes
Checklist: