mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-04 08:15:41 +00:00
fix: open the keyboard shortcuts at the top instead of scrolled down to the tour link
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useId, useRef, type ReactNode, type RefObject, type FormEvent } from "react";
|
||||
import { useId, useRef, type ReactNode, type RefObject, type FormEvent } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useFocusTrap } from "@/hooks/use-focus-trap";
|
||||
@@ -91,23 +91,18 @@ export function Dialog({
|
||||
const id = useId();
|
||||
const titleId = `${id}-title`;
|
||||
const descriptionId = `${id}-description`;
|
||||
const panelRef = useFocusTrap({ isActive: isOpen, onEscape: onClose, restoreFocus: true });
|
||||
// The focus starts on an explicit target, else the first field, else
|
||||
// the first control.
|
||||
const panelRef = useFocusTrap({
|
||||
isActive: isOpen,
|
||||
onEscape: onClose,
|
||||
restoreFocus: true,
|
||||
initialFocus: () => initialFocus?.current ?? panelRef.current?.querySelector<HTMLElement>(FIELD_SELECTOR),
|
||||
});
|
||||
// A press that started on the backdrop, so a text selection dragged out of
|
||||
// a field and released outside doesn't count as an outside click.
|
||||
const pressedOnBackdrop = useRef(false);
|
||||
|
||||
// The focus trap has put the focus on the first control; a field or an
|
||||
// explicit target is the better start.
|
||||
useEffect(() => {
|
||||
if (!isOpen) return;
|
||||
const panel = panelRef.current;
|
||||
if (!panel) return;
|
||||
const target = initialFocus?.current ?? panel.querySelector<HTMLElement>(FIELD_SELECTOR);
|
||||
target?.focus();
|
||||
// Only on open: a later render must not pull the focus back.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isOpen]);
|
||||
|
||||
if (!isOpen || typeof document === "undefined") return null;
|
||||
|
||||
const blockOutside = preventOutsideClose || dirty;
|
||||
|
||||
@@ -8,12 +8,15 @@ interface UseFocusTrapOptions {
|
||||
isActive: boolean;
|
||||
onEscape?: () => void;
|
||||
restoreFocus?: boolean;
|
||||
/** Where the focus goes on open, instead of the first focusable element. */
|
||||
initialFocus?: () => HTMLElement | null | undefined;
|
||||
}
|
||||
|
||||
export function useFocusTrap({
|
||||
isActive,
|
||||
onEscape,
|
||||
restoreFocus = true,
|
||||
initialFocus,
|
||||
}: UseFocusTrapOptions) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const previousActiveElement = useRef<HTMLElement | null>(null);
|
||||
@@ -22,8 +25,10 @@ export function useFocusTrap({
|
||||
// focus back to the opener and then to the first element, out of the field
|
||||
// the user was typing in whenever the page behind rendered again.
|
||||
const onEscapeRef = useRef(onEscape);
|
||||
const initialFocusRef = useRef(initialFocus);
|
||||
useEffect(() => {
|
||||
onEscapeRef.current = onEscape;
|
||||
initialFocusRef.current = initialFocus;
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -57,12 +62,9 @@ export function useFocusTrap({
|
||||
};
|
||||
container.addEventListener('focusin', handleFocusIn);
|
||||
|
||||
// Focus first element
|
||||
const focusableElements = getFocusableElements();
|
||||
const firstElement = focusableElements[0];
|
||||
if (firstElement) {
|
||||
firstElement.focus();
|
||||
}
|
||||
// Focus the requested element, else the first one
|
||||
const target = initialFocusRef.current?.() ?? getFocusableElements()[0];
|
||||
target?.focus();
|
||||
|
||||
// Handle Tab key to trap focus
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
|
||||
Reference in New Issue
Block a user