-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
[DataGrid] Prevent column header scroll #4280
Conversation
These are the results for the performance tests:
|
} else { | ||
headerCellRef.current!.focus(); | ||
const elementToFocus = focusableElement || headerCellRef.current; | ||
elementToFocus?.focus({ preventScroll: true }); |
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.
AFAIK this preventScroll
is not viable because it doesn't work on Safari. What I would propose instead is to look into why the container is scrollable in the first place. We use translate 3d, so why is it possible for scrollLeft
to not always be 0 in the first place?
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.
Even adding overflow: hidden
I still can scroll a div. It's expected: https://stackoverflow.com/questions/33703204/is-scrolltop-and-scrollleft-for-overflow-hidden-elements-reliable
In the past, we even did a small hack by listening to scroll
and calling scrollLeft=0
to prevent scrolling the container - which had overflow: hidden
- when using a touchpad device.
mui-x/packages/grid/_modules_/grid/hooks/features/virtualization/useGridVirtualRows.ts
Lines 487 to 492 in b81daef
const preventScroll = React.useCallback((event: any) => { | |
event.target.scrollLeft = 0; | |
event.target.scrollTop = 0; | |
}, []); | |
useNativeEventListener(apiRef, windowRef, 'scroll', handleScroll, { passive: true }); |
AFAIK this preventScroll is not viable because it doesn't work on Safari.
That's why I call scrollLeft=0
down below if preventScroll
is not supported.
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.
Right ok, great points, all my previous points have been answered.
I had a closer look: did you consider this option?
- Only do this:
mui-x/packages/grid/x-data-grid/src/components/columnHeaders/GridColumnHeaderItem.tsx
Line 210 in 65cf41c
apiRef.current.columnHeadersContainerElementRef!.current!.scrollLeft = 0; |
- Remove (seems dead code)
mui-x/packages/grid/x-data-grid/src/hooks/features/columnHeaders/useGridColumnHeaders.tsx
Lines 52 to 54 in 6643404
React.useEffect(() => { | |
apiRef.current.columnHeadersContainerElementRef!.current!.scrollLeft = 0; | |
}, [apiRef]); |
I'm asking because using preventScroll
here might introduce the same problems as #4282 (vertical scrolling) but for horizontal scrolling.
Actually, speaking of horizontal scrolling, I have found a bug when rows={[]}
https://codesandbox.io/s/datagridprodemo-material-demo-forked-8e4l8w:
- focus a header cell
- use the arrow left or arrow right to move the focus
- the body doesn't scroll horizontally
Now, maybe we don't need to care. Who would try to scroll/use the arrow key? There are no data loaded 😁
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.
The "no row" bug can be fixed. It's an early return to modify in scroll hook
Is it necessary to prevent scroll? I thought adding the hasFocus
un the useLayoutEffect
dependencies was enough to prevent scroll on rendering
The only bug I can think of with the scroll on rendering is when the element is unmounted because it goes out of the virtualization engine and comes back. But that's a larger problem.
For example, I set focus on a cell, I can use keyboard navigation as long as the cell is in the virtualisation buffer. As soon as it exits the buffer, the focus moves to <body>
and the gird does not respond anymore to keyboard interactions
https://github.com/mui/mui-x/blob/master/packages/grid/x-data-grid/src/hooks/features/scroll/useGridScroll.ts#L56:L58
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 removed preventScroll
and kept only scrollLeft=0
. I didn't realize the side effect of using it.
I thought adding the hasFocus un the useLayoutEffect dependencies was enough to prevent scroll on rendering
It's not sufficient. If I remove scrollLeft=0
and scroll very fast to left and right the bug appears at some point. This happens because the column header component may be mounted during scroll.
The "no row" bug can be fixed. It's an early return to modify in scroll hook
Interesting, I won't fix it here. Feel free to submit a PR.
Now, maybe we don't need to care. Who would try to scroll/use the arrow key? There are no data loaded 😁
If what caused "no results" was applying a filter in a column that's outside the visible area, then the user may use the arrow keys to navigate to them. We had a issue about that when we blocked the scrollbar if rows=[]
: #3795 (comment)
@@ -171,7 +171,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => { | |||
|
|||
columns.push( | |||
<GridColumnHeaderItem | |||
key={i} | |||
key={column.field} |
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.
Prevents the effect triggering twice.
Fixes 1st bug from #4275 (comment)
Same solution from #3718 and #2558
Before: https://codesandbox.io/s/intelligent-pasteur-5etmhd?file=/src/App.js
After: https://codesandbox.io/s/immutable-star-qb78zz?file=/src/App.js