UX problem: Hover Delay for Dropdown Menu

Δημοσιεύθηκε 21/01/2024

Το πρόβλημα:

Πολύ συχνά βλέπουμε σε ιστοσελίδες που χρησιμοποιούν Mega Dropdown Menu, να μην έχουν προβλέψει να διορθώσουν ένα σημαντικό UX problem: Δεν έχει προστεθεί Hover Delay for Dropdown Menu.

Ανοίγει το dropdown χωρίς να το περιμένεις!
Με ένα αναγκαστικό στιγμιαίο πέρασμα του ποντικιού πάνω από το μενού, για να προχωρήσεις την πλοήγησή σου στην ιστοσελίδα, ανοίγει το dropdown.

Η λύση:

Μπορείς να προσθέσεις ένα hover delay, δηλαδή να απαιτείται να παραμείνει ένα χρονικό διάστημα (το ελάχιστον δυνατό) το ποντίκι πάνω από το parent item προκειμένου να ανοίξει το dropdown menu.

Διαφορετικά θεωρείται ότι το ποντίκι πέρασε αναγκαστικά-στιγμιαία προκειμένου να πάει σε άλλο μέρος της ιστοσελίδας και δεν θέλουμε να ανοιχθεί το dropdown menu.

Ο κώδικας:

Το κάνουμε με τη βοήθεια του Timeout. Όταν εντοπίσουμε ότι το ποντίκι είναι πάνω από το parent item, ξεκινάμε να μετράμε και αν έχει παραμείνει πάνω από 200-300 ms τότε ανοίγουμε το dropdown menu, διαφορετικά σταματάμε το μέτρημα και δεν το ανοίγουμε

let hoverTimeout;
let dropdownMenu;
const parent_items = document.querySelectorAll(".menu-item-has-dropdown");
if (parent_items.length > 0) {
    parent_items.forEach((element) => {
        dropdownMenu = element.querySelect("dropdown");
        // Set a delay before revealing the dropdown menu on hover
        element.addEventListener("mouseenter", () => {
            hoverTimeout = setTimeout(() => {
                close_all_dropdowns(element)
                dropdownMenu?.classList.add("open_dropdown_class");
                // if mouseleave from dropdown then close it
                dropdownMenu?.addEventListener('mouseleave', () => {
                    dropdownMenu?.classList.remove("open_dropdown_class");
                });
            }, 200);
        });

        //Clear the timeout for opening the dropdown when the mouse leaves the parent item
        element.addEventListener('mouseleave', () => {
            clearTimeout(hoverTimeout);
        });

        // OPTIONAL: Also Open / Close dropdown on click
        element.addEventListener("click", () => {
            close_all_dropdowns(element)
            dropdownMenu?.classList.toggle("open_dropdown_class");
        });
    });
}
function close_all_dropdowns(except_this) {
    parent_items.forEach((element) => {
        dropdownMenu = element.querySelect("dropdown");
        if (element !== except_this) {
            dropdownMenu?.classList.remove("open_dropdown_class");
        }
    });
}