-
Notifications
You must be signed in to change notification settings - Fork 2.9k
[ContextualMenu] Fixes useTargetWidth property #3943
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
Changes from 3 commits
50528e0
1e6a98c
442c9c0
f3cdb18
d667782
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| { | ||
| "changes": [ | ||
| { | ||
| "packageName": "office-ui-fabric-react", | ||
| "comment": "Fixes useTargetWidth prop for ContextualMenu", | ||
| "type": "patch" | ||
| } | ||
| ], | ||
| "packageName": "office-ui-fabric-react", | ||
| "email": "joem@microsoft.com" | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,7 @@ export interface IContextualMenuState { | |
| slideDirectionalClassName?: string; | ||
| subMenuId?: string; | ||
| submenuDirection?: DirectionalHint; | ||
| targetWidth?: number; | ||
| } | ||
|
|
||
| export function hasSubmenu(item: IContextualMenuItem) { | ||
|
|
@@ -153,13 +154,15 @@ export class ContextualMenu extends BaseComponent<IContextualMenuProps, IContext | |
| if (newProps.target !== this.props.target) { | ||
| let newTarget = newProps.target; | ||
| this._setTargetWindowAndElement(newTarget!); | ||
| this._setTargetWidthAsync(); | ||
| } | ||
| } | ||
|
|
||
| // Invoked once, both on the client and server, immediately before the initial rendering occurs. | ||
| public componentWillMount() { | ||
| let target = this.props.target; | ||
| this._setTargetWindowAndElement(target!); | ||
| this._setTargetWidthAsync(); | ||
| this._previousActiveElement = this._targetWindow ? this._targetWindow.document.activeElement as HTMLElement : null; | ||
| } | ||
|
|
||
|
|
@@ -246,15 +249,14 @@ export class ContextualMenu extends BaseComponent<IContextualMenuProps, IContext | |
| */ | ||
| let contextMenuStyle; | ||
| let targetAsHtmlElement = this._target as HTMLElement; | ||
| if ((useTargetWidth || useTargetAsMinWidth) && targetAsHtmlElement && targetAsHtmlElement.offsetWidth) { | ||
| let targetWidth = targetAsHtmlElement.offsetWidth; | ||
| if ((useTargetWidth || useTargetAsMinWidth) && targetAsHtmlElement) { | ||
| if (useTargetWidth) { | ||
| contextMenuStyle = { | ||
| width: targetWidth | ||
| width: this.state.targetWidth | ||
| }; | ||
| } else if (useTargetAsMinWidth) { | ||
| contextMenuStyle = { | ||
| minWidth: targetWidth | ||
| minWidth: this.state.targetWidth | ||
| }; | ||
| } | ||
| } | ||
|
|
@@ -271,7 +273,7 @@ export class ContextualMenu extends BaseComponent<IContextualMenuProps, IContext | |
| } | ||
| return ( | ||
| <Callout | ||
| {...calloutProps} | ||
| { ...calloutProps } | ||
| target={ useTargetPoint ? targetPoint : target } | ||
| isBeakVisible={ isBeakVisible } | ||
| beakWidth={ beakWidth } | ||
|
|
@@ -330,6 +332,23 @@ export class ContextualMenu extends BaseComponent<IContextualMenuProps, IContext | |
| } | ||
| } | ||
|
|
||
| private _setTargetWidthAsync() { | ||
| const targetAsHtmlElement = this._target as HTMLElement; | ||
|
|
||
| // If component doesn't care about target's width, then this is a no-op. | ||
| if ((!this.props.useTargetWidth && !this.props.useTargetAsMinWidth) || !targetAsHtmlElement) { | ||
| return; | ||
| } | ||
|
|
||
| this._async.requestAnimationFrame(() => { | ||
| const targetBoundingRect = targetAsHtmlElement.getBoundingClientRect(); | ||
|
|
||
| this.setState({ | ||
| targetWidth: targetBoundingRect.width - 2 /* Need to account for border width */ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Since this async, how do we make sure this value is set when the render API is called?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It gets called in
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or if you have a better way to solve it, feel free to take it over. The issue has been open since November with no activity and we need a fix. Thanks!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's okay if the value is not set at first render, although it may cause apparent resizing. You would need to provide a default value though. |
||
| }); | ||
| }); | ||
| } | ||
|
|
||
| private _onRenderSubMenu(subMenuProps: IContextualMenuProps) { | ||
| return <ContextualMenu { ...subMenuProps } />; | ||
| } | ||
|
|
||
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.
@joschect Here's the attempt at asynchronously getting the target's width. Let me know what you think.