diff --git a/packages/dockview-core/src/dockview/components/popupService.ts b/packages/dockview-core/src/dockview/components/popupService.ts index dc33488c0..1d34dc662 100644 --- a/packages/dockview-core/src/dockview/components/popupService.ts +++ b/packages/dockview-core/src/dockview/components/popupService.ts @@ -1,3 +1,4 @@ +import { shiftAbsoluteElementIntoView } from '../../dom'; import { addDisposableListener } from '../../events'; import { CompositeDisposable, @@ -5,48 +6,6 @@ import { MutableDisposable, } from '../../lifecycle'; -function shiftAbsoluteElementIntoView(element: HTMLElement, root: HTMLElement) { - const rect = element.getBoundingClientRect(); - const rootRect = element.getBoundingClientRect(); - - const viewportWidth = root.clientWidth; - const viewportHeight = root.clientHeight; - - // const viewportWidth = - // window.innerWidth || document.documentElement.clientWidth; - // const viewportHeight = - // window.innerHeight || document.documentElement.clientHeight; - - const buffer = 10; // 10px buffer - - let translateX = 0; - let translateY = 0; - - const left = rect.left - rootRect.left; - const top = rect.top - rootRect.top; - const bottom = rect.bottom - rootRect.bottom; - const right = rect.right - rootRect.right; - - // Check horizontal overflow - if (left < buffer) { - translateX = buffer - left; - } else if (right > viewportWidth - buffer) { - translateX = viewportWidth - right - buffer; - } - - // Check vertical overflow - if (top < buffer) { - translateY = buffer - top; - } else if (bottom > viewportHeight - buffer) { - translateY = viewportHeight - bottom - buffer; - } - - // Apply the translation if needed - if (translateX !== 0 || translateY !== 0) { - element.style.transform = `translate(${translateX}px, ${translateY}px)`; - } -} - export class PopupService extends CompositeDisposable { private readonly _element: HTMLElement; private _active: HTMLElement | null = null; @@ -71,13 +30,13 @@ export class PopupService extends CompositeDisposable { openPopover( element: HTMLElement, - position: { x: number; y: number } + position: { x: number; y: number; zIndex?: string } ): void { this.close(); const wrapper = document.createElement('div'); wrapper.style.position = 'absolute'; - wrapper.style.zIndex = '99'; + wrapper.style.zIndex = position.zIndex ?? 'var(--dv-overlay-z-index)'; wrapper.appendChild(element); const anchorBox = this._element.getBoundingClientRect(); @@ -92,7 +51,7 @@ export class PopupService extends CompositeDisposable { this._active = wrapper; this._activeDisposable.value = new CompositeDisposable( - addDisposableListener(window, 'pointerdown', (event) => { + addDisposableListener(window, 'pointerdown', (event) => { const target = event.target; if (!(target instanceof HTMLElement)) { diff --git a/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts b/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts index cf60baeeb..d2117c744 100644 --- a/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts +++ b/packages/dockview-core/src/dockview/components/titlebar/tabsContainer.ts @@ -8,7 +8,7 @@ import { addDisposableListener, Emitter, Event } from '../../../events'; import { Tab } from '../tab/tab'; import { DockviewGroupPanel } from '../../dockviewGroupPanel'; import { VoidContainer } from './voidContainer'; -import { toggleClass } from '../../../dom'; +import { findRelativeZIndexParent, toggleClass } from '../../../dom'; import { IDockviewPanel } from '../../dockviewPanel'; import { DockviewComponent } from '../../dockviewComponent'; import { WillShowOverlayLocationEvent } from '../../dockviewGroupPanelModel'; @@ -378,7 +378,7 @@ export class TabsContainer !panelObject.api.isActive ); - wrapper.addEventListener('mousedown', () => { + wrapper.addEventListener('pointerdown', () => { this.accessor.popupService.close(); tab.element.scrollIntoView(); tab.panel.api.setActive(); @@ -388,9 +388,14 @@ export class TabsContainer el.appendChild(wrapper); } + const relativeParent = findRelativeZIndexParent(root); + this.accessor.popupService.openPopover(el, { x: event.clientX, y: event.clientY, + zIndex: relativeParent?.style.zIndex + ? `calc(${relativeParent.style.zIndex} * 2)` + : undefined, }); }) ); diff --git a/packages/dockview-core/src/dom.ts b/packages/dockview-core/src/dom.ts index d02620b65..43e3f4990 100644 --- a/packages/dockview-core/src/dom.ts +++ b/packages/dockview-core/src/dom.ts @@ -451,3 +451,53 @@ export function onDidWindowResizeEnd(element: Window, cb: () => void) { return disposable; } + +export function shiftAbsoluteElementIntoView( + element: HTMLElement, + root: HTMLElement, + options: { buffer: number } = { buffer: 10 } +) { + const buffer = options.buffer; + const rect = element.getBoundingClientRect(); + const rootRect = element.getBoundingClientRect(); + + const viewportWidth = root.clientWidth; + const viewportHeight = root.clientHeight; + + let translateX = 0; + let translateY = 0; + + const left = rect.left - rootRect.left; + const top = rect.top - rootRect.top; + const bottom = rect.bottom - rootRect.bottom; + const right = rect.right - rootRect.right; + + // Check horizontal overflow + if (left < buffer) { + translateX = buffer - left; + } else if (right > viewportWidth - buffer) { + translateX = viewportWidth - right - buffer; + } + + // Check vertical overflow + if (top < buffer) { + translateY = buffer - top; + } else if (bottom > viewportHeight - buffer) { + translateY = viewportHeight - bottom - buffer; + } + + // Apply the translation if needed + if (translateX !== 0 || translateY !== 0) { + element.style.transform = `translate(${translateX}px, ${translateY}px)`; + } +} + +export function findRelativeZIndexParent(el: HTMLElement): HTMLElement | null { + let tmp: HTMLElement | null = el; + + while (tmp && (tmp.style.zIndex === 'auto' || tmp.style.zIndex === '')) { + tmp = tmp.parentElement; + } + + return tmp; +}