Skip to content

feat: added dropdown component #4102

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

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

omneimneh
Copy link

I have previously created this PR #2893.
This was a long time ago and the branch fell behind very far from the current main branch.
Also material m3 has been released so I thought it's a better idea to redo the work from scratch to better align with the new guidelines and the new code version.

Dropdown menus are very commonly used. From a design perspective, dropdown menu is referred to as Menu in material design guidelines, but it's a pain having to create this component with the expected functionality from a developer point of view. At least this is the impression I got from the comments in the previous PR.

image

The dropdown component in this PR is just a combination of a TextInput and a Menu component with an out-of-the-box functionality to select a specific item in the menu.

image

If you think this is a good idea, I'd like to kindly ask for your help to fix any mistakes and enrich this PR with tests/docs (or anything that I missed) so it can hopefully be merged in the repo.

Thanks!

@callstack-bot
Copy link

callstack-bot commented Sep 30, 2023

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

@Angelk90
Copy link

@omneimneh : It will also support this model:

image

https://m2.material.io/components/menus#exposed-dropdown-menu

@omneimneh
Copy link
Author

@omneimneh : It will also support this model:

image

https://m2.material.io/components/menus#exposed-dropdown-menu

Thanks for providing this link.
I think it behaves in the way described, although there might be minor changes (like the arrow icon).
Please point out if you see anything else missing or contradicting the behavior or design that is intended.

@Angelk90
Copy link

Angelk90 commented Oct 1, 2023

@omneimneh : Could you provide an example of everything on snack.expo so we can try it?

How does multiple item selection work?

@omneimneh
Copy link
Author

@omneimneh : Could you provide an example of everything on snack.expo so we can try it?

How does multiple item selection work?

How do I use this version of react-native-paper in snack.expo?

I did not support multiple item selection since I never seen it in native android or in material design guidelines.
I think for that it's better to use radio buttons or switches. What do you think?
https://m2.material.io/components/selection-controls

@Angelk90
Copy link

Angelk90 commented Oct 2, 2023

@omneimneh : Shouldn't you be looking at v3?

https://m3.material.io/components

Will it support grouped items?

Take a look here for the various types of dropdowns, although I don't know if it has much to do with Android's material design: https://mui.com/material-ui/react-autocomplete/#grouped

@lukewalczak
Copy link
Member

Hey @omneimneh, I've run your example, however when pressing the any of anchors there's nothing going on. Could you please check it?

@omneimneh
Copy link
Author

Hey @omneimneh, I've run your example, however when pressing the any of anchors there's nothing going on. Could you please check it?

It's weird that I didn't notice this issue before, it seems like I have to click twice in order to open the menu, I will check this issue. But I also think there's also another bug in the Menu component when the anchor is at the bottom of the screen.

Recording.2023-10-06.083451.mp4

@omneimneh
Copy link
Author

@omneimneh : Shouldn't you be looking at v3?

https://m3.material.io/components

Will it support grouped items?

Take a look here for the various types of dropdowns, although I don't know if it has much to do with Android's material design: https://mui.com/material-ui/react-autocomplete/#grouped

I think it's easy to add this once we have a working component. I see this more as a compound component and there's an example of it in m3 figma file, but I didn't see any specific requirements. Please note that I'm not very familiar with design systems in general but I'm trying my best to follow the documentation.

I'm happy to change it depending on the requirements if you have them.
Otherwise my suggestion is let's start by identifying the different use cases, we can check examples of usage in some google apps.
Then we can comply with the naming as well (whether it's Dropdown, ComboBox, Autocomplete, Exposed Menu...)
And I'll do my best to finish & fix the implementation.

@Angelk90
Copy link

Angelk90 commented Oct 8, 2023

@omneimneh : I can't find it in the figma file, can you take a screenshot?

@omneimneh
Copy link
Author

@omneimneh : I can't find it in the figma file, can you take a screenshot?

https://www.figma.com/community/file/1035203688168086460/material-3-design-kit

@Angelk90
Copy link

Angelk90 commented Oct 8, 2023

@omneimneh :

see this more as a compound component and there's an example of it in m3 figma file.

I looked at the figma file but I can't find this example you mention.

@omneimneh
Copy link
Author

@omneimneh :

see this more as a compound component and there's an example of it in m3 figma file.

I looked at the figma file but I can't find this example you mention.

image

@Angelk90
Copy link

Angelk90 commented Oct 9, 2023

I see this more as a compound component and there's an example of it in m3 figma file

I had seen this too, I thought you were referring to something there that allowed you to select multiple elements.

I was thinking of something like this:

Screenshot 2023-10-09 alle 10 59 37

@Angelk90
Copy link

@omneimneh : Is there any news?

@possum-enjoyer
Copy link

Is there an update on this? Would be very cool to use. I was tinkering with this code and found that

useEffect(() => { menu?.measureInWindow((_x, _y, width, _height) => { setWidth(width); }); }, [open, menu]);

Doesn't really work, width is undefined so the width can't be really calculated. Couldn't this be simplified by using the onLayout Event of the view? Or are there circumstances where this won't fire? It would uncomplicate the some code.

@ondrejnedoma
Copy link
Contributor

Any version milestone on this? Many devs have been waiting for this component for months or years, and this is the closest we've ever been.

@szingg
Copy link

szingg commented Jan 15, 2024

useEffect(() => { menu?.measureInWindow((_x, _y, width, _height) => { setWidth(width); }); }, [open, menu]);

Doesn't really work, width is undefined so the width can't be really calculated. Couldn't this be simplified by using the onLayout Event of the view? Or are there circumstances where this won't fire? It would uncomplicate the some code.

yes. the onLayout event resolves the issue. there's an ugly shadow in outlined mode that can be fixed by setting the ripple color to transparent.

@omneimneh i propose the following changes:

- const [menu, setMenu] = useState<View | null>(null);
- ...
- useEffect(() => {
-     menu?.measureInWindow((_x, _y, width, _height) => {
-         setWidth(width);
-     });
- }, [open, menu]);
- ...
- <View ref={setMenu}>
-     <TouchableRipple onPress={() => setOpen(true)}>
+ <View onLayout={x => setWidth(x.nativeEvent.layout.width) }>
+     <TouchableRipple onPress={() => setOpen(true)} rippleColor={'transparent'}>

Item: typeof DropdownItem;
};

const Dropdown: DropdownExport = Object.assign(

Choose a reason for hiding this comment

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

Isn't cleaner to write

Dropdown.Item = DropdownItem;

like do we need to use Object.assign?

<TouchableRipple onPress={() => setOpen(true)}>
<TextInput
editable={false}
right={

Choose a reason for hiding this comment

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

I would preferer to have a prop called something like disableClearButton in case I don't want the clear button, and having clearButton or renderClearButton prop that accepts function that's going to render the button in case I want another icon or look, or maybe as simple as clearButtonIcon.

* The clear button will show by default to remove the current value.
* If required is set to true, this button will not appear.
*/
required?: boolean;

Choose a reason for hiding this comment

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

can we have extra props for modifying UI components, like ViewContainerProps, MenuProps, and TextInputProps etc...

@AbdUlHamedMaree
Copy link

I can help finishing this, but I'm new to open source contribution if anyone can guide me how to change this code

@AbdUlHamedMaree
Copy link

and we need to map the menu items inside some kind of scroll view, so on large items number we can scroll inside the menu..

@H-pun
Copy link

H-pun commented May 29, 2024

Bruh finally the feature that we all need. Pls update

@bruno-py
Copy link

This looks awesome!

Could you released it as a npm package?

@iM-GeeKy
Copy link

iM-GeeKy commented May 5, 2025

@lukewalczak Are there any plans to incorporate this into the library? Glad to have you back working on the repo, absolute savior 💪🏼😎

@lukewalczak lukewalczak force-pushed the main branch 5 times, most recently from 1062366 to 1da5d15 Compare May 8, 2025 09:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.