Skip to content

Commit

Permalink
feat(popover): m3 styles, new angle (corner) parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
nolimits4web committed Sep 29, 2022
1 parent 0dcdde9 commit b6ebbe3
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 149 deletions.
152 changes: 65 additions & 87 deletions src/core/components/popover/popover-class.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class Popover extends Modal {

// Find Angle
let $angleEl;
if ($el.find('.popover-angle').length === 0) {
if ($el.find('.popover-angle').length === 0 && popover.params.angle) {
$angleEl = $('<div class="popover-angle"></div>');
$el.prepend($angleEl);
} else {
Expand Down Expand Up @@ -191,16 +191,17 @@ class Popover extends Modal {
let angleSize = 0;
let angleLeft;
let angleTop;
if (app.theme === 'ios') {
const hasAngle = $angleEl.length > 0;
const angleMin = app.theme === 'ios' ? 13 : 24;
if (hasAngle) {
$angleEl.removeClass('on-left on-right on-top on-bottom').css({ left: '', top: '' });
angleSize = $angleEl.width() / 2;
} else {
$el
.removeClass(
'popover-on-left popover-on-right popover-on-top popover-on-bottom popover-on-middle',
)
.css({ left: '', top: '' });
}
$el
.removeClass(
'popover-on-left popover-on-right popover-on-top popover-on-bottom popover-on-middle',
)
.css({ left: '', top: '' });

let targetWidth;
let targetHeight;
Expand Down Expand Up @@ -234,102 +235,79 @@ class Popover extends Modal {
let [left, top, diff] = [0, 0, 0];
// Top Position
const forcedPosition = verticalPosition === 'auto' ? false : verticalPosition;
let position = forcedPosition || (app.theme === 'md' ? 'bottom' : 'top');
if (app.theme === 'md') {
if (
forcedPosition === 'bottom' ||
(!forcedPosition && height < app.height - targetOffsetTop - targetHeight)
) {
// On bottom
position = 'bottom';
top = targetOffsetTop + targetHeight;
} else if (
forcedPosition === 'top' ||
(!forcedPosition && height < targetOffsetTop - safeAreaTop)
) {
// On top
top = targetOffsetTop - height;
position = 'top';
} else {
// On middle
position = 'middle';
top = targetHeight / 2 + targetOffsetTop - height / 2;
}
top = Math.max(8, Math.min(top, app.height - height - 8));
let position = forcedPosition || 'top';

// Horizontal Position
let hPosition;
if (targetOffsetLeft < app.width / 2) {
hPosition = 'right';
left = position === 'middle' ? targetOffsetLeft + targetWidth : targetOffsetLeft;
} else {
hPosition = 'left';
left =
position === 'middle' ? targetOffsetLeft - width : targetOffsetLeft + targetWidth - width;
}
left = Math.max(8, Math.min(left, app.width - width - 8 - safeAreaRight), safeAreaLeft);
$el.addClass(`popover-on-${position} popover-on-${hPosition}`);
if (
forcedPosition === 'top' ||
(!forcedPosition && height + angleSize < targetOffsetTop - safeAreaTop)
) {
// On top
top = targetOffsetTop - height - angleSize;
} else if (
forcedPosition === 'bottom' ||
(!forcedPosition && height + angleSize < app.height - targetOffsetTop - targetHeight)
) {
// On bottom
position = 'bottom';
top = targetOffsetTop + targetHeight + angleSize;
} else {
// ios
if (
forcedPosition === 'top' ||
(!forcedPosition && height + angleSize < targetOffsetTop - safeAreaTop)
) {
// On top
top = targetOffsetTop - height - angleSize;
} else if (
forcedPosition === 'bottom' ||
(!forcedPosition && height + angleSize < app.height - targetOffsetTop - targetHeight)
) {
// On bottom
position = 'bottom';
top = targetOffsetTop + targetHeight + angleSize;
} else {
// On middle
position = 'middle';
top = targetHeight / 2 + targetOffsetTop - height / 2;
diff = top;
top = Math.max(5, Math.min(top, app.height - height - 5));
diff -= top;
// On middle
position = 'middle';
top = targetHeight / 2 + targetOffsetTop - height / 2;
diff = top;
top = Math.max(5, Math.min(top, app.height - height - 5));
diff -= top;
}

// Horizontal Position
if (position === 'top' || position === 'bottom') {
left = targetWidth / 2 + targetOffsetLeft - width / 2;
diff = left;
left = Math.max(5, Math.min(left, app.width - width - 5));
if (safeAreaLeft) {
left = Math.max(left, safeAreaLeft);
}
if (safeAreaRight && left + width > app.width - 5 - safeAreaRight) {
left = app.width - 5 - safeAreaRight - width;
}

// Horizontal Position
if (position === 'top' || position === 'bottom') {
left = targetWidth / 2 + targetOffsetLeft - width / 2;
diff = left;
left = Math.max(5, Math.min(left, app.width - width - 5));
if (safeAreaLeft) {
left = Math.max(left, safeAreaLeft);
}
if (safeAreaRight && left + width > app.width - 5 - safeAreaRight) {
left = app.width - 5 - safeAreaRight - width;
}
diff -= left;
if (hasAngle) {
if (position === 'top') {
$angleEl.addClass('on-bottom');
}
if (position === 'bottom') {
$angleEl.addClass('on-top');
}
diff -= left;
angleLeft = width / 2 - angleSize + diff;
angleLeft = Math.max(Math.min(angleLeft, width - angleSize * 2 - 13), 13);
angleLeft = Math.max(Math.min(angleLeft, width - angleSize * 2 - angleMin), angleMin);
$angleEl.css({ left: `${angleLeft}px` });
} else if (position === 'middle') {
left = targetOffsetLeft - width - angleSize;
$angleEl.addClass('on-right');
if (left < 5 || left + width + safeAreaRight > app.width || left < safeAreaLeft) {
if (left < 5) left = targetOffsetLeft + targetWidth + angleSize;
if (left + width + safeAreaRight > app.width)
left = app.width - width - 5 - safeAreaRight;
if (left < safeAreaLeft) left = safeAreaLeft;
$angleEl.removeClass('on-right').addClass('on-left');
}
}
} else if (position === 'middle') {
left = targetOffsetLeft - width - angleSize;
if (hasAngle) $angleEl.addClass('on-right');
if (left < 5 || left + width + safeAreaRight > app.width || left < safeAreaLeft) {
if (left < 5) left = targetOffsetLeft + targetWidth + angleSize;
if (left + width + safeAreaRight > app.width) left = app.width - width - 5 - safeAreaRight;
if (left < safeAreaLeft) left = safeAreaLeft;
if (hasAngle) $angleEl.removeClass('on-right').addClass('on-left');
}
if (hasAngle) {
angleTop = height / 2 - angleSize + diff;
angleTop = Math.max(Math.min(angleTop, height - angleSize * 2 - 13), 13);
angleTop = Math.max(Math.min(angleTop, height - angleSize * 2 - angleMin), angleMin);
$angleEl.css({ top: `${angleTop}px` });
}
}

// Horizontal Position
let hPosition;
if (targetOffsetLeft < app.width / 2) {
hPosition = 'right';
} else {
hPosition = 'left';
}
$el.addClass(`popover-on-${position} popover-on-${hPosition}`);

// Apply Styles
$el.css({ top: `${top}px`, left: `${left}px` });
}
Expand Down
50 changes: 0 additions & 50 deletions src/core/components/popover/popover-ios.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,54 +3,4 @@
transform: none;
transition-property: opacity;
}
.popover-angle {
width: 26px;
height: 26px;
position: absolute;
left: -26px;
top: 0;
z-index: 100;
overflow: hidden;
&:after {
content: '';
background: var(--f7-popover-bg-color);
width: 26px;
height: 26px;
position: absolute;
left: 0;
top: 0;
border-radius: 3px;
transform: rotate(45deg);
}
&.on-left {
left: -26px;
&:after {
left: 19px;
top: 0;
}
}
&.on-right {
left: 100%;
&:after {
left: -19px;
top: 0;
}
}
&.on-top {
left: 0;
top: -26px;
&:after {
left: 0;
top: 19px;
}
}
&.on-bottom {
left: 0;
top: 100%;
&:after {
left: 0;
top: -19px;
}
}
}
}
16 changes: 5 additions & 11 deletions src/core/components/popover/popover-vars.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
}
.ios-vars({
--f7-popover-border-radius: 13px;
--f7-popover-box-shadow: none;
--f7-popover-actions-icon-size: 28px;
--f7-popover-transition-timing-function: initial;
.light-vars({
--f7-popover-bg-color: rgba(255,255,255,0.95);
--f7-popover-actions-label-text-color: rgba(0,0,0,0.45);
Expand All @@ -15,15 +15,9 @@
});
});
.md-vars({
--f7-popover-border-radius: 4px;
--f7-popover-box-shadow: var(--f7-elevation-8);
--f7-popover-transition-timing-function: cubic-bezier(0, 0.8, 0.34, 1);
--f7-popover-border-radius: 28px;
--f7-popover-actions-icon-size: 24px;
.light-vars({
--f7-popover-bg-color: #fff;
--f7-popover-actions-label-text-color: rgba(0,0,0,0.54);
});
.dark-vars({
--f7-popover-bg-color: #1c1c1d;
--f7-popover-actions-label-text-color: rgba(255,255,255,0.54);
});
--f7-popover-bg-color: var(--f7-md-surface-3);
--f7-popover-actions-label-text-color: var(--f7-md-on-surface-variant);
});
2 changes: 2 additions & 0 deletions src/core/components/popover/popover.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ export namespace Popover {
el?: HTMLElement | CSSSelector;
/** Full Popover HTML layout string. Can be useful if you want to create Popover element dynamically. */
content?: string;
/** Enables Popover angle/corner. (default true) */
angle?: boolean;
/** Enables Popover backdrop (dark semi transparent layer behind). (default true) */
backdrop?: boolean;
/** Backdrop element to share across instances */
Expand Down
1 change: 1 addition & 0 deletions src/core/components/popover/popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export default {
params: {
popover: {
verticalPosition: 'auto',
angle: true,
backdrop: true,
backdropEl: undefined,
backdropUnique: false,
Expand Down
56 changes: 55 additions & 1 deletion src/core/components/popover/popover.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
z-index: 13500;
}
}

.popover {
width: var(--f7-popover-width);
z-index: 13500;
Expand All @@ -17,7 +18,6 @@
transition-duration: 300ms;
background-color: var(--f7-popover-bg-color);
border-radius: var(--f7-popover-border-radius);
box-shadow: var(--f7-popover-box-shadow);
will-change: transform, opacity;
.list {
margin: 0;
Expand Down Expand Up @@ -69,6 +69,10 @@
transition-duration: 0ms;
}
}
.popover,
.popover-backdrop {
transition-timing-function: var(--f7-popover-transition-timing-function);
}
.popover-inner {
.scrollable();
}
Expand Down Expand Up @@ -96,6 +100,56 @@
.hairline-remove(bottom);
}
}
.popover-angle {
width: 26px;
height: 26px;
position: absolute;
left: -26px;
top: 0;
z-index: 100;
overflow: hidden;
&:after {
content: '';
background: var(--f7-popover-bg-color);
width: 26px;
height: 26px;
position: absolute;
left: 0;
top: 0;
border-radius: 3px;
transform: rotate(45deg);
}
&.on-left {
left: -26px;
&:after {
left: 19px;
top: 0;
}
}
&.on-right {
left: 100%;
&:after {
left: -19px;
top: 0;
}
}
&.on-top {
left: 0;
top: -26px;
&:after {
left: 0;
top: 19px;
}
}
&.on-bottom {
left: 0;
top: 100%;
&:after {
left: 0;
top: -19px;
}
}
}
.if-ios-theme({
@import './popover-ios.less';
});
Expand Down
Loading

0 comments on commit b6ebbe3

Please sign in to comment.