Skip to content

feat: dropdown component #2530

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

Closed
wants to merge 10 commits into from
Closed

feat: dropdown component #2530

wants to merge 10 commits into from

Conversation

omneimneh
Copy link

@omneimneh omneimneh commented Jan 27, 2021

Summary

This PR introduces a new component which is Dropdown and Dropdown.Option, I noticed that the native Picker in react-native isn't very customizable and doesn't look nice with other react-native-paper components.

I found other libraries on npm such as 'react-native-paper-dropdown' and 'react-native-material-dropdown' however I tested these libraries, they appear to have an issue displaying on the web, when developing this I went through the same problem because I was following their approach at first so I had to change a little bit.
I will try to explain it briefly:
If we want to create a dropdown in react (only web), we can use a div with relative position to parent by following this approach https://stackoverflow.com/a/5209833, however we will need to set the z-index to prevent other components down in the page to appear on top of the dropdown.
With react-native it's a little more complicated since all components by default have a relative position a a z-index preset to 0, so even if we increase the z-index of the dropdown we still can't make it appear above other components unless we change the z-index of the parent (and maybe other parents in the dom tree as well) https://stackoverflow.com/a/35326592.
The approach I took involved using a portal and computing the location of the dropdown when the user clicks on the component and displaying it, it works because the portal renders the dropdown at the top of the tree. But in this approach I assumed that the Provider component will provide the Protal.Host.

Test plan

Screenshot_20210127-110722
Screenshot_20210127-110657

I already provided an example in my PR, but I believe this is not ready to merge yet since there are tests and docs to add and maybe some refactoring required. Other features can be added as well like completely custom components (here I'm just using List.Item) and making the dropdown searchable... but I'll let you guys be the judge.

I'll keep updating the PR as much as I can until it's ready to merge and if anyone can also contribute with this it would be great

@callstack-bot
Copy link

callstack-bot commented Jan 27, 2021

Hey @omneimneh, thank you for your pull request 🤗. The documentation from this branch can be viewed here.

@omneimneh omneimneh marked this pull request as ready for review January 27, 2021 08:50
@omneimneh omneimneh marked this pull request as draft January 27, 2021 08:54
@omneimneh omneimneh marked this pull request as ready for review January 31, 2021 13:19
@omneimneh omneimneh force-pushed the main branch 6 times, most recently from eedefec to af51b5a Compare February 6, 2021 08:30
@omneimneh omneimneh force-pushed the main branch 2 times, most recently from 9e56b77 to 97d02f9 Compare February 6, 2021 22:57
@omneimneh omneimneh requested a review from brunohkbx February 12, 2021 08:41
@omneimneh
Copy link
Author

@brunohkbx any updates on this? thanks 😃

*/
label?: string;
/**
* Required flag removes the possibility for the user to unselect a value once it's selected.
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's not clear to me how this prop works. I'm still able to change the selected option 🤔

Copy link
Author

Choose a reason for hiding this comment

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

So the idea is to remove the option that comes with a value of null, if required is set to false, the default null option will be shown as the first option in the dropdown, so to make a dropdown required you should give it a value and set required to true.

Sorry if the docs are not very clear, I will try to improve them as much as I can, and if you think we need to change the behavior we can maybe change the required prop to something like showUnselectOption or make it an iconButton at the right of the textInput instead I don't mind.

/**
* This message will appear when the required prop is set to true and the number of children is zero.
*/
emptyDropdownLabel?: string;
Copy link
Collaborator

Choose a reason for hiding this comment

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

What do you think about adding an example with this?

const DEFAULT_EMPTY_DROPDOWN_LABEL = 'No available options';
const DEFAULT_PLACEHOLDER_LABEL = 'Select an option';
const DROPDOWN_NULL_OPTION_KEY = 'DROPDOWN_NULL_OPTION_KEY';
// const DEFAULT_MAX_HEIGHT = Infinity;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we keep this?

Copy link
Author

Choose a reason for hiding this comment

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

Hmm, I'm not sure about what the material design guides indicate sorry that I don't have much knowledge about this, I was thinking in case we have a very long dropdown and when displaying this on the web (floating mode) on a large display that we may prefer to limit the height of the dropdown, that was my thoughts when I started working on it but I guess we don't need it anymore so I can remove it if you want

{
children,
emptyDropdownLabel = DEFAULT_EMPTY_DROPDOWN_LABEL,
// maxHeight = DEFAULT_MAX_HEIGHT,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we need this?

) {
return React.Children.toArray(children)
.map((child) => (child as any)?.props)
.find((props) => props?.value === value);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering if wouldn't be better to filter by the key here. just in case when someone uses the same value by mistake.

@@ -44,7 +45,6 @@ export { default as Appbar } from './components/Appbar';
export { default as TouchableRipple } from './components/TouchableRipple/TouchableRipple';
export { default as TextInput } from './components/TextInput/TextInput';
export { default as ToggleButton } from './components/ToggleButton';

Copy link
Collaborator

Choose a reason for hiding this comment

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

No need to remove this line

}, [children, selectedValue]);

React.useEffect(() => {
if (isMenuOpen) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

How about creating a custom hook for this? Something like useOrientations (maybe you can come up with a better name)
You can create it in two different files: useOrientations.native.js and useOrientations.js
just to clean up this a little

@brunohkbx
Copy link
Collaborator

@omneimneh I just realized that there's a missing top/bottom margin in the dropdown. Check it out:

From MD guide: https://material.io/components/menus#specs
Screenshot from 2021-02-23 00-02-25

dropdown

@brunohkbx
Copy link
Collaborator

Also, can we support this error state?

Screenshot from 2021-02-23 00-34-13

* A dropdown can be either be rendered inside a modal or inside a floating menu
* The default value is 'floating' if the platform is web and 'modal' otherwise
*/
mode?: 'modal' | 'floating';
Copy link
Collaborator

Choose a reason for hiding this comment

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

About this floating mode, shouldn't this be only available on web? I couldn't find anything in the MD docs regarding this https://material.io/components/menus

Copy link
Author

@omneimneh omneimneh Feb 24, 2021

Choose a reason for hiding this comment

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

Sorry about that too, I wasn't sure what the correct behavior should be based on the material design guidelines, from what I saw there was only a "floating" mode (I didn't know what to call it) but the default Spinner of the android appears in a modal (or at least used too, it's been a long time since I used native android). Anyways we I can fix this as soon as we figure out what the correct behavior is.

image

Copy link
Author

Choose a reason for hiding this comment

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

I believe they call it exposed dropdown menu

@github-actions
Copy link

Hello 👋, this pull request has been open for more than 2 months with no activity on it. If you think this is still necessary with the latest version, please comment and ping a maintainer to get this reviewed, otherwise it will be closed automatically in 7 days.

@github-actions github-actions bot added the Stale label Apr 26, 2021
@avvari-da
Copy link

@brunohkbx Hello, please let me know if this is going live

@brunohkbx
Copy link
Collaborator

hey @lukewalczak can you please take a look when you have some time?

@RichardLindhout
Copy link
Contributor

I'm working on a similar component but I only tested it on the web for now but it will improve in the coming month:
https://github.com/web-ridge/react-native-paper-autocomplete

@NahumG10
Copy link

NahumG10 commented Dec 12, 2021

How do I intall this component in my app? I'm using Expo

@mggevaer
Copy link

mggevaer commented Feb 9, 2022

+1
I'm using react-native-paper and wanted to use a dropdown picker the Project as well, unfortunately did not find one with good web & react-native support as mentioned at the start of this PR. Looking for other solutions now.

@Angelk90
Copy link

@lukewalczak , @omneimneh : Are there any news?

@jigarzon
Copy link

jigarzon commented Mar 2, 2023

Any news on this PR?

@fellenabmb
Copy link

Any news on this one? 😄

@H-pun
Copy link

H-pun commented Jun 18, 2023

Any news on this?

@omneimneh
Copy link
Author

Hello everyone, sorry for not being able to close this PR. A lot of things has changed with the material design M3 and it was very difficult to find a convenient time to work on this but I'll try to work on it in the upcoming days although I can't promise anything due to life/work commitments.
Sorry again for keeping this open for too long and thanks for understanding.

@omneimneh
Copy link
Author

I moved this to a new PR #4102

@omneimneh omneimneh closed this Sep 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.