diff --git a/docs/conf.py b/docs/conf.py index c08486bd..02dae39c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,7 +18,7 @@ project = "sunpy-sphinx-theme test docs" author = "The SunPy Community" -copyright = f"{datetime.datetime.now(datetime.UTC).year}, {author}" # NOQA: A001 +copyright = f"{datetime.datetime.now(datetime.timezone.utc).year}, {author}" # NOQA: A001 extensions = [ "sphinx_automodapi.automodapi", "sphinx_automodapi.smart_resolver", @@ -70,6 +70,9 @@ } html_theme = "sunpy" html_static_path = [str(_sunpy_static_path), "_static"] +html_js_files = [ + "js/submenu-toggle.js", +] html_extra_path = ["_static/img"] html_theme_options = { "footer_links": [ diff --git a/src/sunpy_sphinx_theme/__init__.py b/src/sunpy_sphinx_theme/__init__.py index 17ff3c33..835eb131 100644 --- a/src/sunpy_sphinx_theme/__init__.py +++ b/src/sunpy_sphinx_theme/__init__.py @@ -36,21 +36,37 @@ def default_navbar(): ( "Documentation", [ + # Core packages shown directly ("sunpy", "https://docs.sunpy.org/", 3), - ("ndcube", "https://docs.sunpy.org/projects/ndcube/", 3), + ("aiapy", "https://aiapy.readthedocs.io/", 3), ("drms", "https://docs.sunpy.org/projects/drms/", 3), - ("sunraster", "https://docs.sunpy.org/projects/sunraster/", 3), + ("dkist", "https://docs.dkist.nso.edu/projects/python-tools", 3), + ("ndcube", "https://docs.sunpy.org/projects/ndcube/", 3), + ("roentgen", "https://roentgen.readthedocs.io/", 3), ("sunkit-image", "https://docs.sunpy.org/projects/sunkit-image/", 3), - ("aiapy", "https://aiapy.readthedocs.io/", 3), + ("sunkit-instruments", "https://docs.sunpy.org/projects/sunkit-instruments/", 3), + ("sunkit-magex", "https://docs.sunpy.org/projects/sunkit-magex/", 3), ("sunpy-soar", "https://docs.sunpy.org/projects/soar/", 3), - ("roentgen", "https://roentgen.readthedocs.io/", 3), - ("sunkit-instruments ", "https://docs.sunpy.org/projects/sunkit-instruments/", 3), - ("demcmc", "https://demcmc.readthedocs.io/en/latest/", 3), - ("dkist", "https://docs.dkist.nso.edu/projects/python-tools", 3), ("solarmach", "https://solarmach.readthedocs.io/en/stable/", 3), - ("sunkit-magex", "https://docs.sunpy.org/projects/sunkit-magex/", 3), - ("pyflct", "https://pyflct.readthedocs.io/", 3), - ("radiospectra", "https://docs.sunpy.org/projects/radiospectra/", 3), + ("sunraster", "https://docs.sunpy.org/projects/sunraster/", 3), + # Provisional packages submenu + ( + "Provisional", + [ + ("pyflct", "https://pyflct.readthedocs.io/", 3), + ("radiospectra", "https://docs.sunpy.org/projects/radiospectra/", 3), + ], + ), + # Tools submenu + ( + "Tools", + [ + ("ablog", "https://ablog.readthedocs.io/en/stable/", 3), + ("demcmc", "https://demcmc.readthedocs.io/en/stable/", 3), + ("mpl-animators", "https://docs.sunpy.org/projects/mpl-animators/", 3), + ("streamtracer", "https://docs.sunpy.org/projects/streamtracer/", 3), + ], + ), ], ), ("Packages", "affiliated/", 2), diff --git a/src/sunpy_sphinx_theme/conf.py b/src/sunpy_sphinx_theme/conf.py index 81c1909e..40711db6 100644 --- a/src/sunpy_sphinx_theme/conf.py +++ b/src/sunpy_sphinx_theme/conf.py @@ -26,6 +26,7 @@ "svg_icon", ] + html_theme = "sunpy" html_theme_options = {} diff --git a/src/sunpy_sphinx_theme/theme/sunpy/components/navbar_center.html b/src/sunpy_sphinx_theme/theme/sunpy/components/navbar_center.html index 51f7136e..b543b599 100644 --- a/src/sunpy_sphinx_theme/theme/sunpy/components/navbar_center.html +++ b/src/sunpy_sphinx_theme/theme/sunpy/components/navbar_center.html @@ -8,31 +8,56 @@ {% set toggle="collapse" %} {% set list_class="collapse" %} {% endif %} +{% macro render_nav_item(item, depth=0) %} + {% set is_leaf = item[1] is string %} + {% set is_nested = item[1] is iterable and (item[1]|length > 0) and (item[1][0] is sequence or item[1][0] is mapping) %} + + {% if is_leaf %} + + + {% elif is_nested %} + {% set submenu_id = item[0]|replace(" ", "_")|lower %} + + {% endif %} +{% endmacro %} diff --git a/src/sunpy_sphinx_theme/theme/sunpy/static/js/submenu-toggle.js b/src/sunpy_sphinx_theme/theme/sunpy/static/js/submenu-toggle.js new file mode 100644 index 00000000..e5d24379 --- /dev/null +++ b/src/sunpy_sphinx_theme/theme/sunpy/static/js/submenu-toggle.js @@ -0,0 +1,54 @@ +document.addEventListener("DOMContentLoaded", function () { + // Setup toggle for nested submenus + const triggers = document.querySelectorAll( + ".dropdown-submenu > .dropdown-toggle", + ); + + triggers.forEach(function (trigger, i) { + trigger.dataset.bound = "true"; + trigger.addEventListener("click", function (e) { + if (trigger.dataset.processing === "true") return; + + trigger.dataset.processing = "true"; + setTimeout(() => delete trigger.dataset.processing, 100); + + e.preventDefault(); + e.stopPropagation(); + + const submenu = trigger.nextElementSibling; + + // Close other submenus at this level + const parent = trigger.closest(".dropdown-menu"); + if (parent) { + parent.querySelectorAll(".dropdown-menu.show").forEach(function (open) { + if (open !== submenu) { + open.classList.remove("show"); + } + }); + } + + submenu.classList.toggle("show"); + }); + }); + + // Close all open submenus when a top-level dropdown is closed + document.querySelectorAll(".dropdown").forEach(function (dropdown) { + dropdown.addEventListener("hide.bs.dropdown", function () { + dropdown + .querySelectorAll(".dropdown-menu.show") + .forEach(function (submenu) { + submenu.classList.remove("show"); + }); + }); + }); + + document.addEventListener("keydown", function (e) { + if (e.key === "Escape") { + document + .querySelectorAll(".dropdown-menu.show") + .forEach(function (submenu) { + submenu.classList.remove("show"); + }); + } + }); +}); diff --git a/src/sunpy_sphinx_theme/theme/sunpy/static/sunpy_style.css b/src/sunpy_sphinx_theme/theme/sunpy/static/sunpy_style.css index 268635e9..d7ca8c2e 100644 --- a/src/sunpy_sphinx_theme/theme/sunpy/static/sunpy_style.css +++ b/src/sunpy_sphinx_theme/theme/sunpy/static/sunpy_style.css @@ -412,3 +412,26 @@ html[data-theme="dark"] .search-button-field:hover { align-items: center; } } + +/* Position submenu beside parent */ +.dropdown-submenu { + position: relative; +} + +.navbar-nav .dropdown-item { + color: var(--sst-header-text); +} + +/* Initially hidden */ +.dropdown-submenu > .dropdown-menu { + position: absolute; + top: 0; + left: 100%; + display: none; + z-index: 1000; +} + +/* Show when toggled */ +.dropdown-submenu > .dropdown-menu.show { + display: block; +}