Skip to content
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

Show the backdrop while displaying the popover as mobile tray #5299

Merged
merged 4 commits into from
Jan 10, 2025
Merged
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
74 changes: 62 additions & 12 deletions components/popover/popover-mixin.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '../backdrop/backdrop.js';
import '../colors/colors.js';
import '../focus-trap/focus-trap.js';
import { clearDismissible, setDismissible } from '../../helpers/dismissible.js';
Expand All @@ -6,6 +7,7 @@ import { getComposedActiveElement, getFirstFocusableDescendant, getPreviousFocus
import { getComposedParent, isComposedAncestor } from '../../helpers/dom.js';
import { _offscreenStyleDeclarations } from '../offscreen/offscreen.js';
import { styleMap } from 'lit/directives/style-map.js';
import { tryGetIfrauBackdropService } from '../../helpers/ifrauBackdropService.js';

const defaultPreferredPosition = {
location: 'block-end', // block-start, block-end
Expand Down Expand Up @@ -46,6 +48,7 @@ export const PopoverMixin = superclass => class extends superclass {
_position: { state: true },
_preferredPosition: { state: true },
_rtl: { state: true },
_showBackdrop: { state: true },
_trapFocus: { state: true },
_useNativePopover: { type: String, reflect: true, attribute: 'popover' },
_width: { state: true }
Expand Down Expand Up @@ -207,6 +210,7 @@ export const PopoverMixin = superclass => class extends superclass {
super();
this.configure();
this._mobile = false;
this._showBackdrop = false;
this._useNativePopover = isSupported ? 'manual' : undefined;
this.#handleAncestorMutationBound = this.#handleAncestorMutation.bind(this);
this.#handleAutoCloseClickBound = this.#handleAutoCloseClick.bind(this);
Expand Down Expand Up @@ -236,15 +240,23 @@ export const PopoverMixin = superclass => class extends superclass {
async close() {
if (!this._opened) return;

this._opened = false;
const ifrauBackdropService = await tryGetIfrauBackdropService();

this._opened = false;
if (this._useNativePopover) this.hidePopover();

this._previousFocusableAncestor = null;
this.#removeAutoCloseHandlers();
this.#removeMediaQueryHandlers();
this.#removeRepositionHandlers();
this.#clearDismissible();

if (ifrauBackdropService && this._showBackdrop) {
ifrauBackdropService.hideBackdrop();
this.#ifrauContextInfo = null;
}
this._showBackdrop = false;

await this.updateComplete; // wait before applying focus to opener
this.#focusOpener();
this.dispatchEvent(new CustomEvent('d2l-popover-close', { bubbles: true, composed: true }));
Expand Down Expand Up @@ -281,6 +293,8 @@ export const PopoverMixin = superclass => class extends superclass {
async open(applyFocus = true) {
if (this._opened) return;

const ifrauBackdropService = await tryGetIfrauBackdropService();

this.#addMediaQueryHandlers();

this._rtl = document.documentElement.getAttribute('dir') === 'rtl';
Expand All @@ -297,6 +311,11 @@ export const PopoverMixin = superclass => class extends superclass {

await this.#position();

this._showBackdrop = this._mobile && this._mobileTrayLocation;
if (ifrauBackdropService && this._showBackdrop) {
this.#ifrauContextInfo = await ifrauBackdropService.showBackdrop();
}

this._dismissibleId = setDismissible(() => this.close());

this.#focusContent(this);
Expand All @@ -323,7 +342,7 @@ export const PopoverMixin = superclass => class extends superclass {
const contentStyle = stylesMap['content'];

content = html`
<div class="content-width vdiff-target" style=${styleMap(widthStyle)}>
<div id="content-wrapper" class="content-width vdiff-target" style=${styleMap(widthStyle)}>
<div class="content-container" style=${styleMap(contentStyle)}>${content}</div>
</div>
`;
Expand Down Expand Up @@ -362,12 +381,17 @@ export const PopoverMixin = superclass => class extends superclass {
</div>
` : nothing;

return html`${content}${pointer}`;
return this._mobileTrayLocation ? html`
${content}
<d2l-backdrop for-target="content-wrapper" ?shown="${this._showBackdrop}"></d2l-backdrop>
${pointer}
` : html`${content}${pointer}`;
dbatiste marked this conversation as resolved.
Show resolved Hide resolved

}

async resize() {
if (!this._opened) return;
this._showBackdrop = this._mobile && this._mobileTrayLocation;
await this.#position();
}

Expand All @@ -376,6 +400,7 @@ export const PopoverMixin = superclass => class extends superclass {
else return this.open(!this._noAutoFocus && applyFocus);
}

#ifrauContextInfo;
#mediaQueryList;
#handleAncestorMutationBound;
#handleAutoCloseClickBound;
Expand Down Expand Up @@ -520,7 +545,8 @@ export const PopoverMixin = superclass => class extends superclass {
#getMobileTrayBlockStyleMaps() {

let maxHeightOverride;
const availableHeight = Math.min(window.innerHeight, window.screen.height);
let availableHeight = Math.min(window.innerHeight, window.screen.height);
if (this.#ifrauContextInfo) availableHeight = this.#ifrauContextInfo.availableHeight;

// default maximum height for bottom tray (42px margin)
const mobileTrayMaxHeightDefault = availableHeight - minBackdropHeightMobile;
Expand All @@ -532,12 +558,20 @@ export const PopoverMixin = superclass => class extends superclass {
}
maxHeightOverride = `${maxHeightOverride}px`;

let bottomOverride;
if (this.#ifrauContextInfo) {
// the bottom override is measured as the distance from the bottom of the screen
const screenHeight = window.innerHeight - this.#ifrauContextInfo.availableHeight + Math.min(this.#ifrauContextInfo.top, 0);
bottomOverride = `${screenHeight}px`;
}

const widthOverride = '100vw';

const widthStyle = {
minWidth: widthOverride,
width: widthOverride,
maxHeight: maxHeightOverride,
bottom: bottomOverride
};

const contentWidthStyle = {
Expand All @@ -552,14 +586,15 @@ export const PopoverMixin = superclass => class extends superclass {

return {
width: widthStyle,
content: contentStyle,
content: contentStyle
};
}

#getMobileTrayInlineStyleMaps() {

let maxWidthOverride = this._maxWidth;
const availableWidth = Math.min(window.innerWidth, window.screen.width);
let availableWidth = Math.min(window.innerWidth, window.screen.width);
if (this.#ifrauContextInfo) availableWidth = this.#ifrauContextInfo.availableWidth;

// default maximum width for tray (30px margin)
const mobileTrayMaxWidthDefault = Math.min(availableWidth - minBackdropWidthMobile, 420);
Expand Down Expand Up @@ -592,7 +627,17 @@ export const PopoverMixin = superclass => class extends superclass {
// add 2 to content width since scrollWidth does not include border
const containerWidth = `${widthOverride + 20}px`;

const topOverride = (window.innerHeight > window.screen.height) ? window.pageYOffset : undefined;
let maxHeightOverride = '';
if (this.#ifrauContextInfo) maxHeightOverride = `${this.#ifrauContextInfo.availableHeight}px`;
dbatiste marked this conversation as resolved.
Show resolved Hide resolved

let topOverride;
if (this.#ifrauContextInfo) {
// if inside iframe, use ifrauContext top as top of screen
topOverride = `${this.#ifrauContextInfo.top < 0 ? -this.#ifrauContextInfo.top : 0}px`;
} else if (window.innerHeight > window.screen.height) {
// non-responsive page, manually override top to scroll distance
topOverride = window.pageYOffset;
}

let inlineEndOverride;
let inlineStartOverride;
Expand All @@ -614,6 +659,7 @@ export const PopoverMixin = superclass => class extends superclass {
minWidth: minWidthOverride,
width: containerWidth,
top: topOverride,
maxHeight: maxHeightOverride,
insetInlineStart: inlineStartOverride,
insetInlineEnd: inlineEndOverride
};
Expand All @@ -626,11 +672,12 @@ export const PopoverMixin = superclass => class extends superclass {

const contentStyle = {
...contentWidthStyle,
maxHeight: maxHeightOverride,
};

return {
width : widthStyle,
content : contentStyle,
width: widthStyle,
content: contentStyle
};
}

Expand Down Expand Up @@ -767,8 +814,8 @@ export const PopoverMixin = superclass => class extends superclass {
};

return {
width : widthStyle,
content : contentStyle
width: widthStyle,
content: contentStyle
};
}

Expand Down Expand Up @@ -824,7 +871,10 @@ export const PopoverMixin = superclass => class extends superclass {

async #handleMobileResize() {
this._mobile = this.#mediaQueryList.matches;
if (this._opened) await this.#position();
if (this._opened) {
this._showBackdrop = this._mobile && this._mobileTrayLocation;
await this.#position();
}
}

#handleResize() {
Expand Down
Loading