[TikiWiki-commits] [Git][tikiwiki/tiki][master] [FIX] Restore native SmartMenus scrolling

"luci \(@luciash\) via TikiWiki-cvs" <[email protected]>
Newsgroups gmane.comp.cms.tiki.cvs
Message-ID <69f4b54e53662_3818fec0886e4@gitlab-sidekiq-low-urgency-cpu-bound-v2-778c5f576f-vrzr4.mail>

luci pushed to branch master at Tiki Wiki CMS Groupware / Tiki


Commits:
ec98dc96 by Moïse Nturubika at 2026-05-01T13:52:57+00:00
[FIX] Restore native SmartMenus scrolling
---
* [FIX] Updated menu arrows to point correctly and added RTL support

* [FIX][UI] SmartMenus: Correct vertical arrow defaults and fix nested dropup staircase

* [FIX][UI] Fix SmartMenus v2 regressions (arrow reactivity, mobile touch, and dropups)

* [FIX] SmartMenus: Improve mobile UX with auto-dismissal and hierarchical accordion logic

* [FIX] SmartMenus: Resolve regressions including overflow trap, arrow indicators, and mobile touch events

* [FIX][UI] Fix the vertical offset

* [FIX][UI] Restore SmartMenus v2 layering and ensure dropdown reachability

* [FIX] SmartMenus: Restore native scrolling and modernize dropdown positioning logic

* [FIX] Restore native SmartMenus scrolling

See merge request tikiwiki/tiki!9733

- - - - -


3 changed files:

- src/js/jquery-tiki/tiki-menu.js
- themes/base_files/scss/_tiki-menus.scss
- themes/base_files/scss/_tiki-variables.scss


Changes:

=====================================
src/js/jquery-tiki/tiki-menu.js
=====================================
@@ -14,10 +14,10 @@
  */
 
 $(function () {
-    $(".sm-nav-item, .dropdown, .mega-menu").each(function () {
+    $(".dropdown, .mega-menu").each(function () {
         const $parent = $(this);
         const $menu = $parent.find(".dropdown-menu, ul").first();
-        if (!$menu.length) return;
+        if (!$menu.length || $parent.hasClass("sm-nav-item") || $menu.hasClass("sm-sub")) return;
 
         const id = $parent.closest(".card-body").attr("id");
 
@@ -47,17 +47,9 @@ $(function () {
             var viewportH = window.innerHeight;
 
             var menuMaxW = Math.min(viewportW - 16, Math.max(200, $menu.outerWidth()));
-            $menu.css({ position: "fixed", "box-sizing": "border-box", width: menuMaxW + "px" });
-
-            var menuH = Math.min($menu.outerHeight(), viewportH - 16);
-            $menu.css("max-height", menuH + "px");
-
-            var topBelow = rect.bottom + 8;
-            var topAbove = rect.top - menuH - 8;
-            var top = topBelow + menuH <= viewportH - 8 ? topBelow : Math.max(8, topAbove);
-
             var left = Math.round(rect.left + (rect.width - menuMaxW) / 2);
             left = Math.max(8, Math.min(left, viewportW - menuMaxW - 8));
+            var top = rect.bottom + 4;
 
             $menu.css({ top: top + "px", left: left + "px", right: "auto", transform: "none", zIndex: 1060 });
 
@@ -84,4 +76,55 @@ $(function () {
     });
 })(jQuery);
 
+/* Prevent mobile touch race condition on parent links (iOS Safari) */
+$(document).on("click touchend", ".sm-navbar .sm-sub-toggler", function (e) {
+    e.preventDefault();
+    e.stopImmediatePropagation();
+
+    var $toggler = $(this);
+    var $navbar = $toggler.closest(".sm-navbar");
+
+    if (!$navbar.hasClass("sm-collapsible") && window.innerWidth >= 768) {
+        return;
+    }
+
+    var $panel = $toggler.siblings(".sm-sub").first();
+    if (!$panel.length || !window.bootstrap || !window.bootstrap.Collapse) return;
+
+    var bsCollapse = window.bootstrap.Collapse.getOrCreateInstance($panel[0], { toggle: false });
+    var isShown = $panel.hasClass("show");
+
+    // Close peers but spare ancestors (Accordion behavior)
+    if (!isShown) {
+        $navbar.find(".sm-sub.show").each(function () {
+            if (this !== $panel[0] && !$.contains(this, $toggler[0])) {
+                var peer = window.bootstrap.Collapse.getInstance(this);
+                if (peer) peer.hide();
+                $(this).siblings(".sm-sub-toggler").attr("aria-expanded", "false");
+            }
+        });
+    }
+
+    bsCollapse.toggle();
+    $toggler.attr("aria-expanded", isShown ? "false" : "true");
+
+    return false;
+});
+
+/* Click outside to close open mobile menu dropdowns */
+$(document).on("touchend click", function (e) {
+    var $target = $(e.target);
+
+    // If the click is outside all navbars, close any open dropdowns
+    if (!$target.closest(".sm-navbar").length) {
+        $(".sm-navbar .sm-sub.show").each(function () {
+            var peer = window.bootstrap.Collapse.getInstance(this);
+            if (peer) {
+                peer.hide();
+                $(this).siblings(".sm-sub-toggler").attr("aria-expanded", "false");
+            }
+        });
+    }
+});
+
 // end of src/js/tiki-menu.js


=====================================
themes/base_files/scss/_tiki-menus.scss
=====================================
@@ -15,25 +15,65 @@
 }
 
 // Align the various width icons and the menu option text labels nicely
-.navbar-nav .nav-item > .nav-link .icon {
+.navbar-nav .nav-item>.nav-link .icon {
     min-width: var(--bs-gutter-x);
     text-align: center;
 }
 
 .navbar-nav.sm-vertical:not(.sm-collapsible) a:not(.dropdown-item) .sub-arrow {
     transform: rotate(-90deg);
-    /* position: absolute;
-    top: 55%;
-    margin-top: -5px;
-    bottom: auto;
-    left: auto;
-    margin-left: 0;
-    right: 10px; */
 }
 
-// Make Smartmenus dropdowns open on top of, not under, other navbars
+// Submenu Arrow Directions
+:root {
+    --tiki-menu-arrow-rotate: -90deg;
+}
+html[dir="rtl"] {
+    --tiki-menu-arrow-rotate: 90deg;
+}
+
+// Direction-neutral rule for vertical and nested flyout arrows
+.tiki .sm-navbar.sm-navbar--vertical .navbar-collapse .navbar-nav > .nav-item > .sm-sub-toggler > small *,
+.tiki .sm-sub-item > .sm-sub-toggler > small * {
+    display: inline-block !important;
+    transform: rotate(var(--tiki-menu-arrow-rotate)) !important;
+}
+
+// Reset horizontal top-level arrows to DOWN
+.tiki .sm-navbar:not(.sm-navbar--vertical) .navbar-nav > .nav-item > .sm-sub-toggler > small * {
+    transform: none !important;
+}
+
+// Prevent iOS native long-press menu on togglers
+.tiki .sm-navbar--vertical .sm-sub-toggler {
+    -webkit-touch-callout: none;
+}
+
+// Stacking Layer Isolation:
+// Ensures dropdowns (9999) appear over fixed headers while keeping 
+// the navbar container at its natural stacking level to respect sidebars.
 .tiki .sm-navbar {
     --sm-navbar-z-index: inherit !important;
+
+    .sm-sub {
+        z-index: 9999;
+    }
+}
+
+// Help long menus stay inside the screen height
+$sm-sub-top-offset: 70px; // Estimated header height
+$sm-sub-bottom-buffer: 50px; // Safety margin for viewport edges
+$sm-sub-max-height: calc(100vh - ($sm-sub-top-offset + $sm-sub-bottom-buffer));
+
+// Stop menus with submenus from clipping their children
+.tiki .sm-navbar:not(.sm-collapsible) .sm-sub:has(.sm-sub) {
+    max-height: none !important;
+    overflow-y: visible !important;
+}
+
+.tiki .sm-navbar:not(.sm-collapsible) .sm-sub:not(:has(.sm-sub)) {
+    max-height: $sm-sub-max-height;
+    overflow-y: auto;
 }
 
 /* Smartmenus navbars (Megamenu static) */
@@ -161,27 +201,50 @@
 }
 
 /* --- Force all dropdowns to open upwards ---*/
-.dropdown-menu-bottom {
+/* Note: :not(.sm-sub) prevents breaking SmartMenus v2 native collision detection */
+.dropdown-menu-bottom:not(.sm-sub) {
     top: auto !important;
     bottom: 100% !important;
     margin-bottom: .5rem;
     margin-top: 0 !important;
-    overflow-y: auto;
-    overflow-x: hidden;
 }
 
-.dropdown-menu-top-t,
-.dropdown-menu-end-l,
-.dropdown-menu-start-r {
+// Support for dropup menus (.sm-navbar--drop-reverse-y or inside bottom modules)
+.tiki .sm-navbar--drop-reverse-y,
+.tiki [id^="mod-menubottom"] .sm-navbar {
+    
+    // 1. ONLY first-level dropdowns open UPWARDS
+    .navbar-nav > .nav-item > .sm-sub {
+        top: auto !important;
+        bottom: 100% !important;
+        margin-bottom: 2px !important;
+    }
+
+    // 2. Nested flyouts open to the SIDE, aligning their bottoms with the parent item
+    .sm-sub .sm-sub {
+        top: auto !important;
+        bottom: 0 !important;
+        margin-bottom: 0 !important;
+    }
+}
+
+// Prevent clipping for dropups
+.tiki .sm-navbar:has(.sm-navbar--drop-reverse-y),
+.tiki .sm-navbar:has(.sm-navbar--drop-reverse-y) .sm-collapse,
+.tiki [id^="mod-menubottom"] .sm-navbar,
+.tiki [id^="mod-menubottom"] .sm-navbar .sm-collapse {
+    overflow: visible !important;
+}
+
+.dropdown-menu-top-t:not(.sm-sub),
+.dropdown-menu-end-l:not(.sm-sub),
+.dropdown-menu-start-r:not(.sm-sub) {
     top: 100%;
     bottom: auto;
-    max-height: 90vh;
-    overflow-y: auto;
-    overflow-x: hidden;
-    z-index: 2000 !important;
+    z-index: 2000;
 }
 
-.dropdown-menu-bottom-b {
+.dropdown-menu-bottom-b:not(.sm-sub) {
     max-height: 90vh;
     z-index: 3000;
 }


=====================================
themes/base_files/scss/_tiki-variables.scss
=====================================
@@ -157,11 +157,6 @@ header.navbar.fixed-top {
     }
 }
 
-// Added for Smartmenus 2
-.tiki .sm-navbar {
-    --sm-navbar-z-index: 1000; // reset; // 1050; // 9999;
-}
-
 :root {
     --tiki-list-top-margin: 0;
     --tiki-list-bottom-margin: 0;



View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/ec98dc96ccd3cc9a7aa970d16a61cf635b2f836c

-- 
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/ec98dc96ccd3cc9a7aa970d16a61cf635b2f836c
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help

_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.