-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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: Menu component #485
feat: Menu component #485
Conversation
Hey @iyadthayyil, thank you for your pull request 🤗. The documentation from this branch can be viewed here. Please remember to update Typescript types if you changed API. |
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.
Hi Iyad!
First of all, please excuse me for taking so long to review this PR. This should have happened much earlier. Thank you for your contribution. It's exciting to see that you tackle writing this -- quite important -- component.
However, there are two major issues with your approach:
- The position of the menu is not updated when the screen changes orientation:
- If the menu is larger than available vertical space, it should become a scrollable view. Instead, it flows outside of the screen:
Also, another minor blocker is that the dropdown menu default placement should be below the element that generates it (see relevant material docs). While this is not so for all of elements (indeed some menus should appear on top of the generating element), it should be the default. I believe that we should support steering of the placement of the menu, relatively to the generating element, but it's good enough for the initial version to stick with the default mentioned above.
I also have several other comments about the code. Please address them, or give more support for the choices that you made.
Thanks again!
* }); | ||
* ``` | ||
*/ | ||
class Surface extends React.Component<Props> { |
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.
Frankly, I don't see much value in having Surface
as a separate component. It's used in just one place, and only adds some styles. Can you tell me what use this component has outside of how it's used in your PR?
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 a quick hack to overcome an animation problem I faced when creating a new animated view from the existing Surface
component. This was the original way I did it:
const AnimatedSurface = Animated.createAnimatedComponent(Surface);
But this seems to render very choppy animations, would like to know if there is a way to just use Surface
without this animation issue.
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.
@iyadthayyil We can change View
to Animated.View
here: https://github.com/callstack/react-native-paper/blob/master/src/components/Surface.js#L65
Then we wouldn't need Animated.createAnimatedComponent(Surface)
src/components/Menu/Menu.js
Outdated
}; | ||
|
||
/** | ||
* Menus display a list of choices on temporary surfaces. Their placement varies based on the element that opens them. |
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.
Nit: add 'elevated' before 'surfaces'. Also elaborate on the placement -- I believe it only adapts based on the source element's position + actual size of the menu.
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.
Ok will do that.
<Animated.View | ||
{...rest} | ||
style={[ | ||
styles.surface, |
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.
Since the only rule that styles.surface
has is backgroundColor
, it will be overridden by the next line. Please remove it.
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 just used the same code from the original Surface
component, but will change that, also should probably change that in the original Surface
component aswell.
src/components/Menu/Menu.js
Outdated
this.setState({ buttonWidth: width, buttonHeight: height }); | ||
}; | ||
|
||
_toggle = () => { |
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.
Nit: This doesn't really "toggle" anything, it just updates the shown/hidden state, so I suggest renaming it to "_updateVisibility"
src/components/Menu/Menu.js
Outdated
menuSizeAnimation, | ||
} = this.state; | ||
|
||
const menuSize = { |
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.
You use this constant only once, and really far away from this declaration. It's a bit confusing why you need this until line 282, especially since you keep using menuSizeAnimation.x
and menuSizeAnimation.y
. Please avoid defining it and instead inline it's use below.
src/components/Menu/Menu.js
Outdated
} | ||
|
||
// RTL support | ||
const leftOrRight = I18nManager.isRTL ? { right: left } : { left }; |
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.
You use this constant only once, please inline it where it's used.
src/components/Menu/MenuItem.js
Outdated
}; | ||
|
||
/** | ||
* A component to show list of options inside a Menu. |
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.
Nit: I believe this component just shows a single option inside a Menu, no?
src/components/Menu/MenuItem.js
Outdated
*/ | ||
icon?: IconSource, | ||
/** | ||
* Whether the `MenuItem` is disabled. A disabled `MenuItem` is greyed out and `onPress` is not called on touch. |
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.
Nit: write 'item' instead of `MenuItem`.
src/components/Menu/MenuItem.js
Outdated
maxWidth: maxWidth - 16, | ||
}, | ||
widthWithIcon: { | ||
maxWidth: maxWidth - (8 * 6 + 40), |
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.
Can you explain where does "8 * 6 + 40" come from? Possibly define a marginWidth
const so that it's clear where does '8' come from.
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.
Ok will clear this up with some variables.
src/components/Menu/MenuItem.js
Outdated
.string(); | ||
|
||
if (disabled) { | ||
iconColor = titleColor = color(theme.dark ? white : black) |
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.
Please define const disabledColor
instead, and use it with the ?:
operator to define const titleColor
and iconColor
.
@iyadthayyil are you still working on this or you need some help? :) |
Ok, sorry guys, I have been busy with uni work, will try to get this ready soon. |
Maybe we can do it step by step and take a look to rotation later and other edge cases. Let us know if you need help @iyadthayyil. |
f33cab9
to
295a771
Compare
Any ETA for this component?? This component looks beautiful |
knock knock |
please move forward, we need menu |
Hey guys, I want to help merge this PR. Can I rebase from 'upstream' master, the main reason is so that we can remove |
Hey guys, I have made some changes to follow the new way of doing things compared to when the PR was first created. Part of this was to add the typescript typings here: |
Hey @waquidvp thanks for coming back to this. I guess you work together with @iyadthayyil ? Would you mind adding: Screenshots and code for docs? You can see how to do it from other components. I am also wondering if we could animate scale instead animating |
There were already some screenshots and some code examples. They just weren't in the right place and so wasn't showing up in the generated docs. I have moved it to the right place and the docs look ok now. |
To solve the status bar issue, should a combination |
Let's do it for now. We can refactor to extract this logic later. |
@satya164 can we have your approval here for merging it? |
ohhh! amazing! thanks all. |
Great work @iyadthayyil! Thanks everyone! |
Can the Menu component be used as a Dropdown for TextInput as shown https://material.io/design/components/menus.html#exposed-dropdown-menu ? Replacing the |
@Zefau I also needed to do something similar and I ended up using focus and blur events. It's working on android simulator & device, but for ios is working just in the simulator, I think the surface height bug it's caused by the ScrollView issue described here Any ideea what might be the problem ? This is how the component looks like
The PaperMenu is a fork of Menu component to temporary fix the bug #970 |
On iOS Statusbar.currentHeight does not work so ending up with a undefined top. |
Yes..I use a default value of 40 for now..so i removed StatusBar completely..the issue I have now is with the height of the menu..not the position |
Please create issue ticket instead of posting here. This component is very new so you will see lot of issues. |
Motivation
Menu component with auto positioning and RTL support:
https://material.io/design/components/menus.html
fixes: #9
Test plan