-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
feat: dropdown component #2530
Conversation
Hey @omneimneh, thank you for your pull request 🤗. The documentation from this branch can be viewed here. |
eedefec
to
af51b5a
Compare
9e56b77
to
97d02f9
Compare
@brunohkbx any updates on this? thanks 😃 |
*/ | ||
label?: string; | ||
/** | ||
* Required flag removes the possibility for the user to unselect a value once it's selected. |
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.
It's not clear to me how this prop works. I'm still able to change the selected option 🤔
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.
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; |
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.
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; |
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.
Should we keep this?
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.
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, |
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.
Do we need this?
) { | ||
return React.Children.toArray(children) | ||
.map((child) => (child as any)?.props) | ||
.find((props) => props?.value === value); |
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'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'; | |||
|
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.
No need to remove this line
}, [children, selectedValue]); | ||
|
||
React.useEffect(() => { | ||
if (isMenuOpen) { |
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.
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
@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 |
* 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'; |
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.
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
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.
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.
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 believe they call it exposed dropdown menu
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. |
@brunohkbx Hello, please let me know if this is going live |
hey @lukewalczak can you please take a look when you have some time? |
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: |
How do I intall this component in my app? I'm using Expo |
+1 |
@lukewalczak , @omneimneh : Are there any news? |
Any news on this PR? |
Any news on this one? 😄 |
Any news on this? |
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. |
I moved this to a new PR #4102 |
Summary
This PR introduces a new component which is
Dropdown
andDropdown.Option
, I noticed that the nativePicker
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
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