Add option to show Tabs within Table of Contents
Description
I created the following [1] issue over on the mkdocs-material repo, but it was suggested that I create an issue here, as it is out of scope for them. My request is that: I'm wondering, since Tabs work as URL slugs, is it possible to add them to the page Table of Contents, and, if possible switch to the tab? Obviously, some users may not want this, so having it as an option would probably be ideal, and/or if they are under a heading in the document, have them nest under that heading in the Table of Contents.
[1] https://github.com/squidfunk/mkdocs-material/issues/8400
Benefits
This should improve the navigation of a document, especially a longer one, that may have multiple tabs. Tabs allow a document to not appear as long when compared to a document that doesn't have the same information within tabs, but the navigation ability of the document is lost when the information is placed into tabs.
Solution Idea
Here is a visual of what I'm thinking (I would like to see the two tabs under 'Installation method' appear under that entry in the Table of Contents list):
FWIW, I did ask Copilot if this was possible, and it suggested this change - but I have ZERO clue if this would even work, or be the change(s) needed; but sharing in case it helps:
Here’s a concrete proposal you could submit as a patch/PR against
pymdown-extensionsto make tab labels show up in the MkDocs‐Material TOC. The idea is to let users opt in to “exporting” each tab title as a hidden heading node in the Markdown AST, so that the standardtocextension picks it up automatically.
1. Add a new config flag
In
TabbedTreeprocessor.__init__, add:def __init__(self, md, config): super().__init__(md) self.alternate = config['alternate_style'] self.slugify = config['slugify'] self.combine_header_slug = config['combine_header_slug'] self.sep = config["separator"] + self.add_tabs_to_toc = config.get("add_tabs_to_toc", False)Also surface it in
TabExtension.config:self.config = { 'alternate_style': [False, "…"], 'slugify': [0, "…"], 'combine_header_slug': [False, "…"], 'separator': ['-', "…"], + 'add_tabs_to_toc': [False, "Add each tab title as an Hn for TOC generation"] }
2. Inject a hidden heading for each tab
In
TabbedTreeprocessor.run(self, doc), right after you assigninpt.attrib["id"] = slugandlabel.attrib["for"] = slug, insert:inpt.attrib["id"] = slug label.attrib["for"] = slug + if self.add_tabs_to_toc: + # Create an H3 element (or choose level dynamically) + header = etree.Element("h3", {"id": slug}) + # Use the label text as the heading content + header.text = innertext + # Insert it immediately after the label, so it appears + # before the content block in the AST + parent = el # 'el' is the <div class="tabbed-set"> + # find where the label lives, then insert after it + for idx, child in enumerate(list(parent)): + if child is label: + parent.insert(idx + 1, header) + breakWhat this does:
- When
add_tabs_to_toc=True, each tab label gets a real<h3 id="…">My Tab</h3>injected into the HTML tree.- The existing MkDocs Material TOC pipeline will now pick up those headings and insert them into the sidebar nav automatically.
- You don’t need any custom JavaScript hacks, nor special Markdown slugs everywhere—you just flip on the option in your
mkdocs.yml:markdown_extensions: - pymdownx.blocks.tab: alternate_style: true combine_header_slug: false separator: '-' add_tabs_to_toc: trueThen rebuild your docs, and you’ll find each tab title nested right under its parent section in the “On this page” TOC.
Feel free to tweak the heading level (H3) or insertion point, but this minimal patch should give you exactly the up‐the‐pipeline support you’ve been craving.
This may be beyond the scope of this project. This AI suggestion looks like it is assuming that it can just insert a header into the tab and it won't cause any issues. I don't know if this is true or not.
I also don't know if this is a direction we want to go in. I disagree that tabs should be added to the TOC, I think this desire is extremely niche. I think those who may desire this would be in a very small minority.
When I have some time to consider this more seriously, I'll make a decision.
Thank you for the prompt response. Again, take the AI suggestion with a grain of salt, or not at all - I have no idea if it's even close to a solution.
I/we (working on RaspAP documentation at present) look forward to your decision. There are a number of discussions/issues in the mkdocs-material repo (some links below) that ask about adding headings that are within tabs to show in the Table of Contents; so I think this is a decent compromise that would likely be welcomed by many that didn't know it was something they wanted. Knowing what information is in a document is pretty priceless, and this would only help that. Let's say we have a document that doesn't use tabs, and is say 1,000 lines long, with 50 entries in the TOC. If we re-organize that document into tabs making it only a few hundred lines long, a good majority of those headings go away (and this won't fix that), but at least the parent demarc'ing tabs could be in the TOC.
Links to a handful of the issues: https://github.com/squidfunk/mkdocs-material/issues/3879 https://github.com/squidfunk/mkdocs-material/discussions/6217 https://github.com/squidfunk/mkdocs-material/issues/4828 https://github.com/squidfunk/mkdocs-material/issues/3376 https://github.com/squidfunk/mkdocs-material/issues/3527 https://github.com/squidfunk/mkdocs-material/issues/3376 https://github.com/squidfunk/mkdocs-material/discussions/3981
It may be decided that this is something a TOC extension should do. I'm not sure I want to maintain an alternative TOC here, so keep that in mind. That's why I think it might be out of scope, but I'll wait to reserve judgement once I can properly investigate whether I'm interested in hacking something directly into tabs.
Fully understood - I'm new to all of this, and am not sure where this belongs, so feel free to point me in a better direction if needed. Thank you again for your responses.