docs: Use sphinx-design for tabbed content

Change-Id: I71ce4721d02c51ac5fea5014a997c101215b5275
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/168341
Presubmit-Verified: CQ Bot Account <pigweed-scoped@luci-project-accounts.iam.gserviceaccount.com>
Commit-Queue: Auto-Submit <auto-submit@pigweed-service-accounts.iam.gserviceaccount.com>
Pigweed-Auto-Submit: Anthony DiGirolamo <tonymd@google.com>
Reviewed-by: Armando Montanez <amontanez@google.com>
diff --git a/docs/conf.py b/docs/conf.py
index ed42c6b..5bda6de 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -52,7 +52,6 @@
     'myst_parser',
     'breathe',
     'sphinx_copybutton',  # Copy-to-clipboard button on code blocks
-    'sphinx_tabs.tabs',
 ]
 
 myst_enable_extensions = [
diff --git a/docs/style_guide.rst b/docs/style_guide.rst
index 536e9de..f61e9df 100644
--- a/docs/style_guide.rst
+++ b/docs/style_guide.rst
@@ -1809,150 +1809,164 @@
 
 Grouping related content with tabs
 ==================================
-Use the ``tabs`` directive to group related content together. This feature is
-powered by `sphinx-tabs <https://sphinx-tabs.readthedocs.io>`_.
+Use the ``tab-set`` directive to group related content together. This feature is
+powered by `sphinx-design Tabs
+<https://sphinx-design.readthedocs.io/en/furo-theme/tabs.html>`_
 
 Tabs for code-only content
 --------------------------
 Use the ``tabs`` and ``code-tab`` directives together. Example:
 
-.. code:: none
+.. code-block:: rst
 
-   .. tabs::
+   .. tab-set-code::
 
-      .. code-tab:: c++
+      .. code-block:: c++
 
          // C++ code...
 
-      .. code-tab:: py
+      .. code-block:: python
 
          # Python code...
 
 Rendered output:
 
-.. tabs::
+.. tab-set-code::
 
-   .. code-tab:: c++
+   .. code-block:: c++
 
       // C++ code...
 
-   .. code-tab:: py
+   .. code-block:: python
 
       # Python code...
 
 Tabs for all other content
 --------------------------
-Use the ``tabs`` and ``group-tab`` directives together. Example:
+Use the ``tabs`` and ``tab-item`` directives together. Example:
 
-.. code:: none
+.. code-block:: rst
 
-   .. tabs::
+   .. tab-set::
 
-      .. group-tab:: Linux
+      .. tab-item:: Linux
 
          Linux instructions...
 
-      .. group-tab:: Windows
+      .. tab-item:: Windows
 
          Windows instructions...
 
 Rendered output:
 
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: Linux
+   .. tab-item:: Linux
 
       Linux instructions...
 
-   .. group-tab:: Windows
+   .. tab-item:: Windows
 
       Windows instructions...
 
 Tab synchronization
 -------------------
-Tabs are synchronized based on ``group-tab`` and ``code-tab`` values. Example:
+Tabs are synchronized in two ways:
 
-.. code:: none
+1. ``tab-set-code::`` ``code-block`` languages names.
+2. ``tab-item::`` ``:sync:`` values.
 
-   .. tabs::
+For Example:
 
-      .. code-tab:: c++
+.. code-block:: rst
+
+   .. tabs-set-code::
+
+      .. code-block:: c++
 
          // C++ code...
 
-      .. code-tab:: py
+      .. code-block:: py
 
          # Python code...
 
-   .. tabs::
+   .. tabs-set-code::
 
-      .. code-tab:: c++
+      .. code-block:: c++
 
          // More C++ code...
 
-      .. code-tab:: py
+      .. code-block:: py
 
          # More Python code...
 
-   .. tabs::
+   .. tab-set::
 
-      .. group-tab:: Linux
+      .. tab-item:: Linux
+         :sync: key1
 
          Linux instructions...
 
-      .. group-tab:: Windows
+      .. tab-item:: Windows
+         :sync: key2
 
          Windows instructions...
 
-   .. tabs::
+   .. tab-set::
 
-      .. group-tab:: Linux
+      .. tab-item:: Linux
+         :sync: key1
 
          More Linux instructions...
 
-      .. group-tab:: Windows
+      .. tab-item:: Windows
+         :sync: key2
 
          More Windows instructions...
 
 Rendered output:
 
-.. tabs::
+.. tab-set-code::
 
-   .. code-tab:: c++
+   .. code-block:: c++
 
       // C++ code...
 
-   .. code-tab:: py
+   .. code-block:: py
 
       # Python code...
 
-.. tabs::
+.. tab-set-code::
 
-   .. code-tab:: c++
+   .. code-block:: c++
 
       // More C++ code...
 
-   .. code-tab:: py
+   .. code-block:: py
 
       # More Python code...
 
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: Linux
+   .. tab-item:: Linux
+      :sync: key1
 
       Linux instructions...
 
-   .. group-tab:: Windows
+   .. tab-item:: Windows
+      :sync: key2
 
       Windows instructions...
 
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: Linux
+   .. tab-item:: Linux
+      :sync: key1
 
       More Linux instructions...
 
-   .. group-tab:: Windows
+   .. tab-item:: Windows
+      :sync: key2
 
       More Windows instructions...
 
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/constraint.list b/pw_env_setup/py/pw_env_setup/virtualenv_setup/constraint.list
index 152f2a6..6a35805 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/constraint.list
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/constraint.list
@@ -81,7 +81,6 @@
 sphinx-copybutton==0.5.1
 sphinx-design==0.5.0
 sphinx-rtd-theme==1.2.0
-sphinx-tabs==3.4.1
 toml==0.10.2
 tomlkit==0.11.6
 traitlets==5.1.1
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/pigweed_upstream_requirements.txt b/pw_env_setup/py/pw_env_setup/virtualenv_setup/pigweed_upstream_requirements.txt
index 3db53bf..61cd918 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/pigweed_upstream_requirements.txt
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/pigweed_upstream_requirements.txt
@@ -17,7 +17,6 @@
 beautifulsoup4==4.12.2
 furo @ https://github.com/chadnorvell/furo/releases/download/2023.03.27/furo-2023.3.27.dev1-py3-none-any.whl
 sphinx-copybutton==0.5.1
-sphinx-tabs==3.4.1
 myst-parser==0.18.1
 breathe==4.34.0
 kconfiglib==14.1.0
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_darwin_lock.txt b/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_darwin_lock.txt
index 27c235f..dccfac3 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_darwin_lock.txt
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_darwin_lock.txt
@@ -294,7 +294,6 @@
     #   myst-parser
     #   sphinx
     #   sphinx-rtd-theme
-    #   sphinx-tabs
 executing==1.2.0 \
     --hash=sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc \
     --hash=sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107
@@ -784,7 +783,6 @@
     #   ipython
     #   ptpython
     #   sphinx
-    #   sphinx-tabs
 pylint==2.17.5 \
     --hash=sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413 \
     --hash=sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252
@@ -906,7 +904,6 @@
     #   sphinx-copybutton
     #   sphinx-design
     #   sphinx-rtd-theme
-    #   sphinx-tabs
     #   sphinxcontrib-jquery
 sphinx-argparse==0.4.0 \
     --hash=sha256:73bee01f7276fae2bf621ccfe4d167af7306e7288e3482005405d9f826f9b037 \
@@ -930,10 +927,6 @@
     --hash=sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8 \
     --hash=sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2
     # via -r /python/gen/pw_env_setup/pigweed_build_venv/compiled_requirements.txt
-sphinx-tabs==3.4.1 \
-    --hash=sha256:7cea8942aeccc5d01a995789c01804b787334b55927f29b36ba16ed1e7cb27c6 \
-    --hash=sha256:d2a09f9e8316e400d57503f6df1c78005fdde220e5af589cc79d493159e1b832
-    # via -r /python/gen/pw_env_setup/pigweed_build_venv/compiled_requirements.txt
 sphinxcontrib-applehelp==1.0.2 \
     --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \
     --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_linux_lock.txt b/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_linux_lock.txt
index c7186b7..1046928 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_linux_lock.txt
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_linux_lock.txt
@@ -288,7 +288,6 @@
     #   myst-parser
     #   sphinx
     #   sphinx-rtd-theme
-    #   sphinx-tabs
 executing==1.2.0 \
     --hash=sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc \
     --hash=sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107
@@ -778,7 +777,6 @@
     #   ipython
     #   ptpython
     #   sphinx
-    #   sphinx-tabs
 pylint==2.17.5 \
     --hash=sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413 \
     --hash=sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252
@@ -900,7 +898,6 @@
     #   sphinx-copybutton
     #   sphinx-design
     #   sphinx-rtd-theme
-    #   sphinx-tabs
     #   sphinxcontrib-jquery
 sphinx-argparse==0.4.0 \
     --hash=sha256:73bee01f7276fae2bf621ccfe4d167af7306e7288e3482005405d9f826f9b037 \
@@ -924,10 +921,6 @@
     --hash=sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8 \
     --hash=sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2
     # via -r /python/gen/pw_env_setup/pigweed_build_venv/compiled_requirements.txt
-sphinx-tabs==3.4.1 \
-    --hash=sha256:7cea8942aeccc5d01a995789c01804b787334b55927f29b36ba16ed1e7cb27c6 \
-    --hash=sha256:d2a09f9e8316e400d57503f6df1c78005fdde220e5af589cc79d493159e1b832
-    # via -r /python/gen/pw_env_setup/pigweed_build_venv/compiled_requirements.txt
 sphinxcontrib-applehelp==1.0.2 \
     --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \
     --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58
diff --git a/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_windows_lock.txt b/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_windows_lock.txt
index 6723408..79b30b8 100644
--- a/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_windows_lock.txt
+++ b/pw_env_setup/py/pw_env_setup/virtualenv_setup/upstream_requirements_windows_lock.txt
@@ -298,7 +298,6 @@
     #   myst-parser
     #   sphinx
     #   sphinx-rtd-theme
-    #   sphinx-tabs
 executing==1.2.0 \
     --hash=sha256:0314a69e37426e3608aada02473b4161d4caf5a4b244d1d0c48072b8fee7bacc \
     --hash=sha256:19da64c18d2d851112f09c287f8d3dbbdf725ab0e569077efb6cdcbd3497c107
@@ -776,7 +775,6 @@
     #   ipython
     #   ptpython
     #   sphinx
-    #   sphinx-tabs
 pylint==2.17.5 \
     --hash=sha256:73995fb8216d3bed149c8d51bba25b2c52a8251a2c8ac846ec668ce38fab5413 \
     --hash=sha256:f7b601cbc06fef7e62a754e2b41294c2aa31f1cb659624b9a85bcba29eaf8252
@@ -904,7 +902,6 @@
     #   sphinx-copybutton
     #   sphinx-design
     #   sphinx-rtd-theme
-    #   sphinx-tabs
     #   sphinxcontrib-jquery
 sphinx-argparse==0.4.0 \
     --hash=sha256:73bee01f7276fae2bf621ccfe4d167af7306e7288e3482005405d9f826f9b037 \
@@ -928,10 +925,6 @@
     --hash=sha256:a0d8bd1a2ed52e0b338cbe19c4b2eef3c5e7a048769753dac6a9f059c7b641b8 \
     --hash=sha256:f823f7e71890abe0ac6aaa6013361ea2696fc8d3e1fa798f463e82bdb77eeff2
     # via -r \python\gen\pw_env_setup\pigweed_build_venv\compiled_requirements.txt
-sphinx-tabs==3.4.1 \
-    --hash=sha256:7cea8942aeccc5d01a995789c01804b787334b55927f29b36ba16ed1e7cb27c6 \
-    --hash=sha256:d2a09f9e8316e400d57503f6df1c78005fdde220e5af589cc79d493159e1b832
-    # via -r \python\gen\pw_env_setup\pigweed_build_venv\compiled_requirements.txt
 sphinxcontrib-applehelp==1.0.2 \
     --hash=sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a \
     --hash=sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58
diff --git a/pw_hdlc/api.rst b/pw_hdlc/api.rst
index 18ed106..c90df8b 100644
--- a/pw_hdlc/api.rst
+++ b/pw_hdlc/api.rst
@@ -17,9 +17,9 @@
 The Encoder API provides a single function that encodes data as an HDLC
 unnumbered information frame.
 
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: C++
+   .. tab-item:: C++
 
       .. doxygenfunction:: pw::hdlc::WriteUIFrame(uint64_t address, ConstByteSpan data, stream::Writer &writer)
 
@@ -44,7 +44,7 @@
            }
          }
 
-   .. group-tab:: Python
+   .. tab-item:: Python
 
       .. automodule:: pw_hdlc.encode
          :members:
@@ -65,7 +65,7 @@
          address = 123
          ser.write(encode.ui_frame(address, b'your data here!'))
 
-   .. group-tab:: TypeScript
+   .. tab-item:: TypeScript
 
       The Encoder class provides a way to build complete, escaped HDLC UI frames.
 
@@ -82,9 +82,9 @@
 =======
 
 
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: C++
+   .. tab-item:: C++
 
       .. doxygenclass:: pw::hdlc::Decoder
          :members:
@@ -114,7 +114,7 @@
            }
          }
 
-   .. group-tab:: Python
+   .. tab-item:: Python
 
       .. autoclass:: pw_hdlc.decode.FrameDecoder
          :members:
@@ -149,7 +149,7 @@
         :members:
         :noindex:
 
-   .. group-tab:: TypeScript
+   .. tab-item:: TypeScript
 
       The decoder class unescapes received bytes and adds them to a buffer. Complete,
       valid HDLC frames are yielded as they are received.
@@ -172,9 +172,9 @@
 RPC
 ===
 
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: C++
+   .. tab-item:: C++
 
       .. autoclass:: pw_hdlc.rpc.HdlcRpcClient
          :members:
diff --git a/pw_hdlc/guide.rst b/pw_hdlc/guide.rst
index f259f48..2029acf 100644
--- a/pw_hdlc/guide.rst
+++ b/pw_hdlc/guide.rst
@@ -13,9 +13,9 @@
 --------
 Encoding
 --------
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: C++
+   .. tab-item:: C++
 
       ..
         TODO(b/279648188): Share this code between api.rst and guide.rst.
@@ -37,7 +37,7 @@
            }
          }
 
-   .. group-tab:: Python
+   .. tab-item:: Python
 
       ..
         TODO(b/279648188): Share this code between api.rst and guide.rst.
@@ -55,9 +55,9 @@
 
 Allocating buffers when encoding
 ================================
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: C++
+   .. tab-item:: C++
 
       Since HDLC's encoding overhead changes with payload size and what data is being
       encoded, this module provides helper functions that are useful for determining
@@ -86,9 +86,9 @@
 --------
 Decoding
 --------
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: C++
+   .. tab-item:: C++
 
       ..
         TODO(b/279648188): Share this code between api.rst and guide.rst.
@@ -114,7 +114,7 @@
            }
          }
 
-   .. group-tab:: Python
+   .. tab-item:: Python
 
       ..
         TODO(b/279648188): Share this code between api.rst and guide.rst.
@@ -135,9 +135,9 @@
 
 Allocating buffers when decoding
 ================================
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: C++
+   .. tab-item:: C++
 
       The HDLC ``Decoder`` has its own helper for allocating a buffer since it doesn't
       need the entire escaped frame in-memory to decode, and therefore has slightly
diff --git a/pw_string/docs.rst b/pw_string/docs.rst
index c74d69d..1287e84 100644
--- a/pw_string/docs.rst
+++ b/pw_string/docs.rst
@@ -92,9 +92,9 @@
 Getting Started
 ---------------
 
-.. tabs::
+.. tab-set::
 
-   .. group-tab:: GN
+   .. tab-item:: GN
 
       Add ``$dir_pw_string`` to the ``deps`` list in your ``pw_executable()``
       build target:
@@ -113,7 +113,7 @@
       See `//source/BUILD.gn <https://pigweed.googlesource.com/pigweed/sample_project/+/refs/heads/main/source/BUILD.gn>`_
       in the Pigweed Sample Project for an example.
 
-   .. group-tab:: Zephyr
+   .. tab-item:: Zephyr
 
       Add ``CONFIG_PIGWEED_STRING=y`` to the Zephyr project's configuration.