Skip to content

Commit

Permalink
feat(overlay): only hide descendant overlays automatically
Browse files Browse the repository at this point in the history
  • Loading branch information
DRiFTy17 committed Jan 9, 2024
1 parent 59e8476 commit 1d0d9d5
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 16 deletions.
40 changes: 26 additions & 14 deletions src/lib/overlay/overlay-adapter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { autoUpdate, Boundary } from '@floating-ui/dom';
import { getShadowElement } from '@tylertech/forge-core';
import { BaseAdapter, IBaseAdapter } from '../core/base/base-adapter';
import { DismissibleStack } from '../core/utils/dismissible-stack';
import { positionElementAsync, PositionPlacement, VirtualElement } from '../core/utils/position-utils';
import { locateElementById } from '../core/utils/utils';
import { IOverlayComponent, OverlayComponent } from './overlay';
Expand All @@ -19,7 +18,7 @@ import {
export interface IOverlayAdapter extends IBaseAdapter {
show(): void;
hide(): void;
tryHideOpenOverlays(): void;
tryHideDescendantOverlays(): void;
locateAnchorElement(id: string | null): HTMLElement | null;
isMostRecentOpenOverlay(): boolean;
positionElement(config: IPositionElementConfig): void;
Expand Down Expand Up @@ -61,12 +60,7 @@ export class OverlayAdapter extends BaseAdapter<IOverlayComponent> implements IO
this._rootElement.removeAttribute('popover');
}

// Wait for any other overlays to finish dismissing before adding ourselves to the stack
await DismissibleStack.instance.dismissing;

if (this._component.isConnected && this._component.open) {
OverlayComponent[overlayStack].add(this._component);
}
OverlayComponent[overlayStack].add(this._component);
}

public hide(): void {
Expand All @@ -89,12 +83,10 @@ export class OverlayAdapter extends BaseAdapter<IOverlayComponent> implements IO
OverlayComponent[overlayStack].delete(this._component);
}

public tryHideOpenOverlays(): void {
// Attempts to hide any overlays that were opened after this one in reverse order
const overlays = Array.from(OverlayComponent[overlayStack]);
const overlaysAfter = overlays.slice(overlays.indexOf(this._component) + 1).reverse();
overlaysAfter
.filter(o => !o.persistent) // Ignore persistent overlays
public tryHideDescendantOverlays(): void {
const descendantOverlays = this._findDescendantOverlays();
descendantOverlays
.filter(o => !o.persistent) // Ignore persistent overlays since those are manually controlled
.forEach(o => o.open = false);
}

Expand Down Expand Up @@ -236,4 +228,24 @@ export class OverlayAdapter extends BaseAdapter<IOverlayComponent> implements IO
this._lightDismissController.abort();
this._lightDismissController = new AbortController();
}

/**
* Finds all descendant overlays that are not persistent.
* @returns An array of descendant overlays.
*/
private _findDescendantOverlays(): IOverlayComponent[] {
const allOverlays = Array.from(OverlayComponent[overlayStack]);
const overlaysAboveUs = allOverlays.slice(allOverlays.indexOf(this._component) + 1).reverse();
const descendantOverlays: IOverlayComponent[] = [];

if (overlaysAboveUs.length) {
// Dispatch an event on each overlay after us to see if it is a descendant of our overlay
const listener: EventListener = evt => descendantOverlays.push(evt.target as IOverlayComponent);
this._component.addEventListener(OVERLAY_CONSTANTS.events.DESCENDANT_TEST, listener);
overlaysAboveUs.forEach(o => o.dispatchEvent(new CustomEvent(OVERLAY_CONSTANTS.events.DESCENDANT_TEST, { bubbles: true, composed: true })));
this._component.removeEventListener(OVERLAY_CONSTANTS.events.DESCENDANT_TEST, listener);
}

return descendantOverlays;
}
}
3 changes: 2 additions & 1 deletion src/lib/overlay/overlay-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ const selectors = {
} as const;

const events = {
LIGHT_DISMISS: `${elementName}-light-dismiss`
LIGHT_DISMISS: `${elementName}-light-dismiss`,
DESCENDANT_TEST: `${elementName}-descendant-test`
} as const;

const defaults = {
Expand Down
2 changes: 1 addition & 1 deletion src/lib/overlay/overlay-foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export class OverlayFoundation extends BaseOverlayFoundation<IOverlayAdapter> im
}

private _hideOverlay(): void {
this._adapter.tryHideOpenOverlays();
this._adapter.tryHideDescendantOverlays();
this._adapter.hide();
this._adapter.removeLightDismissListener();
}
Expand Down

0 comments on commit 1d0d9d5

Please sign in to comment.