bug: always rendered floating groups z-index

This commit is contained in:
mathuo 2024-08-06 21:33:20 +01:00
parent 6bf0263797
commit 1efa5c0ef6
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
7 changed files with 115 additions and 52 deletions

View File

@ -29,10 +29,6 @@
position: absolute;
z-index: 997;
&.dv-bring-to-front {
z-index: 999;
}
border: 1px solid var(--dv-tab-divider-color);
box-shadow: var(--dv-floating-box-shadow);

View File

@ -1,7 +1,5 @@
import {
applyOnlyToThisElement,
disableIframePointEvents,
getElementsByTagName,
quasiDefaultPrevented,
toggleClass,
} from '../dom';
@ -15,7 +13,36 @@ import { CompositeDisposable, MutableDisposable } from '../lifecycle';
import { clamp } from '../math';
import { AnchoredBox } from '../types';
const bringElementToFront = applyOnlyToThisElement('dv-bring-to-front');
export const DEFAULT_OVERLAY_Z_INDEX = 999;
class AriaLevelTracker {
private _orderedList: HTMLElement[] = [];
push(element: HTMLElement): void {
this._orderedList = [
...this._orderedList.filter((item) => item !== element),
element,
];
this.update();
}
destroy(element: HTMLElement): void {
this._orderedList = this._orderedList.filter(
(item) => item !== element
);
this.update();
}
private update(): void {
for (let i = 0; i < this._orderedList.length; i++) {
this._orderedList[i].setAttribute('aria-level', `${i}`);
this._orderedList[i].style.zIndex = `${DEFAULT_OVERLAY_Z_INDEX + i * 2}`;
}
}
}
const arialLevelTracker = new AriaLevelTracker();
export class Overlay extends CompositeDisposable {
private _element: HTMLElement = document.createElement('div');
@ -40,6 +67,10 @@ export class Overlay extends CompositeDisposable {
this.options.minimumInViewportHeight = value;
}
get element(): HTMLElement {
return this._element;
}
constructor(
private readonly options: AnchoredBox & {
container: HTMLElement;
@ -75,10 +106,12 @@ export class Overlay extends CompositeDisposable {
...('left' in this.options && { left: this.options.left }),
...('right' in this.options && { right: this.options.right }),
});
arialLevelTracker.push(this._element);
}
bringToFront(): void {
bringElementToFront.update(this._element);
arialLevelTracker.push(this._element);
}
setBounds(bounds: Partial<AnchoredBox> = {}): void {
@ -346,14 +379,12 @@ export class Overlay extends CompositeDisposable {
this.options.content,
'mousedown',
() => {
bringElementToFront.update(this._element);
arialLevelTracker.push(this._element);
},
true
)
);
bringElementToFront.update(this._element);
if (options.inDragMode) {
track();
}
@ -586,6 +617,7 @@ export class Overlay extends CompositeDisposable {
}
override dispose(): void {
arialLevelTracker.destroy(this._element);
this._element.remove();
super.dispose();
}

View File

@ -357,6 +357,10 @@ export class DockviewComponent
return this.gridview.margin;
}
get floatingGroups(): DockviewFloatingGroupPanel[] {
return this._floatingGroups;
}
constructor(parentElement: HTMLElement, options: DockviewComponentOptions) {
super({
proportionalLayout: true,
@ -371,11 +375,14 @@ export class DockviewComponent
className: options.className,
});
const gready = document.createElement('div');
gready.className = 'dv-overlay-render-container';
this.gridview.element.appendChild(gready);
// const gready = document.createElement('div');
// gready.className = 'dv-overlay-render-container';
// this.gridview.element.appendChild(gready);
this.overlayRenderContainer = new OverlayRenderContainer(gready);
this.overlayRenderContainer = new OverlayRenderContainer(
this.gridview.element,
this
);
toggleClass(this.gridview.element, 'dv-dockview', true);
toggleClass(this.element, 'dv-debug', !!options.debug);
@ -639,7 +646,8 @@ export class DockviewComponent
gready.className = 'dv-overlay-render-container';
const overlayRenderContainer = new OverlayRenderContainer(
gready
gready,
this
);
const referenceGroup =

View File

@ -964,7 +964,7 @@ export class DockviewGroupPanelModel
});
this.watermark = watermark;
addDisposableListener(this.watermark.element, 'click', () => {
addDisposableListener(this.watermark.element, 'pointerdown', () => {
if (!this.isActive) {
this.accessor.doSetGroupActive(this.groupPanel);
}

View File

@ -278,21 +278,3 @@ export function disableIframePointEvents() {
},
};
}
export function applyOnlyToThisElement(className: string): {
update: (element: HTMLElement) => void;
} {
let previous: WeakRef<HTMLElement> | null;
return {
update: (element: HTMLElement): void => {
const ref = previous?.deref();
if (ref !== element && ref !== undefined) {
toggleClass(ref, className, false);
}
toggleClass(element, className, true);
previous = new WeakRef(element);
},
};
}

View File

@ -7,7 +7,7 @@
z-index: 998;
&.dv-render-overlay-active {
z-index: 1000;
// z-index: 1000;
}
}
}

View File

@ -1,12 +1,15 @@
import { DragAndDropObserver } from './dnd/dnd';
import { Droptarget } from './dnd/droptarget';
import { getDomNodePagePosition, toggleClass } from './dom';
import {
applyOnlyToThisElement,
getDomNodePagePosition,
toggleClass,
} from './dom';
import { CompositeDisposable, Disposable, IDisposable } from './lifecycle';
CompositeDisposable,
Disposable,
IDisposable,
MutableDisposable,
} from './lifecycle';
import { IDockviewPanel } from './dockview/dockviewPanel';
import { DockviewComponent } from './dockview/dockviewComponent';
import { DEFAULT_OVERLAY_Z_INDEX } from './dnd/overlay';
export type DockviewPanelRenderer = 'onlyWhenVisible' | 'always';
@ -21,8 +24,6 @@ function createFocusableElement(): HTMLDivElement {
return element;
}
const bringElementToFront = applyOnlyToThisElement('dv-active');
export class OverlayRenderContainer extends CompositeDisposable {
private readonly map: Record<
string,
@ -36,7 +37,10 @@ export class OverlayRenderContainer extends CompositeDisposable {
private _disposed = false;
constructor(private readonly element: HTMLElement) {
constructor(
readonly element: HTMLElement,
readonly accessor: DockviewComponent
) {
super();
this.addDisposables(
@ -114,7 +118,10 @@ export class OverlayRenderContainer extends CompositeDisposable {
focusContainer.style.display = panel.api.isVisible ? '' : 'none';
};
const observerDisposable = new MutableDisposable();
const disposable = new CompositeDisposable(
observerDisposable,
/**
* since container is positioned absoutely we must explicitly forward
* the dnd events for the expect behaviours to continue to occur in terms of dnd
@ -155,14 +162,52 @@ export class OverlayRenderContainer extends CompositeDisposable {
resize();
}),
panel.api.onDidActiveGroupChange(() => {
// toggleClass(
// focusContainer,
// 'dv-active',
// panel.api.isGroupActive
// );
if (panel.api.isGroupActive) {
bringElementToFront.update(focusContainer);
panel.api.onDidLocationChange((event) => {
const isFloating = event.location.type === 'floating';
/**
* Whilst floating the z-index must sync with the floating
* groups z-index
*/
if (isFloating) {
queueMicrotask(() => {
const floatingGroup = this.accessor.floatingGroups.find(
(group) => group.group === panel.api.group
);
if (!floatingGroup) {
return;
}
const element = floatingGroup.overlay.element;
const update = () => {
const level = Number(
element.getAttribute('aria-level')
);
focusContainer.style.zIndex = `${
DEFAULT_OVERLAY_Z_INDEX + level * 2 + 1
}`;
};
const observer = new MutationObserver(() => {
update();
});
observerDisposable.value = Disposable.from(() =>
observer.disconnect()
);
observer.observe(element, {
attributeFilter: ['aria-level'],
attributes: true,
});
update();
});
} else {
focusContainer.style.zIndex = ''; // reset the z-index, perhaps CSS will take over here
}
})
);