Sphinx docs: How to activate tabs for your OS

hugovk

Hugo van Kemenade

Posted on April 2, 2024

Sphinx docs: How to activate tabs for your OS

On the Python Developer's Guide and Pillow documentation we have some pages with tabs for different operating systems:

Screenshot showing instructions how to build Python. Some parts have Unix, macOS and Windows tabs. The macOS tab is active, showing a configure command to run in your terminal. Underneath is a second step with its own tabs and a macOS command. There's a macOS-specific note underneath.

It's possible to add some JavaScript so that the matching tab is activated based on the visitor's operating system.

Here's how!

Sphinx Inline Tabs

First add the Sphinx Inline Tabs extension to your docs' requirements.txt:

# requirements.txt
sphinx-inline-tabs>=2023.4.21
Enter fullscreen mode Exit fullscreen mode

JavaScript

Next, add activate_tab.js to your _static/ directory:

// activate_tab.js
// Based on https://stackoverflow.com/a/38241481/724176
function getOS() {
  const userAgent = window.navigator.userAgent,
    platform =
      window.navigator?.userAgentData?.platform || window.navigator.platform,
    macosPlatforms = ["macOS", "Macintosh", "MacIntel", "MacPPC", "Mac68K"],
    windowsPlatforms = ["Win32", "Win64", "Windows", "WinCE"],
    iosPlatforms = ["iPhone", "iPad", "iPod"];

  if (macosPlatforms.includes(platform)) {
    return "macOS";
  } else if (iosPlatforms.includes(platform)) {
    return "iOS";
  } else if (windowsPlatforms.includes(platform)) {
    return "Windows";
  } else if (/Android/.test(userAgent)) {
    return "Android";
  } else if (/Linux/.test(platform)) {
    return "Unix";
  }

  return "unknown";
}

function activateTab(tabName) {
  // Find all label elements containing the specified tab name
  const labels = document.querySelectorAll(".tab-label");

  labels.forEach((label) => {
    if (label.textContent.includes(tabName)) {
      // Find the associated input element using the 'for' attribute
      const tabInputId = label.getAttribute("for");
      const tabInput = document.getElementById(tabInputId);

      // Check if the input element exists before attempting to set the "checked" attribute
      if (tabInput) {
        // Activate the tab by setting its "checked" attribute to true
        tabInput.checked = true;
      }
    }
  });
}
Enter fullscreen mode Exit fullscreen mode

conf.py

Add the extension and JavaScript to your conf.py:

# conf.py
extensions = [
    "sphinx_inline_tabs",
]

html_js_files = [
    "activate_tab.js",
]
Enter fullscreen mode Exit fullscreen mode

reStructuredText

Almost there!

Add tabs to the reStructuredText files.

For example, here we have three different commands; one for Unix, one for macOS, and one for Windows:

.. tab:: Unix

    .. code-block:: shell

        ./python -m test -h

.. tab:: macOS

    .. code-block:: shell

        ./python.exe -m test -h

.. tab:: Windows

    .. code-block:: dosbatch

        .\python.bat -m test -h
Enter fullscreen mode Exit fullscreen mode

Finally, add the JavaScript to the same reST page to activate the correct tab:

.. raw:: html

    <script>
    document.addEventListener('DOMContentLoaded', function() {
      activateTab(getOS());
    });
    </script>
Enter fullscreen mode Exit fullscreen mode

You can see the results here. When the page loads, the browser finds the browser name, and activates the tabs with a matching name.

If you have many sets of tabs on a page, the corresponding OS tab will be activated for all. And if you click on another OS tab, all the others with the same name are activated.

Happy tabbing!


Header photo: "The Great Pyramid and the Sphinx" by National Galleries of Scotland, with no known copyright restrictions.

💖 💪 🙅 🚩
hugovk
Hugo van Kemenade

Posted on April 2, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related