fix zindex

This commit is contained in:
Juergen Kunz
2025-06-26 18:37:49 +00:00
parent 931a760ee1
commit b5a2bd7436
5 changed files with 495 additions and 96 deletions

View File

@ -56,4 +56,106 @@ export const componentZIndex = {
'dees-mobilenavigation': zIndexLayers.fixed.mobileNav,
'dees-slash-menu': zIndexLayers.wysiwygMenus,
'dees-formatting-menu': zIndexLayers.wysiwygMenus,
} as const;
} as const;
/**
* Z-Index Registry for managing stacked elements
* Simple incremental z-index assignment based on creation order
*/
export class ZIndexRegistry {
private static instance: ZIndexRegistry;
private activeElements = new Set<HTMLElement>();
private elementZIndexMap = new WeakMap<HTMLElement, number>();
private currentZIndex = 1000; // Starting z-index
private constructor() {}
public static getInstance(): ZIndexRegistry {
if (!ZIndexRegistry.instance) {
ZIndexRegistry.instance = new ZIndexRegistry();
}
return ZIndexRegistry.instance;
}
/**
* Get the next available z-index
* @returns The next available z-index
*/
public getNextZIndex(): number {
this.currentZIndex += 10;
return this.currentZIndex;
}
/**
* Register an element with the z-index registry
* @param element - The HTML element to register
* @param zIndex - The z-index assigned to this element
*/
public register(element: HTMLElement, zIndex: number): void {
this.activeElements.add(element);
this.elementZIndexMap.set(element, zIndex);
}
/**
* Unregister an element from the z-index registry
* @param element - The HTML element to unregister
*/
public unregister(element: HTMLElement): void {
this.activeElements.delete(element);
this.elementZIndexMap.delete(element);
// If no more active elements, reset counter to base
if (this.activeElements.size === 0) {
this.currentZIndex = 1000;
}
}
/**
* Get the z-index for a specific element
* @param element - The HTML element
* @returns The z-index or undefined if not registered
*/
public getElementZIndex(element: HTMLElement): number | undefined {
return this.elementZIndexMap.get(element);
}
/**
* Get count of active elements
* @returns Number of active elements
*/
public getActiveCount(): number {
return this.activeElements.size;
}
/**
* Get the current highest z-index
* @returns The current z-index value
*/
public getCurrentZIndex(): number {
return this.currentZIndex;
}
/**
* Clear all registrations (useful for testing)
*/
public clear(): void {
this.activeElements.clear();
this.elementZIndexMap = new WeakMap();
this.currentZIndex = 1000;
}
/**
* Get all active elements in z-index order
* @returns Array of elements sorted by z-index
*/
public getActiveElementsInOrder(): HTMLElement[] {
return Array.from(this.activeElements).sort((a, b) => {
const aZ = this.elementZIndexMap.get(a) || 0;
const bZ = this.elementZIndexMap.get(b) || 0;
return aZ - bZ;
});
}
}
// Export singleton instance for convenience
export const zIndexRegistry = ZIndexRegistry.getInstance();

View File

@ -280,6 +280,11 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
elevatedDropdown.style.top = this.getBoundingClientRect().top + 'px';
elevatedDropdown.style.left = this.getBoundingClientRect().left + 'px';
elevatedDropdown.style.width = this.clientWidth + 'px';
// Get z-index from registry for the elevated dropdown
const dropdownZIndex = (await import('./00zindex.js')).zIndexRegistry.getNextZIndex();
elevatedDropdown.style.zIndex = dropdownZIndex.toString();
(await import('./00zindex.js')).zIndexRegistry.register(elevatedDropdown, dropdownZIndex);
elevatedDropdown.options = this.options;
elevatedDropdown.selectedOption = this.selectedOption;
elevatedDropdown.highlightedIndex = elevatedDropdown.selectedOption ? elevatedDropdown.options.indexOf(
@ -296,9 +301,13 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
'0';
elevatedDropdown.removeEventListener('selectedOption', handleSelection);
this.windowOverlay.removeEventListener('clicked', destroyOverlay);
// Unregister elevated dropdown from z-index registry
(await import('./00zindex.js')).zIndexRegistry.unregister(elevatedDropdown);
this.windowOverlay.destroy();
};
const handleSelection = async (event) => {
const handleSelection = async () => {
await this.updateSelection(elevatedDropdown.selectedOption);
destroyOverlay();
};
@ -323,10 +332,20 @@ export class DeesInputDropdown extends DeesInputBase<DeesInputDropdown> {
await domtoolsInstance.convenience.smartdelay.delayFor(0);
const searchInput = selectionBox.querySelector('input');
searchInput?.focus();
// Get z-index from registry for the selection box
const selectionBoxZIndex = (await import('./00zindex.js')).zIndexRegistry.getNextZIndex();
selectionBox.style.zIndex = selectionBoxZIndex.toString();
(await import('./00zindex.js')).zIndexRegistry.register(selectionBox as HTMLElement, selectionBoxZIndex);
selectionBox.classList.add('show');
} else {
selectedBox.style.pointerEvents = 'none';
selectionBox.classList.remove('show');
// Unregister selection box from z-index registry
(await import('./00zindex.js')).zIndexRegistry.unregister(selectionBox as HTMLElement);
// selectedBox.style.opacity = '0';
}
}

View File

@ -1,6 +1,6 @@
import * as colors from './00colors.js';
import * as plugins from './00plugins.js';
import { zIndexLayers } from './00zindex.js';
import { zIndexLayers, zIndexRegistry } from './00zindex.js';
import { demoFunc } from './dees-modal.demo.js';
import {
@ -62,6 +62,11 @@ export class DeesModal extends DeesElement {
});
body.append(modal.windowLayer);
body.append(modal);
// Get z-index for modal (should be above window layer)
modal.modalZIndex = zIndexRegistry.getNextZIndex();
zIndexRegistry.register(modal, modal.modalZIndex);
return modal;
}
@ -95,6 +100,9 @@ export class DeesModal extends DeesElement {
@property({ attribute: false })
public onHelp: () => void | Promise<void>;
@state()
private modalZIndex: number = 1000;
constructor() {
super();
@ -118,7 +126,6 @@ export class DeesModal extends DeesElement {
box-sizing: border-box;
align-items: center;
justify-content: center;
z-index: ${zIndexLayers.overlay.modal};
}
.modal {
will-change: transform;
@ -291,7 +298,7 @@ export class DeesModal extends DeesElement {
${maxWidthStyle ? `.modal { max-width: ${maxWidthStyle}; }` : ''}
${minWidthStyle ? `.modal { min-width: ${minWidthStyle}; }` : ''}
</style>
<div class="modalContainer" @click=${this.handleOutsideClick}>
<div class="modalContainer" @click=${this.handleOutsideClick} style="z-index: ${this.modalZIndex}">
<div class="modal ${widthClass}">
<div class="heading">
<div class="heading-text">${this.heading}</div>
@ -349,6 +356,9 @@ export class DeesModal extends DeesElement {
await domtools.convenience.smartdelay.delayFor(200);
document.body.removeChild(this);
await this.windowLayer.destroy();
// Unregister from z-index registry
zIndexRegistry.unregister(this);
}
private async handleHelp() {

View File

@ -1,5 +1,5 @@
import { customElement, DeesElement, domtools, type TemplateResult, html, property, type CSSResult, state, } from '@design.estate/dees-element';
import { zIndexLayers } from './00zindex.js';
import { zIndexLayers, zIndexRegistry } from './00zindex.js';
declare global {
interface HTMLElementTagNameMap {
@ -33,6 +33,12 @@ export class DeesWindowLayer extends DeesElement {
public options: IOptions_DeesWindowLayer = {
blur: false
};
@state()
private backdropZIndex: number = 1000;
@state()
private contentZIndex: number = 1001;
// INSTANCE
@property({
@ -63,7 +69,7 @@ export class DeesWindowLayer extends DeesElement {
background: rgba(0, 0, 0, 0.0);
backdrop-filter: brightness(1) ${this.options.blur ? 'blur(0px)' : ''};
pointer-events: none;
z-index: ${zIndexLayers.backdrop.dropdown};
z-index: ${this.backdropZIndex};
}
.slotContent {
position: fixed;
@ -72,7 +78,7 @@ export class DeesWindowLayer extends DeesElement {
display: flex;
justify-content: center;
align-items: center;
z-index: ${zIndexLayers.overlay.dropdown};
z-index: ${this.contentZIndex};
}
.visible {
@ -102,9 +108,21 @@ export class DeesWindowLayer extends DeesElement {
public toggleVisibility () {
this.visible = !this.visible;
}
public getContentZIndex(): number {
return this.contentZIndex;
}
public async show() {
const domtools = await this.domtoolsPromise;
// Get z-indexes from registry
this.backdropZIndex = zIndexRegistry.getNextZIndex();
this.contentZIndex = zIndexRegistry.getNextZIndex();
// Register this element
zIndexRegistry.register(this, this.backdropZIndex);
await domtools.convenience.smartdelay.delayFor(0);
this.visible = true;
}
@ -119,6 +137,10 @@ export class DeesWindowLayer extends DeesElement {
const domtools = await this.domtoolsPromise;
await this.hide();
await domtools.convenience.smartdelay.delayFor(300);
// Unregister from z-index registry
zIndexRegistry.unregister(this);
this.remove();
}
}