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

[DataGrid] Improve selection with keyboard #4157

Merged
merged 24 commits into from
Mar 29, 2022

Conversation

flaviendelangle
Copy link
Member

@flaviendelangle flaviendelangle commented Mar 11, 2022

Fixes #4185

  • When reducing a selection range, keep the focus key selected
  • Drop useGridKeyboard (movie the publication of cellNavigationKeydown in useGridKeyboardNavigation and the content of expandCellSelection in useGridSelection)

@flaviendelangle flaviendelangle self-assigned this Mar 11, 2022
@mui-bot
Copy link

mui-bot commented Mar 11, 2022

These are the results for the performance tests:

Test case Unit Min Max Median Mean σ
Filter 100k rows ms 264.9 585.6 479.7 428.68 124.531
Sort 100k rows ms 444.3 999.9 911.4 821.8 205.618
Select 100k rows ms 118.4 283.8 189.2 186.3 57.85
Deselect 100k rows ms 104.4 345.2 141.5 175 86.854

Generated by 🚫 dangerJS against 8f0c73e

@@ -64,6 +63,7 @@ export const useDataGridComponent = (props: DataGridProcessedProps) => {
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
useGridInitializeState(columnMenuStateInitializer, apiRef, props);

useGridKeyboardNavigation(apiRef, props);
Copy link
Member Author

Choose a reason for hiding this comment

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

useGridSelection must consume the cellKeydown after the navigation have been applied.

@flaviendelangle flaviendelangle marked this pull request as ready for review March 11, 2022 12:57
@flaviendelangle flaviendelangle requested review from m4theushw and alexfauquette and removed request for m4theushw March 11, 2022 12:57
Copy link
Member

@alexfauquette alexfauquette left a comment

Choose a reason for hiding this comment

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

From the preview, it seems you did not fix the issue #4156

In expandRowRangeSelection, there is

if (startIndex > endIndex) {
endId = visibleRowIds[endIndex + 1];
} else {
endId = visibleRowIds[endIndex - 1];
}

Which forget the case when user click on the same cell

else if (startIndex === endIndex) {
	endId = visibleRowIds[endIndex];
}

@flaviendelangle
Copy link
Member Author

flaviendelangle commented Mar 11, 2022

I mis-read the issue and fixed another bug 😆
My bug was with the keyboard and the issue is talking about the mouse.
I will also fix it then.

Copy link
Member

@alexfauquette alexfauquette left a comment

Choose a reason for hiding this comment

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

The bug could be tested, but I'm not sure it's interesting to add it

Copy link
Member

@m4theushw m4theushw left a comment

Choose a reason for hiding this comment

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

I would be very careful when changing how the selection works. I would prefer to have a PR only fixing #4156. With #4157 I can't expand the selection holding Shift while pressing ArrowDown.

msedge_5VthSSdvWt

This happens because we do nothing if the target is not the cell root. There's a TODO to improve this check but I don't know the side effects doing it now.

if (!isGridCellRoot(event.target as Element)) {

@@ -108,6 +112,9 @@ export const useGridSelection = (
const visibleRowIds = gridVisibleSortedRowIdsSelector(apiRef);
const startIndex = visibleRowIds.findIndex((rowId) => rowId === startId);
const endIndex = visibleRowIds.findIndex((rowId) => rowId === endId);
Copy link
Member

Choose a reason for hiding this comment

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

Could apiRef.current.getRowIndexRelativeToVisibleRows be used here?

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think so because when expanding with the mouse, we support cross-page expansion.

You click on a row of page 1
You go to page 2
You shift click a row of page 2

=> It selects all the row between your two clicks.

@flaviendelangle
Copy link
Member Author

I would be very careful when changing how the selection works. I would prefer to have a PR only fixing #4156.

I will extract the fix for #4156 in a standalone PR 👍

This happens because we do nothing if the target is not the cell root. There's a TODO to improve this check but I don't know the side effects doing it now.

@m4theushw ok so before this PR, the isGridCellRoot check was done to select to row by pressing Enter + Shift or to select all rows by pressing Ctrl + A
But it was not applied to expand the row selection by pressing Shift + Arrow Up / Down.

Do we need the check at all for selection ? Was this check for some scenarios but not others the right behavior or just an error ?

@m4theushw
Copy link
Member

Do we need the check at all for selection ? Was this check for some scenarios but not others the right behavior or just an error ?

The check was added to fix #701. It might be useless now. But if keep it, then it's better to extend to check if the keydown came from inside the cell, not only the root.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Mar 17, 2022
@github-actions
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Mar 17, 2022
// Get the most recent params because the cell mode may have changed by another listener
const cellParams = apiRef.current.getCellParams(params.id, params.field);

if (cellParams.cellMode !== GridCellModes.Edit && isNavigationKey(event.key)) {
Copy link
Member

@m4theushw m4theushw Mar 21, 2022

Choose a reason for hiding this comment

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

Space is not a navigation key if it is pressed when the focus is on the checkbox column. It jumps if a click only on the border of the checkbox. By doing an additional check here, you can remove the event.preventDefault. Also, the modification in the order that the hooks are called can be reverted.

msedge_5cXogi4eMh

if (focusCell && focusCell.id !== params.id) {
event.preventDefault();

const isPreviousRowSelected = apiRef.current.isRowSelected(focusCell.id);
Copy link
Member

Choose a reason for hiding this comment

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

We're relying on the fact that the focus was not updated yet. If the order of the listeners is changed, or we change to listen for the event in the capture phase, it won't work. Would it work if lastRowToggled is used here instead?

Copy link
Member Author

Choose a reason for hiding this comment

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

We're relying on the fact that the focus was not updated yet.

The opposite, I missed-named this variable, it should be isNewRowSelected
I access the previous row through params.id and the new one through focusCell.id

I don't think we could easily cover all use cases
If you navigate with the keyboard without selecting rows, your "previousRow" still needs to be the cell the focus is currently in, not the last row toggled.
I agree that this is a constraint on the call order and that is why I am putting useGridKeyboardNavigation before useGridSelection.

Copy link
Member

Choose a reason for hiding this comment

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

Sounds fair. I only don't like the constraint on the call order, but I don't have any other simple solution. We could listen to cellFocusIn and try to track if the new focus came from the keyboard navigation. It's a way to not depend on the call order but much more complex. We can leave it as it is.

Copy link
Member Author

Choose a reason for hiding this comment

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

Alternatively, the keyboard navigation could publish an event keyboardNavigation with the cell before and after.

} else {
// We are navigating to the top of the page and adding selected rows
start = newRowIndex;
end = previousRowIndex - 1;
Copy link
Member

@m4theushw m4theushw Mar 21, 2022

Choose a reason for hiding this comment

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

There's a bug here. If I press ArrowUp already with Shift pressed, it ignores the first row.

msedge_ubqGBx7SP5

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed

@@ -346,48 +346,48 @@ describe('<DataGrid /> - Selection', () => {
});
});

/* eslint-disable material-ui/disallow-active-element-as-key-event-target */
Copy link
Member

Choose a reason for hiding this comment

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

Could you update the tests so we don't need to ignore this ESLint rule? To keep consistent with the core.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@flaviendelangle flaviendelangle added component: data grid This is the name of the generic UI component, not the React module! feature: Selection Related to the data grid Selection feature labels Mar 29, 2022
Copy link
Member

@m4theushw m4theushw left a comment

Choose a reason for hiding this comment

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

Ignore.

Co-authored-by: Matheus Wichman <matheushw@outlook.com>
@flaviendelangle flaviendelangle merged commit dcaeab3 into mui:master Mar 29, 2022
@flaviendelangle flaviendelangle deleted the selection-keyboard branch March 29, 2022 15:00
alexfauquette pushed a commit to alexfauquette/mui-x that referenced this pull request Aug 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: data grid This is the name of the generic UI component, not the React module! feature: Selection Related to the data grid Selection feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[data-grid] Pressing Shift + ArrowUp unselect two rows when the row above the focus is selected
4 participants