Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Expand Up @@ -247,7 +247,9 @@ export class ContextualMenu extends BaseComponent<IContextualMenuProps, IContext
let contextMenuStyle;
let targetAsHtmlElement = this._target as HTMLElement;
if ((useTargetWidth || useTargetAsMinWidth) && targetAsHtmlElement && targetAsHtmlElement.offsetWidth) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you're checking offsetWidth, but calling getBoundingClientRect, while it's probably fine we should still change it to be consistent.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

What's the appropriate check here then? I would've thought checking offsetWidth initially was unnecessary anyway.

let targetWidth = targetAsHtmlElement.offsetWidth;
const targetBoundingRect = targetAsHtmlElement.getBoundingClientRect();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should never have been in the render function in the first place. Calling offsetWidth/getBoundingClientRect (and other stuff) can trigger a reflow which is bad for performance. Ideally we'll store this and not call it again, and when we do call it it should be async. Move all of this to a separate function that get's called asynchronously.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Any guidance on this? There doesn't seem to be any async/await patterns that exist in OUFR.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'm not sure how to include an async function in the render function. Should the calculation be done in life-cycle method?

@joschect joschect Feb 12, 2018

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Take a look at _updateAsyncPosition() in callout. It uses requestAnimationFrame which essentially bundles the measures/renders separately, so instead of there being dom changes then measuring then dom changes again and then re-measuring (and so on), it tells the browser to complete dom changes, then measures after reflows are complete.

Really contextualmenu shouldn't be measuring anything. But yes, it should be part of the lifecycle.

const targetWidth = targetBoundingRect.width;

if (useTargetWidth) {
contextMenuStyle = {
width: targetWidth
Expand All @@ -271,7 +273,7 @@ export class ContextualMenu extends BaseComponent<IContextualMenuProps, IContext
}
return (
<Callout
{...calloutProps}
{ ...calloutProps }
target={ useTargetPoint ? targetPoint : target }
isBeakVisible={ isBeakVisible }
beakWidth={ beakWidth }
Expand Down