-
Notifications
You must be signed in to change notification settings - Fork 10
Description
Creating a custom drop-down or fly-out menu in the Sphinx Alabaster sidebar requires a combination of custom sidebar templates, HTML/Jinja2, and custom CSS/JavaScript, as the Alabaster theme's built-in sidebar primarily uses standard Sphinx toctree and simple links.
Here's the general approach:
1. Create a Custom Sidebar Template
You need to define the structure of your drop-down menu using HTML.
- Create a
_templatesdirectory in your Sphinx source directory (whereconf.pyis located). - Inside
_templates, create a new file, for example,custom_dropdown.html.
In custom_dropdown.html, you'll use HTML/CSS/JavaScript to create the menu. A common pattern is to use an unordered list (<ul>) and apply CSS/JS for the expand/collapse behavior.
<div class="sphinxsidebarwrapper custom-sidebar-section">
<p class="caption">
<span class="caption-text">External Links</span>
</p>
<ul class="current">
<li class="toctree-l1">
<a class="reference internal" href="#">
**My Dropdown Menu**
</a>
<ul class="simple-dropdown-content">
<li class="toctree-l2">
<a class="reference internal" href="https://example.com/link1">
Link 1
</a>
</li>
<li class="toctree-l2">
<a class="reference internal" href="https://example.com/link2">
Link 2
</a>
</li>
</ul>
</li>
</ul>
</div>2. Configure Sphinx to Use the Custom Template
In your conf.py file, you need to tell Sphinx to include your custom template in the sidebar.
-
Define
templates_path:templates_path = ['_templates']
-
Update
html_sidebars: Include your new template (custom_dropdown.html) in the dictionary, along with the other Alabaster templates you want.html_sidebars = { '**': [ 'about.html', 'navigation.html', 'relations.html', 'searchbox.html', 'custom_dropdown.html', # <-- Add your custom file here 'donate.html', ] }
3. Implement Drop-down Behavior with CSS/JS
Since Alabaster is a minimal theme, it doesn't provide built-in drop-down functionality outside of the standard toctree. You'll need to add your own CSS and JavaScript.
3.1. Add Custom CSS (for basic styling)
You'll need CSS to hide the drop-down content by default and style the trigger.
-
Create a
_staticdirectory in your Sphinx source directory. -
Inside
_static, create a file likecustom.css./* _static/custom.css */ /* Hide the dropdown content initially */ .custom-sidebar-section .simple-dropdown-content { display: none; padding-left: 10px; /* Indent for visual hierarchy */ } /* Style the main menu item to look like a clickable header */ .custom-sidebar-section .toctree-l1 a.reference.internal { cursor: pointer; user-select: none; display: block; font-weight: bold; } /* Optionally, add a marker (like an arrow) to the header */ .custom-sidebar-section .toctree-l1 a.reference.internal::after { content: " \25B6"; /* Right triangle */ float: right; transition: transform 0.3s; } /* Rotate the marker when the content is open */ .custom-sidebar-section .toctree-l1.open > a.reference.internal::after { content: " \25BC"; /* Down triangle */ }
3.2. Add Custom JavaScript (for toggling)
You'll need JavaScript to toggle the display property of the drop-down content when the header is clicked.
-
In your
_staticdirectory, create a file likecustom.js./* _static/custom.js */ document.addEventListener('DOMContentLoaded', function() { // Select all custom dropdown headers const dropdownHeaders = document.querySelectorAll('.custom-sidebar-section .toctree-l1 > a.reference.internal'); dropdownHeaders.forEach(header => { header.addEventListener('click', function(event) { // Prevent the default link behavior if it's just a placeholder if (this.getAttribute('href') === '#') { event.preventDefault(); } // Get the parent <li> element const parentLi = this.closest('.toctree-l1'); // Toggle the 'open' class on the parent <li> parentLi.classList.toggle('open'); // Get the dropdown content (the nested <ul>) const content = parentLi.querySelector('.simple-dropdown-content'); // Toggle the display if (content.style.display === 'block') { content.style.display = 'none'; } else { content.style.display = 'block'; } }); }); });
3.3. Include CSS and JS in conf.py
In conf.py, you must register your static files so Sphinx includes them.
# Add your static paths
html_static_path = ['_static']
# Add your custom CSS and JS files
html_css_files = [
'custom.css',
]
html_js_files = [
'custom.js',
]⚠️ Alternative: Use sphinx-design
A much easier, modern, and theme-agnostic way to add drop-downs to your documentation (though typically used in the main page content, not the sidebar) is to use the sphinx-design extension.
You would install it: pip install sphinx-design and add it to your conf.py:
extensions = [
# ... other extensions
'sphinx_design',
]Then, in any .rst file (including a custom template, if you render it from a file):
.. dropdown:: My Dropdown Menu Title
This is the content that drops down.
* Link A
* Link BWhile designed for page content, you could potentially embed this reStructuredText block into a custom sidebar template that uses the rst directive, but the manual HTML/CSS/JS method offers more control over the final sidebar appearance in Alabaster.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status