-
Notifications
You must be signed in to change notification settings - Fork 3.4k
update(panel): constrain panel to viewport boundries #9651
Conversation
2505bd8
to
1284aa9
Compare
* Margin between the edges of the panel and the viewport | ||
* @type {number} | ||
*/ | ||
this.viewportMargin = MdPanelPosition.viewportMargin; |
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 don't think this one needs to be re-exported via $mdPanel
, since there are no values for people to access or change.
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.
The main reason was to expose it to the unit tests. It can also be a global variable there that can be easily changed if tests start failing because of the wrong margin.
@@ -1767,6 +1773,12 @@ MdPanelPosition.absPosition = { | |||
LEFT: 'left' | |||
}; | |||
|
|||
/** | |||
* Margin between the edges of a panel and the viewport. | |||
* @type {number} |
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 this use @const
?
* Margin between the edges of a panel and the viewport. | ||
* @type {number} | ||
*/ | ||
MdPanelPosition.viewportMargin = 5; |
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.
5 -> 8 (everything in Material design is based on 8s.)
https://material.google.com/layout/responsive-ui.html#responsive-ui-grid
1284aa9
to
d80b0b8
Compare
Included the feedback from Erin. |
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
Prevents the panel from going outside the viewport by adjusting the position. If developers want more control over how the panel gets repositioned, they can specify addition fallback positions via `addPanelPosition`. Related to angular#9641. Fixes angular#7878.
d80b0b8
to
fa5c22e
Compare
@ThomasBurleson this should be ready for presubmit. |
} | ||
} | ||
|
||
if (this.getLeft()) { |
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 one case when the panel width is 100% in which there is no right side margin. Should the intent of this issue cover that scenario as well? Or is that something to handle as a separate issue or by the user of the md-panel? I am able to adjust using "withXPosition('align-left')"... but I am just wondering if you think this should be performed by the constrainToViewport method.
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 question. IMO the constrainToViewport
method is a last-ditch effort to keep the panel in the viewport and it may not be successful (e.g. the element is wider than the viewport). Before mdPanel
resorts to it, it tries all of the available positions to see which one stays in the viewport. If you want a bit more control, you can add extra positions via addPanelPosition
and it'll try those first. Here's an example:
$mdPanel.newPanelPosition()
.relativeTo('something')
.addPanelPosition(this._mdPanel.xPosition.ALIGN_START, this._mdPanel.yPosition.BELOW)
.addPanelPosition(this._mdPanel.xPosition.ALIGN_END, this._mdPanel.yPosition.BELOW)
.addPanelPosition(this._mdPanel.xPosition.ALIGN_START, this._mdPanel.yPosition.ABOVE);
This will try to position it start/below, end/below, start/above before resorting to constraining it.
Also I think you asked yesterday about the "position adjusted" class. This is useful in the cases where the panel was constrained, because it allows you to do some specific styling (e.g. we use it in the datepicker to hide a part of the overlay).
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 do use multiple positions. The panel does not really go off the screen, but it touches the right edge of the viewport with no margin (so I set a negative offsetX). Thinking about it more, that could probably be handled by css instead. Thank you for this change. I am already trying out your changes.
I noticed earlier that the md-panel position is not updated when disableParentScroll is set to true (and as a result the panel falls outside the viewport boundaries). In my case the md-panel is at the bottom of the screen and this results in part of the panel being offscreen. The panel is positioned correctly within the viewport when disableParentScroll is set to false. Looking at the code, I can see this was a pre-existing behavior. I haven't finished debugging but the issue may have to do with the positionUpdate performed when the onScroll event handler is added in line 1783 ( this._$window.addEventListener('scroll', onScroll, true) ). Should re-positioning work when the parent scroll is disabled? Should I open a separate issue to handle this? |
I'm not sure about it, but it would be great if you made an issue so it's easier to track and discuss. It does sound strange though. |
Ok, I will create a small test to replicate and create a new issue later in the week. Thank you. |
MdPanelPosition.prototype._constrainToViewport = function(panelEl) { | ||
var margin = MdPanelPosition.viewportMargin; | ||
|
||
if (this.getTop()) { |
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.
The md-datepicker code has a comment regarding "disabled body scrolling" which I think is applicable here as well. I need to understand the code more, but I think this may be a gap in the constrainToViewport implementation.
Comment from: https://github.com/angular/material/pull/9641/files#diff-31bf126782bc06608d149fe72237bf4eL640
If ng-material has disabled body scrolling (for example, if a dialog is open),
then it's possible that the already-scrolled body has a negative top/left. In this case,
we want to treat the "real" top as (0 - bodyRect.top). In a normal scrolling situation,
though, the top of the viewport should just be the body's scroll position.
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 doubt it, because the panel is always positioned relatively to the viewport (position: fixed
). The current datepicker implementation positions the calendar relatively to the body (via position: absolute
).
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, thank you.
I am no longer able to replicate the issue I mentioned earlier with disableParentScroll (I had a fresh checkout of the master branch and your branch only.). I am not sure why it failed earlier but it seems to be working now. Thank you again. |
Prevents the panel from going outside the viewport by adjusting the position.
If developers want more control over how the panel gets repositioned, they can specify addition fallback positions via
addPanelPosition
.Related to #9641.
Fixes #7878.