summaryrefslogtreecommitdiff
path: root/packages/frontend/src/scripts
diff options
context:
space:
mode:
authorかっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>2024-08-18 14:18:46 +0900
committerGitHub <noreply@github.com>2024-08-18 14:18:46 +0900
commitb53ee54e4f1172a0d13ef0808b7236c176bf8d1a (patch)
tree03b0dd4bdc759ec750fedfabc61ac72b1cdb9b36 /packages/frontend/src/scripts
parentBump version to 2024.8.0-rc.4 (diff)
downloadsharkey-b53ee54e4f1172a0d13ef0808b7236c176bf8d1a.tar.gz
sharkey-b53ee54e4f1172a0d13ef0808b7236c176bf8d1a.tar.bz2
sharkey-b53ee54e4f1172a0d13ef0808b7236c176bf8d1a.zip
fix(frontend): focustrapがzindexを考慮するように (#14431)
Diffstat (limited to 'packages/frontend/src/scripts')
-rw-r--r--packages/frontend/src/scripts/focus-trap.ts64
1 files changed, 60 insertions, 4 deletions
diff --git a/packages/frontend/src/scripts/focus-trap.ts b/packages/frontend/src/scripts/focus-trap.ts
index a5df36f520..fb7caea830 100644
--- a/packages/frontend/src/scripts/focus-trap.ts
+++ b/packages/frontend/src/scripts/focus-trap.ts
@@ -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);