mirror of
https://github.com/mathuo/dockview
synced 2025-02-09 01:45:45 +00:00
Merge pull request #683 from mathuo/656-renderer-always-causes-floating-group-z-index-bug
feat: correct z-index level for floating always rendered panel
This commit is contained in:
commit
520aa39724
@ -8,11 +8,11 @@ import {
|
|||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { Writable, exhaustMicrotaskQueue } from '../__test_utils__/utils';
|
import { Writable, exhaustMicrotaskQueue } from '../__test_utils__/utils';
|
||||||
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
import { DockviewComponent } from '../../dockview/dockviewComponent';
|
||||||
|
import { DockviewGroupPanel } from '../../dockview/dockviewGroupPanel';
|
||||||
|
|
||||||
describe('overlayRenderContainer', () => {
|
describe('overlayRenderContainer', () => {
|
||||||
let referenceContainer: IRenderable;
|
let referenceContainer: IRenderable;
|
||||||
let parentContainer: HTMLElement;
|
let parentContainer: HTMLElement;
|
||||||
let cut: OverlayRenderContainer;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
parentContainer = document.createElement('div');
|
parentContainer = document.createElement('div');
|
||||||
@ -21,14 +21,14 @@ describe('overlayRenderContainer', () => {
|
|||||||
element: document.createElement('div'),
|
element: document.createElement('div'),
|
||||||
dropTarget: fromPartial<Droptarget>({}),
|
dropTarget: fromPartial<Droptarget>({}),
|
||||||
};
|
};
|
||||||
|
|
||||||
cut = new OverlayRenderContainer(
|
|
||||||
parentContainer,
|
|
||||||
fromPartial<DockviewComponent>({})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('that attach(...) and detach(...) mutate the DOM as expected', () => {
|
test('that attach(...) and detach(...) mutate the DOM as expected', () => {
|
||||||
|
const cut = new OverlayRenderContainer(
|
||||||
|
parentContainer,
|
||||||
|
fromPartial<DockviewComponent>({})
|
||||||
|
);
|
||||||
|
|
||||||
const panelContentEl = document.createElement('div');
|
const panelContentEl = document.createElement('div');
|
||||||
|
|
||||||
const onDidVisibilityChange = new Emitter<any>();
|
const onDidVisibilityChange = new Emitter<any>();
|
||||||
@ -42,6 +42,7 @@ describe('overlayRenderContainer', () => {
|
|||||||
onDidDimensionsChange: onDidDimensionsChange.event,
|
onDidDimensionsChange: onDidDimensionsChange.event,
|
||||||
onDidLocationChange: onDidLocationChange.event,
|
onDidLocationChange: onDidLocationChange.event,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
|
location: { type: 'grid' },
|
||||||
},
|
},
|
||||||
view: {
|
view: {
|
||||||
content: {
|
content: {
|
||||||
@ -67,6 +68,11 @@ describe('overlayRenderContainer', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('add a view that is not currently in the DOM', async () => {
|
test('add a view that is not currently in the DOM', async () => {
|
||||||
|
const cut = new OverlayRenderContainer(
|
||||||
|
parentContainer,
|
||||||
|
fromPartial<DockviewComponent>({})
|
||||||
|
);
|
||||||
|
|
||||||
const panelContentEl = document.createElement('div');
|
const panelContentEl = document.createElement('div');
|
||||||
|
|
||||||
const onDidVisibilityChange = new Emitter<any>();
|
const onDidVisibilityChange = new Emitter<any>();
|
||||||
@ -80,6 +86,7 @@ describe('overlayRenderContainer', () => {
|
|||||||
onDidDimensionsChange: onDidDimensionsChange.event,
|
onDidDimensionsChange: onDidDimensionsChange.event,
|
||||||
onDidLocationChange: onDidLocationChange.event,
|
onDidLocationChange: onDidLocationChange.event,
|
||||||
isVisible: true,
|
isVisible: true,
|
||||||
|
location: { type: 'grid' },
|
||||||
},
|
},
|
||||||
view: {
|
view: {
|
||||||
content: {
|
content: {
|
||||||
@ -197,4 +204,60 @@ describe('overlayRenderContainer', () => {
|
|||||||
referenceContainer.element.getBoundingClientRect
|
referenceContainer.element.getBoundingClientRect
|
||||||
).toHaveBeenCalledTimes(3);
|
).toHaveBeenCalledTimes(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('related z-index from `aria-level` set on floating panels', async () => {
|
||||||
|
const group = fromPartial<DockviewGroupPanel>({});
|
||||||
|
|
||||||
|
const element = document.createElement('div');
|
||||||
|
element.setAttribute('aria-level', '2');
|
||||||
|
const spy = jest.spyOn(element, 'getAttribute');
|
||||||
|
|
||||||
|
const accessor = fromPartial<DockviewComponent>({
|
||||||
|
floatingGroups: [
|
||||||
|
{
|
||||||
|
group,
|
||||||
|
overlay: {
|
||||||
|
element,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const cut = new OverlayRenderContainer(parentContainer, accessor);
|
||||||
|
|
||||||
|
const panelContentEl = document.createElement('div');
|
||||||
|
|
||||||
|
const onDidVisibilityChange = new Emitter<any>();
|
||||||
|
const onDidDimensionsChange = new Emitter<any>();
|
||||||
|
const onDidLocationChange = new Emitter<any>();
|
||||||
|
|
||||||
|
const panel = fromPartial<IDockviewPanel>({
|
||||||
|
api: {
|
||||||
|
id: 'test_panel_id',
|
||||||
|
onDidVisibilityChange: onDidVisibilityChange.event,
|
||||||
|
onDidDimensionsChange: onDidDimensionsChange.event,
|
||||||
|
onDidLocationChange: onDidLocationChange.event,
|
||||||
|
isVisible: true,
|
||||||
|
group,
|
||||||
|
location: { type: 'floating' },
|
||||||
|
},
|
||||||
|
view: {
|
||||||
|
content: {
|
||||||
|
element: panelContentEl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
group: {
|
||||||
|
api: {
|
||||||
|
location: { type: 'floating' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
cut.attach({ panel, referenceContainer });
|
||||||
|
|
||||||
|
await exhaustMicrotaskQueue();
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalledWith('aria-level');
|
||||||
|
expect(panelContentEl.parentElement!.style.zIndex).toBe('1004');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -87,7 +87,7 @@ export class DockviewPanel
|
|||||||
// you are actually just resizing the panels parent which is the group
|
// you are actually just resizing the panels parent which is the group
|
||||||
this.group.api.setSize(event);
|
this.group.api.setSize(event);
|
||||||
}),
|
}),
|
||||||
this.api.onDidRendererChange((event) => {
|
this.api.onDidRendererChange(() => {
|
||||||
this.group.model.rerender(this);
|
this.group.model.rerender(this);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -120,6 +120,48 @@ export class OverlayRenderContainer extends CompositeDisposable {
|
|||||||
|
|
||||||
const observerDisposable = new MutableDisposable();
|
const observerDisposable = new MutableDisposable();
|
||||||
|
|
||||||
|
const correctLayerPosition = () => {
|
||||||
|
if (panel.api.location.type === 'floating') {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const disposable = new CompositeDisposable(
|
const disposable = new CompositeDisposable(
|
||||||
observerDisposable,
|
observerDisposable,
|
||||||
/**
|
/**
|
||||||
@ -147,7 +189,7 @@ export class OverlayRenderContainer extends CompositeDisposable {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
panel.api.onDidVisibilityChange((event) => {
|
panel.api.onDidVisibilityChange(() => {
|
||||||
/**
|
/**
|
||||||
* Control the visibility of the content, however even when not visible (display: none)
|
* Control the visibility of the content, however even when not visible (display: none)
|
||||||
* the content is still maintained within the DOM hence DOM specific attributes
|
* the content is still maintained within the DOM hence DOM specific attributes
|
||||||
@ -162,48 +204,8 @@ export class OverlayRenderContainer extends CompositeDisposable {
|
|||||||
|
|
||||||
resize();
|
resize();
|
||||||
}),
|
}),
|
||||||
panel.api.onDidLocationChange((event) => {
|
panel.api.onDidLocationChange(() => {
|
||||||
const isFloating = event.location.type === 'floating';
|
correctLayerPosition();
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -215,6 +217,8 @@ export class OverlayRenderContainer extends CompositeDisposable {
|
|||||||
focusContainer.parentElement?.removeChild(focusContainer);
|
focusContainer.parentElement?.removeChild(focusContainer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
correctLayerPosition();
|
||||||
|
|
||||||
queueMicrotask(() => {
|
queueMicrotask(() => {
|
||||||
if (this.isDisposed) {
|
if (this.isDisposed) {
|
||||||
return;
|
return;
|
||||||
|
Loading…
Reference in New Issue
Block a user