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

[Select]Bug when the first child is a ListSubheader #27299

Merged
merged 13 commits into from
Apr 11, 2022
Merged

[Select]Bug when the first child is a ListSubheader #27299

merged 13 commits into from
Apr 11, 2022

Conversation

DouglasPds
Copy link
Contributor

@DouglasPds DouglasPds commented Jul 15, 2021

Checking if the child is a ListSubheader to return a different object in React.cloneElement.
And setting the second child as selected when the first child is a ListSubheader, to can use the arrow to navigate the options.
And when an option is selected has no more need to set the second option as selected.

#26790

@mui-pr-bot
Copy link

mui-pr-bot commented Jul 15, 2021

Details of bundle changes (experimental)

Generated by 🚫 dangerJS against 5a970c5

Copy link
Member

@eps1lon eps1lon left a comment

Choose a reason for hiding this comment

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

Could you please add some test to check the various branches of the code you introduced? It's not clear what we need all this added code for.

A demo would also be nice for this feature. Especially for manual testing.

@eps1lon eps1lon added component: select This is the name of the generic UI component, not the React module! new feature New feature or request PR: needs test The pull request can't be merged labels Jul 17, 2021
@DouglasPds
Copy link
Contributor Author

Could you please add some test to check the various branches of the code you introduced? It's not clear what we need all this added code for.

A demo would also be nice for this feature. Especially for manual testing.

I will try to explain the code I've made

return true;
};

if (child.props.value === undefined) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This returns a different object when the option is a ListSubheader. The role option is because the role listbox of the Menu needs that the children have the role option, but when the option is not a selectable option the aria-selected should be omitted.

@@ -385,7 +399,7 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
}
},
role: 'option',
selected,
selected: index === 1 && arr[0].props.value === undefined ? hasOptionSelected() : selected,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here when the first child is a ListSubheader it sets the selected true to the second option, to gains the focus when the list of options is open, with the tabindex = 0, to the arrow down works.

@@ -369,6 +369,20 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
foundMatch = true;
}

const hasOptionSelected = () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

And here, when you select an option don't need more to set the second option as selected true to gain the focus.

@DouglasPds
Copy link
Contributor Author

codesandbox example
Using the grouping example in the docs.

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Sep 1, 2021
@eps1lon eps1lon changed the base branch from next to master September 14, 2021 09:15
@mnajdova mnajdova requested a review from michaldudak November 19, 2021 10:49
Copy link
Member

@michaldudak michaldudak left a comment

Choose a reason for hiding this comment

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

Hi @DouglasPds. I've taken a look at your implementation and found one issue - the problem remains if the second element is also a header or a disabled MenuItem. In such cases, instead of selecting the second element, we'd have to look for the first selectable one.

@DouglasPds
Copy link
Contributor Author

@michaldudak you're right, this creates another problem, I will try this approach.

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

mui-bot commented Mar 2, 2022

Details of bundle changes

Generated by 🚫 dangerJS against 36402c8

@michaldudak
Copy link
Member

@DouglasPds you may be interested to know that we've recently created an unstyled select (https://mui.com/components/selects/#unstyled) that does not suffer from this issue. If you're still having this problem in your application, you may consider evaluating the SelectUnstyled instead.

@DouglasPds
Copy link
Contributor Author

@michaldudak oh nice, this issue doesn't occur. I will try them. And I find a solution to use with the Select, which I will share here for you to see and evaluate.

@DouglasPds
Copy link
Contributor Author

codesandbox example

Copy link
Member

@michaldudak michaldudak left a comment

Choose a reason for hiding this comment

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

Sorry for the delay. This solution does work better, but I think the code may be improved a bit.

Comment on lines 404 to 406
if (value) {
return selected;
}
Copy link
Member

Choose a reason for hiding this comment

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

This could be placed before arr.find(...) as it doesn't use its result.

Copy link
Member

@michaldudak michaldudak 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 good! Thanks for your work!

@michaldudak michaldudak removed the PR: needs test The pull request can't be merged label Apr 6, 2022
@michaldudak michaldudak merged commit a8db12e into mui:master Apr 11, 2022
@@ -405,7 +425,10 @@ const SelectInput = React.forwardRef(function SelectInput(props, ref) {
}
},
role: 'option',
selected,
selected:
arr[0].props.value === undefined || arr[0].props.disabled === true
Copy link
Member

Choose a reason for hiding this comment

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

@michaldudak @DouglasPds

This assumes that the first child is always a valid React component.
This leads to crash if the first child is of different type. Here is a first report

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I tried here and when the first child is a number, string, NaN, it crashes. The first solution that works was to put optional chaining to check the values after the props. Here where the value is passed to selected and inside the function isFirstSelectableElement.

Copy link
Member

Choose a reason for hiding this comment

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

arr[0].props?.value === undefined || arr[0].props?.disabled === true

You are suggesting this, right? As long as this doesn't break the logic of the fix this PR originally contained, I am fine with that. Will you be willing to ensure that and open a PR with the change?

return selected;
}
const firstSelectableElement = arr.find(
(item) => item.props.value !== undefined && item.props.disabled !== true,
Copy link
Member

Choose a reason for hiding this comment

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

@DouglasPds Let's ensure that item is a valid React component here as well to prevent potential crash.

@litera
Copy link

litera commented Feb 1, 2023

@michaldudak How in the world could you approve this PR because it's not resolving the root cause of keyboard interactivity issue but invalidly selects an item that shouldn't be selected in the first place (just to mitigate the keyboard bug)? This code should be reverted and an actual solution should be made. The problem seems to be that the code puts the focus on the wrong item. That code should be changed to resolve the bug and not as it was done here.

michaldudak added a commit to michaldudak/material-ui that referenced this pull request Feb 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: select This is the name of the generic UI component, not the React module! new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants