diff --git a/docs/source/_static/css/mobile-menu-fix.css b/docs/source/_static/css/mobile-menu-fix.css new file mode 100644 index 000000000..92a78ddcb --- /dev/null +++ b/docs/source/_static/css/mobile-menu-fix.css @@ -0,0 +1,25 @@ +/* Mobile menu fix: ensure overlay is clickable on iOS */ + +/* Raise the stacked navigation elements above possible overlays */ +.primary-toggle, +.secondary-toggle, +.mobile-menu-container .navbar, +.mobile-menu-container .navbar-collapse, +#pst-primary-sidebar-modal, +#pst-secondary-sidebar-modal { + z-index: 1500; + pointer-events: auto !important; +} + +/* + * Ensure the modal overlay allows pointer events to reach menu links. + * Both `pointer-events: auto` and a high `z-index` are necessary because: + * - Some themes/modal implementations use overlays that block pointer events or stack above menu links, + * making them unclickable (especially on iOS). + * - This rule ensures that the backdrop does not block interaction with menu links, + * and that the stacking order is correct so links remain accessible. + * If the theme/modal implementation changes, review whether this workaround is still needed. + */ +.pst-modal-backdrop { + pointer-events: auto !important; +} diff --git a/docs/source/_static/js/mobile-menu-fix.js b/docs/source/_static/js/mobile-menu-fix.js new file mode 100644 index 000000000..a879e5855 --- /dev/null +++ b/docs/source/_static/js/mobile-menu-fix.js @@ -0,0 +1,30 @@ +// Mobile menu fix: make touch interactions on mobile (iOS/Safari) reliably trigger +// the mobile navigation toggle. Minimal, defensive enhancement. +document.addEventListener('DOMContentLoaded', function () { + try { + const selectors = [ + '.primary-toggle', + '.secondary-toggle', + '[data-toggle="collapse"]', + '.navbar [aria-controls][aria-expanded]' + ].join(','); + const controls = Array.from(document.querySelectorAll(selectors)); + controls.forEach(el => { + if (el.__pymc_touchbound) return; + el.__pymc_touchbound = true; + el.addEventListener('touchstart', function (e) { + // iOS sometimes doesn't synthesize click events for transformed + // elements or elements in certain stacking contexts. Best-effort + // bridge: prevent default then dispatch a MouseEvent click. + try { + // e.preventDefault(); // Removed to allow scrolling on touch devices + this.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true })); + } catch (err) { + // ignore errors + } + }, { passive: false }); + }); + } catch (err) { + // swallow errors to avoid breaking docs + } +}); diff --git a/docs/source/conf.py b/docs/source/conf.py index 5b1ec7440..bf7c5b8e6 100755 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -390,7 +390,16 @@ def setup(app): # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ["../logos"] +html_static_path = [ + "../logos", + "_static", +] +html_css_files = [ + "css/mobile-menu-fix.css", +] +html_js_files = [ + "js/mobile-menu-fix.js", +] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied