From 6711e9b0399dee93ef4ce1b27e908172fa04801d Mon Sep 17 00:00:00 2001 From: AakashGC Date: Fri, 11 Mar 2022 17:31:36 +1100 Subject: [PATCH] ENH: Left navigation menu to collapse at the "part" level (#594) * restructuring html for parts * added styling and restructured bs html * adding list-caption class * not adding collapse parts for now * modified tests * pre-commit * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * opening captions explicitly * making parts text clickable * style for part label * pre-commit * corrections in __init__ and tests * adding docs for show_nav_levek: 0 * parts collapse only when show_nav_level: 0 * tests update * added test for sidebar nav_level0 * docs edit * parts chevron style * Update docs/user_guide/configuring.rst Co-authored-by: Chris Holdgraf * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * Update src/pydata_sphinx_theme/__init__.py Co-authored-by: Chris Holdgraf * tests and some code refactoring * Clarify this in the docs * Update docs/user_guide/configuring.rst * Cleaning up docs Co-authored-by: Chris Holdgraf Co-authored-by: Chris Holdgraf --- docs/user_guide/configuring.rst | 32 ++++++- src/pydata_sphinx_theme/__init__.py | 30 +++++++ .../assets/styles/index.scss | 84 +++++++++++-------- tests/test_build.py | 40 +++++++++ 4 files changed, 149 insertions(+), 37 deletions(-) diff --git a/docs/user_guide/configuring.rst b/docs/user_guide/configuring.rst index d678d2d51..2f4b83f99 100644 --- a/docs/user_guide/configuring.rst +++ b/docs/user_guide/configuring.rst @@ -245,8 +245,8 @@ override this behavior and control the sidebar on a per-page basis, use the .. _navigation-depth: -Navigation depth and collapsing of the sidebar -============================================== +Navigation depth and collapsing the sidebar +=========================================== By default, this theme enables to expand/collapse subsections in the left sidebar navigation (without actually navigating to the page itself), and this extends @@ -272,6 +272,34 @@ default, you can use the following configuration in ``conf.py``: This will make the first two navigations show up by default (AKA, top-level pages and their immediate children). +Collapse entire toctree captions / parts +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If your ``toctree`` elements have captions assigned to them (with ``:caption:``), you may +collapse navigation items so that only the caption is visible. Clicking on the +caption will display the items below. + +To enable this behavior, set the ``show_nav_level`` value to 0, like below: + +.. code:: python + + html_theme_options = { + "show_nav_level": 0 + } + + + + +You can only collapse your ``toctree`` items underneath their caption if a caption is defined for them! +If your ``toctree`` does not have a caption defined, then all of the pages underneath it will be displayed +(the same as the default theme behavior). See `the toctree documentation `_ +for more details. + +.. note:: + + In some Sphinx sites, the top-level ``toctree`` groupings make up "parts" in the documentation, with + each page beneath making up a "chapter". + .. _remove_toctrees: Selectively remove pages from your sidebar diff --git a/src/pydata_sphinx_theme/__init__.py b/src/pydata_sphinx_theme/__init__.py index f6e9367dc..f3473111d 100644 --- a/src/pydata_sphinx_theme/__init__.py +++ b/src/pydata_sphinx_theme/__init__.py @@ -147,6 +147,25 @@ def generate_nav_html(kind, startdepth=None, show_nav_level=1, **kwargs): for ul in soup("ul", recursive=False): ul.attrs["class"] = ul.attrs.get("class", []) + ["nav", "bd-sidenav"] + # Add collapse boxes for parts/captions. + # Wraps the TOC part in an extra
    to behave like chapters with toggles + # show_nav_level: 0 means make parts collapsible. + if show_nav_level == 0: + partcaptions = soup.find_all("p", attrs={"class": "caption"}) + if len(partcaptions): + new_soup = bs("
      ", "html.parser") + for caption in partcaptions: + # Assume that the next
        element is the TOC list + # for this part + for sibling in caption.next_siblings: + if sibling.name == "ul": + toclist = sibling + break + li = soup.new_tag("li", attrs={"class": "toctree-l0"}) + li.extend([caption, toclist]) + new_soup.ul.append(li) + soup = new_soup + # Add icons and labels for collapsible nested sections _add_collapse_checkboxes(soup) @@ -280,6 +299,12 @@ def _add_collapse_checkboxes(soup): # We check all "li" elements, to add a "current-page" to the correct li. classes = element.get("class", []) + # expanding the parent part explicitly, if present + if "current" in classes: + parentli = element.find_parent("li", class_="toctree-l0") + if parentli: + parentli.select("p.caption ~ input")[0].attrs["checked"] = "" + # Nothing more to do, unless this has "children" if not element.find("ul"): continue @@ -294,8 +319,12 @@ def _add_collapse_checkboxes(soup): # Add the "label" for the checkbox which will get filled. if soup.new_tag is None: continue + label = soup.new_tag("label", attrs={"for": checkbox_name}) label.append(soup.new_tag("i", attrs={"class": "fas fa-chevron-down"})) + if "toctree-l0" in classes: + # making label cover the whole caption text with css + label["class"] = "label-parts" element.insert(1, label) # Add the checkbox that's used to store expanded/collapsed state. @@ -308,6 +337,7 @@ def _add_collapse_checkboxes(soup): "name": checkbox_name, }, ) + # if this has a "current" class, be expanded by default # (by checking the checkbox) if "current" in classes: diff --git a/src/pydata_sphinx_theme/assets/styles/index.scss b/src/pydata_sphinx_theme/assets/styles/index.scss index be386c83f..00deae819 100644 --- a/src/pydata_sphinx_theme/assets/styles/index.scss +++ b/src/pydata_sphinx_theme/assets/styles/index.scss @@ -165,34 +165,6 @@ footer { } } -.bd-sidebar { - padding-top: 1em; - overflow-y: auto; - display: flex; - flex-direction: column; - - @include media-breakpoint-up(md) { - border-right: 1px solid rgba(0, 0, 0, 0.1); - - @supports (position: -webkit-sticky) or (position: sticky) { - position: -webkit-sticky; - position: sticky; - top: var(--pst-header-height); - z-index: 1000; - height: calc(100vh - var(--pst-header-height)); - } - } - - &.no-sidebar { - border-right: 0; - } - - .sidebar-end-items { - margin-top: auto; - margin-bottom: 1em; - } -} - .bd-links { padding-top: 1rem; padding-bottom: 1rem; @@ -346,7 +318,8 @@ nav.bd-links { /* Nav: hide second level (shown on .active) */ -.bd-toc .nav { +.bd-toc .nav, +.list-caption { .nav { display: none; @@ -522,8 +495,44 @@ nav.bd-links { } .bd-sidebar { + padding-top: 1em; + overflow-y: auto; + display: flex; + flex-direction: column; + + @include media-breakpoint-up(md) { + border-right: 1px solid rgba(0, 0, 0, 0.1); + + @supports (position: -webkit-sticky) or (position: sticky) { + position: -webkit-sticky; + position: sticky; + top: var(--pst-header-height); + z-index: 1000; + height: calc(100vh - var(--pst-header-height)); + } + } + + &.no-sidebar { + border-right: 0; + } + + .sidebar-end-items { + margin-top: auto; + margin-bottom: 1em; + } + .list-caption { + list-style: none; + padding-left: 0px; + } li { position: relative; + // If it has children, add a bit more padding to wrap the content to avoid + // overlapping with the