-
Notifications
You must be signed in to change notification settings - Fork 231
feat(menu-surface): upgrade to mdc web v1 #762
feat(menu-surface): upgrade to mdc web v1 #762
Conversation
@@ -253,62 +250,60 @@ class MenuSurface extends React.Component<MenuSurfaceProps, MenuSurfaceState> { | |||
getWindowScroll: () => { | |||
return {x: window.pageXOffset, y: window.pageYOffset}; | |||
}, | |||
setPosition: (position: Position) => { | |||
setPosition: (position: Partial<MDCMenuDistance>) => { |
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.
Previously, Position
had properties with string type. but MDCMenuDistance
has properties with number type. You might need to append px
when setting style.
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.
Good catch! It was actually working this way before (as a number). I also verified that it is automatically added on to the value when rendered. Do you think I should still add px
?
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.
Ah ok. Didn't know it automatically adds 'px' suffix. is that a React thing?
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 must be, but I couldn't fin any documentation on this.
packages/menu-surface/index.tsx
Outdated
@@ -217,15 +212,16 @@ class MenuSurface extends React.Component<MenuSurfaceProps, MenuSurfaceState> { | |||
this.previousFocus.focus(); | |||
}, | |||
isFirstElementFocused: () => | |||
this.firstFocusableElement && | |||
Boolean(this.firstFocusableElement) && |
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.
Does't typescript has sugar syntax for null checking?
this!.firstFocusableElement === document.activeElement
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.
actually I don't even need the Boolean() part. firstFocusableElement
and last
will be an HTMLElement or null. Which means that in all cases this.firstFocusableElement === document.activeElement
will be valid.
setTransformOrigin: (transformOrigin: string) => this.setState({transformOrigin}), | ||
return { | ||
addClass: (className: string) => { | ||
const classList = new Set(this.state.classList); |
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.
if this.state.classList
is already of Set type why do we need to instantiate this with Set
again?
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.
If we just add to the existing Set, React will not detect a change meaning there won't be a re-render. React does not do a deep comparison.
classList.delete(className); | ||
this.setState({classList}); | ||
}, | ||
hasClass: (className: string) => this.classes.split(' ').includes(className), |
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.
This should use classList
(Set) state for consistency.
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 naming might be causing confusion, but classList
is from the foundationClasses (what I want to rename all of them to). this.classes
contains all the classes that are on the menu-surface, including mdc-menu-surface
, mdc-menu-surface--fixed
, and anything the foundation or user add to the component.
packages/menu-surface/index.tsx
Outdated
hasClass: (className: string) => this.classes.split(' ').includes(className), | ||
hasAnchor: () => !!this.props.anchorElement, | ||
notifyOpen: () => { | ||
if (this.registerWindowClickListener) { |
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.
Why do we need to register window listener here? Seems like this adapter doing more stuff than it should. We're not doing it in vanilla component implementation?
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 actually gets registered during the OPENED_EVENT this.listen(strings.OPENED_EVENT, this.registerBodyClickListener_);
, which eventually calls the #adapter.notifyOpen
method. Since we don't listen to the events, this is the closest we can get to the vanilla component. What are your thoughts?
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 feel it is clearer if we encapsulate these event registrations.
notifyOpen: () => {
this.handleOpen_();
this.props.onOpen!();
}
So you can put more stuff in handleOpen_
in feature if need to be. Same for notifyClose
.
WDYT?
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.
Ya that would clean up the adapter. Sounds good to me
this.props.onClose!(); | ||
}, | ||
isElementInContainer: (el: HTMLElement) => { | ||
if (!this.menuSurfaceElement.current) return false; |
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.
.contains
also includes the root element so you don't need to compare it with root yourself.
The adapter implementation can be shortened to:
this.menuSurfaceElement!.current.contains(el);
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.
good to know!
return this.menuSurfaceElement.current.contains(el); | ||
}, | ||
isRtl: () => { | ||
if (!this.menuSurfaceElement) return false; |
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've seen many places that you're checking if this.menuSurfaceElement
is null or undefined. Would this every be null or undefined? Can we not use Non-null assertion operator? (this.menuSurfaceElement!.current
)
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.
There is a time when this could be undefined/null, which is before componentDidMount, and after componentWillUnmount. So assuming that it is non-null
is not accurate.
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.
LGTM. Responded to your other comments.
@@ -253,62 +250,60 @@ class MenuSurface extends React.Component<MenuSurfaceProps, MenuSurfaceState> { | |||
getWindowScroll: () => { | |||
return {x: window.pageXOffset, y: window.pageYOffset}; | |||
}, | |||
setPosition: (position: Position) => { | |||
setPosition: (position: Partial<MDCMenuDistance>) => { |
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.
Ah ok. Didn't know it automatically adds 'px' suffix. is that a React thing?
packages/menu-surface/index.tsx
Outdated
hasClass: (className: string) => this.classes.split(' ').includes(className), | ||
hasAnchor: () => !!this.props.anchorElement, | ||
notifyOpen: () => { | ||
if (this.registerWindowClickListener) { |
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 feel it is clearer if we encapsulate these event registrations.
notifyOpen: () => {
this.handleOpen_();
this.props.onOpen!();
}
So you can put more stuff in handleOpen_
in feature if need to be. Same for notifyClose
.
WDYT?
2639599
to
bc2b36b
Compare
So there's good news and bad news. 👍 The good news is that everyone that needs to sign a CLA (the pull request submitter and all commit authors) have done so. Everything is all good there. 😕 The bad news is that it appears that one or more commits were authored or co-authored by someone other than the pull request submitter. We need to confirm that all authors are ok with their commits being contributed to this project. Please have them confirm that here in the pull request. Note to project maintainer: This is a terminal state, meaning the ℹ️ Googlers: Go here for more info. |
Codecov Report
@@ Coverage Diff @@
## feat/mdcweb-typescript-update #762 +/- ##
=================================================================
- Coverage 94.33% 94.27% -0.06%
=================================================================
Files 73 73
Lines 2963 2968 +5
Branches 459 457 -2
=================================================================
+ Hits 2795 2798 +3
Misses 60 60
- Partials 108 110 +2
Continue to review full report at Codecov.
|
closing for #774 |
reopening from #751
related #697