fix(frontend): focustrapがzindexを考慮するように (#14431)
This commit is contained in:
		
							parent
							
								
									b708b27bc8
								
							
						
					
					
						commit
						b53ee54e4f
					
				
					 1 changed files with 60 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -16,21 +16,57 @@ function containsFocusTrappedElements(el: HTMLElement): boolean {
 | 
			
		|||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getZIndex(el: HTMLElement): number {
 | 
			
		||||
	const zIndex = parseInt(window.getComputedStyle(el).zIndex || '0', 10);
 | 
			
		||||
	if (isNaN(zIndex)) {
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	return zIndex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getHighestZIndexElement(): { el: HTMLElement; zIndex: number; } | null {
 | 
			
		||||
	let highestZIndexElement: HTMLElement | null = null;
 | 
			
		||||
	let highestZIndex = -Infinity;
 | 
			
		||||
 | 
			
		||||
	focusTrapElements.forEach((el) => {
 | 
			
		||||
		const zIndex = getZIndex(el);
 | 
			
		||||
		if (zIndex > highestZIndex) {
 | 
			
		||||
			highestZIndex = zIndex;
 | 
			
		||||
			highestZIndexElement = el;
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	return highestZIndexElement == null ? null : {
 | 
			
		||||
		el: highestZIndexElement,
 | 
			
		||||
		zIndex: highestZIndex,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function releaseFocusTrap(el: HTMLElement): void {
 | 
			
		||||
	focusTrapElements.delete(el);
 | 
			
		||||
	if (el.inert === true) {
 | 
			
		||||
		el.inert = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const highestZIndexElement = getHighestZIndexElement();
 | 
			
		||||
 | 
			
		||||
	if (el.parentElement != null && el !== document.body) {
 | 
			
		||||
		el.parentElement.childNodes.forEach((siblingNode) => {
 | 
			
		||||
			const siblingEl = getHTMLElementOrNull(siblingNode);
 | 
			
		||||
			if (!siblingEl) return;
 | 
			
		||||
			if (siblingEl !== el && (focusTrapElements.has(siblingEl) || containsFocusTrappedElements(siblingEl) || focusTrapElements.size === 0)) {
 | 
			
		||||
			if (
 | 
			
		||||
				siblingEl !== el &&
 | 
			
		||||
				(
 | 
			
		||||
					highestZIndexElement == null ||
 | 
			
		||||
					siblingEl === highestZIndexElement.el ||
 | 
			
		||||
					siblingEl.contains(highestZIndexElement.el)
 | 
			
		||||
				)
 | 
			
		||||
			) {
 | 
			
		||||
				siblingEl.inert = false;
 | 
			
		||||
			} else if (
 | 
			
		||||
				focusTrapElements.size > 0 &&
 | 
			
		||||
				!containsFocusTrappedElements(siblingEl) &&
 | 
			
		||||
				!focusTrapElements.has(siblingEl) &&
 | 
			
		||||
				highestZIndexElement != null &&
 | 
			
		||||
				siblingEl !== highestZIndexElement.el &&
 | 
			
		||||
				!siblingEl.contains(highestZIndexElement.el) &&
 | 
			
		||||
				!ignoreElements.includes(siblingEl.tagName.toLowerCase())
 | 
			
		||||
			) {
 | 
			
		||||
				siblingEl.inert = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -45,9 +81,29 @@ function releaseFocusTrap(el: HTMLElement): void {
 | 
			
		|||
export function focusTrap(el: HTMLElement, hasInteractionWithOtherFocusTrappedEls: boolean, parent: true): void;
 | 
			
		||||
export function focusTrap(el: HTMLElement, hasInteractionWithOtherFocusTrappedEls?: boolean, parent?: false): { release: () => void; };
 | 
			
		||||
export function focusTrap(el: HTMLElement, hasInteractionWithOtherFocusTrappedEls = false, parent = false): { release: () => void; } | void {
 | 
			
		||||
	const highestZIndexElement = getHighestZIndexElement();
 | 
			
		||||
 | 
			
		||||
	const highestZIndex = highestZIndexElement == null ? -Infinity : highestZIndexElement.zIndex;
 | 
			
		||||
	const zIndex = getZIndex(el);
 | 
			
		||||
 | 
			
		||||
	// If the element has a lower z-index than the highest z-index element, focus trap the highest z-index element instead
 | 
			
		||||
	// Focus trapping for this element will be done in the release function
 | 
			
		||||
	if (!parent && zIndex < highestZIndex) {
 | 
			
		||||
		focusTrapElements.add(el);
 | 
			
		||||
		if (highestZIndexElement) {
 | 
			
		||||
			focusTrap(highestZIndexElement.el, hasInteractionWithOtherFocusTrappedEls);
 | 
			
		||||
		}
 | 
			
		||||
		return {
 | 
			
		||||
			release: () => {
 | 
			
		||||
				releaseFocusTrap(el);
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (el.inert === true) {
 | 
			
		||||
		el.inert = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (el.parentElement != null && el !== document.body) {
 | 
			
		||||
		el.parentElement.childNodes.forEach((siblingNode) => {
 | 
			
		||||
			const siblingEl = getHTMLElementOrNull(siblingNode);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue