Repository: nodejs/nodejs.dev
Pull request #2646 (2022-08-16 20:04:06)

fix(ssr): fixes some of the ssr errors caused by not using hooks
<!--
Please read the [Code of Conduct](https://github.com/nodejs/nodejs.dev/blob/main/CODE_OF_CONDUCT.md) and the [Contributing Guidelines](https://github.com/nodejs/nodejs.dev/blob/main/CONTRIBUTING.md) before opening a pull request.
-->

### Check List

<!--
ATTENTION
Please follow this check list to ensure that you've followed all items before opening this PR
-->

- [x] I have read the [Contributing Guidelines](https://github.com/nodejs/nodejs.dev/blob/main/CONTRIBUTING.md) and made commit messages that follow the guideline.
- [x] I have run `npm run lint:js -- --fix` and/or `npm run lint:md -- --fix` for my JavaScript and/or Markdown changes.
  - This is important as most of the cases your code changes might not be correctly linted
- [x] I have run `npm run test` to check if all tests are passing, and/or `npm run test -- -u` to update snapshots if I created and/or updated React Components.
- [x] I have checked that the build works locally and that `npm run build` work fine.
- [x] I've covered new added functionality with unit tests if necessary.

## Description

This PR fixes some SSR issues caused by some functions that require environment-based data to be called outside of hooks.

**Note.:** We should be more careful when writing code here and thinking about interoperability between SSR/Browser versions of the code, as is there are SSR mismatches on the initial render, the cache will not be used :(


github-actions[bot]: Please find a preview at: https://staging.nodejs.dev/2646/
codecov-commenter: # [Codecov](https://codecov.io/gh/nodejs/nodejs.dev/pull/2646?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#2646](https://codecov.io/gh/nodejs/nodejs.dev/pull/2646?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (94ea929) into [main](https://codecov.io/gh/nodejs/nodejs.dev/commit/48c5dd39a05aacc0bbf65b284e153393b8399221?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (48c5dd3) will **not change** coverage.
> The diff coverage is `100.00%`.

```diff
@@           Coverage Diff           @@
##             main    #2646   +/-   ##
=======================================
  Coverage   84.19%   84.19%           
=======================================
  Files         101      102    +1     
  Lines        1120     1120           
  Branches      313      308    -5     
=======================================
  Hits          943      943           
  Misses        171      171           
  Partials        6        6           
```


| [Impacted Files](https://codecov.io/gh/nodejs/nodejs.dev/pull/2646?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Coverage Δ | |
|---|---|---|
| [src/components/Header/index.tsx](https://codecov.io/gh/nodejs/nodejs.dev/pull/2646/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2NvbXBvbmVudHMvSGVhZGVyL2luZGV4LnRzeA==) | `94.44% <100.00%> (-0.56%)` | :arrow_down: |
| [src/components/Hero/index.tsx](https://codecov.io/gh/nodejs/nodejs.dev/pull/2646/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2NvbXBvbmVudHMvSGVyby9pbmRleC50c3g=) | `100.00% <100.00%> (ø)` | |
| [src/components/InstallTabs/index.tsx](https://codecov.io/gh/nodejs/nodejs.dev/pull/2646/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2NvbXBvbmVudHMvSW5zdGFsbFRhYnMvaW5kZXgudHN4) | `100.00% <100.00%> (ø)` | |
| [src/hooks/useDetectOs.ts](https://codecov.io/gh/nodejs/nodejs.dev/pull/2646/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL2hvb2tzL3VzZURldGVjdE9zLnRz) | `100.00% <100.00%> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None)

ovflowd: I'm merging this now as this is an important bug fix.

Patch:
diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx
index 563676ca..b1b61ddc 100644
--- a/src/components/Header/index.tsx
+++ b/src/components/Header/index.tsx
@@ -95,22 +95,20 @@ const Header = (): JSX.Element => {
               <SearchBar />
             </li>
             <li className="nav__tabs nav__tabs--right">
-              {theme && (
-                <button
-                  type="button"
-                  onClick={() => handleThemeOnClick()}
-                  className="dark-mode-toggle"
-                  onKeyPress={() => handleThemeOnClick(true)}
-                >
-                  <span className="sr-only">Toggle Dark Mode</span>
-                  <i className="material-icons light-mode-only theme-buttons">
-                    nights_stay
-                  </i>
-                  <i className="material-icons dark-mode-only theme-buttons">
-                    wb_sunny
-                  </i>
-                </button>
-              )}
+              <button
+                type="button"
+                onClick={() => handleThemeOnClick()}
+                className="dark-mode-toggle"
+                onKeyPress={() => handleThemeOnClick(true)}
+              >
+                <span className="sr-only">Toggle Dark Mode</span>
+                <i className="material-icons light-mode-only theme-buttons">
+                  nights_stay
+                </i>
+                <i className="material-icons dark-mode-only theme-buttons">
+                  wb_sunny
+                </i>
+              </button>
             </li>
 
             <li className="nav__tabs">
diff --git a/src/components/Hero/index.tsx b/src/components/Hero/index.tsx
index 9c1a8385..449e0318 100644
--- a/src/components/Hero/index.tsx
+++ b/src/components/Hero/index.tsx
@@ -1,8 +1,7 @@
 import React from 'react';
 import { LocalizedLink as Link } from 'gatsby-theme-i18n';
-import { detectOS } from '../../util/detectOS';
-import downloadUrlByOS from '../../util/downloadUrlByOS';
-import { NodeReleaseLTSVersion } from '../../types';
+import { useDetectOs } from '../../hooks/useDetectOs';
+import type { NodeReleaseLTSVersion } from '../../types';
 
 import './Hero.scss';
 
@@ -17,20 +16,15 @@ const Hero = ({
   subTitle,
   nodeReleasesLTSVersion,
 }: Props): JSX.Element => {
-  const userOS = detectOS();
+  const { getDownloadLink } = useDetectOs();
+
   const [currentRelease, ...releases] = nodeReleasesLTSVersion;
 
   // find first lts version (first found is last LTS)
   const lastLTSRelease = releases.find((release): boolean => !!release.lts);
 
-  const ltsVersionUrl = downloadUrlByOS(
-    userOS,
-    lastLTSRelease ? lastLTSRelease.version : ''
-  );
-  const currentVersionUrl = downloadUrlByOS(
-    userOS,
-    currentRelease ? currentRelease.version : ''
-  );
+  const ltsVersionUrl = getDownloadLink(lastLTSRelease?.version || '');
+  const currentVersionUrl = getDownloadLink(currentRelease?.version || '');
 
   return (
     <div className="home-page-hero">
diff --git a/src/components/InstallTabs/index.tsx b/src/components/InstallTabs/index.tsx
index 3dd6a1e9..f00839f6 100644
--- a/src/components/InstallTabs/index.tsx
+++ b/src/components/InstallTabs/index.tsx
@@ -1,14 +1,63 @@
-import React from 'react';
+import React, { useMemo } from 'react';
 import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
-import { detectOS, UserOS } from '../../util/detectOS';
-import './InstallTabs.scss';
-
+import { UserOS } from '../../util/detectOS';
+import { useDetectOs } from '../../hooks/useDetectOs';
 import WindowsPanel from './WindowsPanel';
 import MacOSPanel from './MacOSPanel';
 import LinuxPanel from './LinuxPanel';
 
+import './InstallTabs.scss';
+
+const getOSPanel = (userOS: UserOS): JSX.Element => {
+  switch (userOS) {
+    case UserOS.MAC:
+      return (
+        <>
+          <TabPanel>
+            <MacOSPanel />
+          </TabPanel>
+          <TabPanel>
+            <WindowsPanel />
+          </TabPanel>
+          <TabPanel>
+            <LinuxPanel />
+          </TabPanel>
+        </>
+      );
+    case UserOS.LINUX:
+    case UserOS.UNIX:
+      return (
+        <>
+          <TabPanel>
+            <LinuxPanel />
+          </TabPanel>
+          <TabPanel>
+            <MacOSPanel />
+          </TabPanel>
+          <TabPanel>
+            <WindowsPanel />
+          </TabPanel>
+        </>
+      );
+    default:
+      return (
+        <>
+          <TabPanel>
+            <WindowsPanel />
+          </TabPanel>
+          <TabPanel>
+            <MacOSPanel />
+          </TabPanel>
+          <TabPanel>
+            <LinuxPanel />
+          </TabPanel>
+        </>
+      );
+  }
+};
+
 const InstallTabs = (): JSX.Element | null => {
-  const userOS = detectOS();
+  const { userOS } = useDetectOs();
 
   const os = {
     win: 'Windows (Chocolatey)',
@@ -22,57 +71,12 @@ const InstallTabs = (): JSX.Element | null => {
     LINUX: [os.linux, os.mac, os.win],
     UNIX: [os.linux, os.mac, os.win],
     UNKNOWN: [os.win, os.mac, os.linux],
+    MOBILE: [],
   };
 
-  function panelSwitch(): JSX.Element {
-    switch (userOS) {
-      case UserOS.MAC:
-        return (
-          <>
-            <TabPanel>
-              <MacOSPanel />
-            </TabPanel>
-            <TabPanel>
-              <WindowsPanel />
-            </TabPanel>
-            <TabPanel>
-              <LinuxPanel />
-            </TabPanel>
-          </>
-        );
-      case UserOS.LINUX:
-      case UserOS.UNIX:
-        return (
-          <>
-            <TabPanel>
-              <LinuxPanel />
-            </TabPanel>
-            <TabPanel>
-              <MacOSPanel />
-            </TabPanel>
-            <TabPanel>
-              <WindowsPanel />
-            </TabPanel>
-          </>
-        );
-      default:
-        return (
-          <>
-            <TabPanel>
-              <WindowsPanel />
-            </TabPanel>
-            <TabPanel>
-              <MacOSPanel />
-            </TabPanel>
-            <TabPanel>
-              <LinuxPanel />
-            </TabPanel>
-          </>
-        );
-    }
-  }
+  const panelSwitch = useMemo(() => getOSPanel(userOS), [userOS]);
 
-  return installTabSystems[userOS] !== undefined ? (
+  return (
     <div className="install">
       <Tabs>
         <div className="install__header">
@@ -90,10 +94,10 @@ const InstallTabs = (): JSX.Element | null => {
             <Tab key={system.toString()}>{system}</Tab>
           ))}
         </TabList>
-        {panelSwitch()}
+        {panelSwitch}
       </Tabs>
     </div>
-  ) : null;
+  );
 };
 
 export default InstallTabs;
diff --git a/src/hooks/useDetectOs.ts b/src/hooks/useDetectOs.ts
new file mode 100644
index 00000000..704c9b04
--- /dev/null
+++ b/src/hooks/useDetectOs.ts
@@ -0,0 +1,14 @@
+import { useEffect, useState } from 'react';
+import { detectOS, UserOS } from '../util/detectOS';
+import downloadUrlByOS from '../util/downloadUrlByOS';
+
+export const useDetectOs = () => {
+  const [userOS, setUserOS] = useState<UserOS>(UserOS.UNKNOWN);
+
+  useEffect(() => setUserOS(detectOS), []);
+
+  return {
+    userOS,
+    getDownloadLink: (version: string) => downloadUrlByOS(userOS, version),
+  };
+};


Test patch:
diff --git a/src/components/InstallTabs/__tests__/__snapshots__/index.tsx.snap b/src/components/InstallTabs/__tests__/__snapshots__/index.tsx.snap
index f5a31eca..f0794723 100644
--- a/src/components/InstallTabs/__tests__/__snapshots__/index.tsx.snap
+++ b/src/components/InstallTabs/__tests__/__snapshots__/index.tsx.snap
@@ -688,7 +688,161 @@ exports[`Tests for InstallTabs component renders correctly for macOS 1`] = `
 </div>
 `;
 
-exports[`Tests for InstallTabs component renders correctly for mobile 1`] = `<div />`;
+exports[`Tests for InstallTabs component renders correctly for mobile 1`] = `
+<div>
+  <div
+    class="install"
+  >
+    <div
+      class="react-tabs"
+      data-rttabs="true"
+    >
+      <div
+        class="install__header"
+      >
+        <div
+          class="install__header-circles"
+        >
+          <div
+            class="install__header-grey-circle"
+          />
+          <div
+            class="install__header-grey-circle"
+          />
+          <div
+            class="install__header-grey-circle"
+          />
+        </div>
+        <div
+          class="install__header-text"
+        >
+          bash
+        </div>
+      </div>
+      <ul
+        class="react-tabs__tab-list"
+        role="tablist"
+      />
+      <div
+        aria-labelledby="tab:r5:0"
+        class="react-tabs__tab-panel react-tabs__tab-panel--selected"
+        id="panel:r5:0"
+        role="tabpanel"
+      >
+        <div>
+          <pre
+            class="shell-box"
+          >
+            <div
+              class="shell-box-top"
+            >
+              <span>
+                SHELL
+              </span>
+              <button
+                type="button"
+              >
+                copy
+              </button>
+            </div>
+            <code>
+              <span
+                class="install__text__no-select"
+              >
+                $
+              </span>
+              <span
+                class="install__text__command"
+              >
+                choco 
+              </span>
+              install nvs
+            </code>
+          </pre>
+          <pre
+            class="shell-box"
+          >
+            <div
+              class="shell-box-top"
+            >
+              <span>
+                SHELL
+              </span>
+              <button
+                type="button"
+              >
+                copy
+              </button>
+            </div>
+            <code>
+              <span
+                class="install__text__no-select"
+              >
+                $
+              </span>
+              <span
+                class="install__text__command"
+              >
+                nvs 
+              </span>
+              add lts
+            </code>
+          </pre>
+          <pre
+            class="shell-box"
+          >
+            <div
+              class="shell-box-top"
+            >
+              <span>
+                SHELL
+              </span>
+              <button
+                type="button"
+              >
+                copy
+              </button>
+            </div>
+            <code>
+              <span
+                class="install__text__no-select"
+              >
+                $
+              </span>
+              <span
+                class="install__text__command"
+              >
+                nvs 
+              </span>
+              use lts
+            </code>
+          </pre>
+          <br />
+          <br />
+          <a
+            class="install__docs-button"
+            href="/download/package-manager/#nvs"
+          >
+            Read documentation
+          </a>
+        </div>
+      </div>
+      <div
+        aria-labelledby="tab:r5:1"
+        class="react-tabs__tab-panel"
+        id="panel:r5:1"
+        role="tabpanel"
+      />
+      <div
+        aria-labelledby="tab:r5:2"
+        class="react-tabs__tab-panel"
+        id="panel:r5:2"
+        role="tabpanel"
+      />
+    </div>
+  </div>
+</div>
+`;
 
 exports[`Tests for InstallTabs component renders correctly for other 1`] = `
 <div>
diff --git a/src/components/Layout/__tests__/__snapshots__/centered-layout.test.tsx.snap b/src/components/Layout/__tests__/__snapshots__/centered-layout.test.tsx.snap
index 9cddec62..28d3284d 100644
--- a/src/components/Layout/__tests__/__snapshots__/centered-layout.test.tsx.snap
+++ b/src/components/Layout/__tests__/__snapshots__/centered-layout.test.tsx.snap
@@ -106,7 +106,28 @@ exports[`CenteredLayout component renders correctly with footer 1`] = `
           </li>
           <li
             class="nav__tabs nav__tabs--right"
-          />
+          >
+            <button
+              class="dark-mode-toggle"
+              type="button"
+            >
+              <span
+                class="sr-only"
+              >
+                Toggle Dark Mode
+              </span>
+              <i
+                class="material-icons light-mode-only theme-buttons"
+              >
+                nights_stay
+              </i>
+              <i
+                class="material-icons dark-mode-only theme-buttons"
+              >
+                wb_sunny
+              </i>
+            </button>
+          </li>
           <li
             class="nav__tabs"
           >
@@ -348,7 +369,28 @@ exports[`CenteredLayout component renders correctly without footer 1`] = `
           </li>
           <li
             class="nav__tabs nav__tabs--right"
-          />
+          >
+            <button
+              class="dark-mode-toggle"
+              type="button"
+            >
+              <span
+                class="sr-only"
+              >
+                Toggle Dark Mode
+              </span>
+              <i
+                class="material-icons light-mode-only theme-buttons"
+              >
+                nights_stay
+              </i>
+              <i
+                class="material-icons dark-mode-only theme-buttons"
+              >
+                wb_sunny
+              </i>
+            </button>
+          </li>
           <li
             class="nav__tabs"
           >
diff --git a/src/components/Layout/__tests__/__snapshots__/layout.test.tsx.snap b/src/components/Layout/__tests__/__snapshots__/layout.test.tsx.snap
index 2fa54958..40cefa51 100644
--- a/src/components/Layout/__tests__/__snapshots__/layout.test.tsx.snap
+++ b/src/components/Layout/__tests__/__snapshots__/layout.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Layout component renders correctly with data 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/src/components/Layout/__tests__/__snapshots__/page-layout.test.tsx.snap b/src/components/Layout/__tests__/__snapshots__/page-layout.test.tsx.snap
index 1dc06b29..00e166f9 100644
--- a/src/components/Layout/__tests__/__snapshots__/page-layout.test.tsx.snap
+++ b/src/components/Layout/__tests__/__snapshots__/page-layout.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`PageLayout component renders correctly with data 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/404.test.tsx.snap b/test/pages/__snapshots__/404.test.tsx.snap
index ccb69921..87c97bd1 100644
--- a/test/pages/__snapshots__/404.test.tsx.snap
+++ b/test/pages/__snapshots__/404.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`404 page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/about.test.tsx.snap b/test/pages/__snapshots__/about.test.tsx.snap
index 1fd77508..6af8fa11 100644
--- a/test/pages/__snapshots__/about.test.tsx.snap
+++ b/test/pages/__snapshots__/about.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`About page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/blog.test.tsx.snap b/test/pages/__snapshots__/blog.test.tsx.snap
index bf071753..e2047852 100644
--- a/test/pages/__snapshots__/blog.test.tsx.snap
+++ b/test/pages/__snapshots__/blog.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Blog page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
@@ -388,7 +409,28 @@ exports[`Blog page renders correctly for empty blogs list 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/community.test.tsx.snap b/test/pages/__snapshots__/community.test.tsx.snap
index c50a4785..7363084d 100644
--- a/test/pages/__snapshots__/community.test.tsx.snap
+++ b/test/pages/__snapshots__/community.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Community Page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/governance.test.tsx.snap b/test/pages/__snapshots__/governance.test.tsx.snap
index d3903544..3fe21e10 100644
--- a/test/pages/__snapshots__/governance.test.tsx.snap
+++ b/test/pages/__snapshots__/governance.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Governance Page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/home.test.tsx.snap b/test/pages/__snapshots__/home.test.tsx.snap
index 92dc6e0e..63e4351f 100644
--- a/test/pages/__snapshots__/home.test.tsx.snap
+++ b/test/pages/__snapshots__/home.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Home page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
@@ -694,7 +715,28 @@ exports[`Home page renders i18n when feature toggle is present 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/privacy.test.tsx.snap b/test/pages/__snapshots__/privacy.test.tsx.snap
index 803647a6..247da132 100644
--- a/test/pages/__snapshots__/privacy.test.tsx.snap
+++ b/test/pages/__snapshots__/privacy.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Privacy Page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/releases.test.tsx.snap b/test/pages/__snapshots__/releases.test.tsx.snap
index 01c34ae3..64cb3a97 100644
--- a/test/pages/__snapshots__/releases.test.tsx.snap
+++ b/test/pages/__snapshots__/releases.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Releases page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/resources.test.tsx.snap b/test/pages/__snapshots__/resources.test.tsx.snap
index 6d769885..9539fb11 100644
--- a/test/pages/__snapshots__/resources.test.tsx.snap
+++ b/test/pages/__snapshots__/resources.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`About page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/security.test.tsx.snap b/test/pages/__snapshots__/security.test.tsx.snap
index af6a197f..383384c0 100644
--- a/test/pages/__snapshots__/security.test.tsx.snap
+++ b/test/pages/__snapshots__/security.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Security page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/trademark.test.tsx.snap b/test/pages/__snapshots__/trademark.test.tsx.snap
index 5af67baf..2cc0fecf 100644
--- a/test/pages/__snapshots__/trademark.test.tsx.snap
+++ b/test/pages/__snapshots__/trademark.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Trademark page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/__snapshots__/working-groups.test.tsx.snap b/test/pages/__snapshots__/working-groups.test.tsx.snap
index f93c612c..0ee71272 100644
--- a/test/pages/__snapshots__/working-groups.test.tsx.snap
+++ b/test/pages/__snapshots__/working-groups.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Working Groups page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/download/__snapshots__/index.test.tsx.snap b/test/pages/download/__snapshots__/index.test.tsx.snap
index 4ac62281..939b01a0 100644
--- a/test/pages/download/__snapshots__/index.test.tsx.snap
+++ b/test/pages/download/__snapshots__/index.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Download page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
@@ -911,7 +932,28 @@ exports[`Download page should handle LTS to Current switch 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/pages/download/__snapshots__/package-manager.test.tsx.snap b/test/pages/download/__snapshots__/package-manager.test.tsx.snap
index fd7536f9..63841ce1 100644
--- a/test/pages/download/__snapshots__/package-manager.test.tsx.snap
+++ b/test/pages/download/__snapshots__/package-manager.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Package Manager Page renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/templates/__snapshots__/blog.test.tsx.snap b/test/templates/__snapshots__/blog.test.tsx.snap
index 9a98b92f..e4fbc38d 100644
--- a/test/templates/__snapshots__/blog.test.tsx.snap
+++ b/test/templates/__snapshots__/blog.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`LearnLayout Template renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >
diff --git a/test/templates/__snapshots__/learn.test.tsx.snap b/test/templates/__snapshots__/learn.test.tsx.snap
index 24bab7a4..6cefbb9b 100644
--- a/test/templates/__snapshots__/learn.test.tsx.snap
+++ b/test/templates/__snapshots__/learn.test.tsx.snap
@@ -109,7 +109,28 @@ exports[`Learn Template renders correctly 1`] = `
             </li>
             <li
               class="nav__tabs nav__tabs--right"
-            />
+            >
+              <button
+                class="dark-mode-toggle"
+                type="button"
+              >
+                <span
+                  class="sr-only"
+                >
+                  Toggle Dark Mode
+                </span>
+                <i
+                  class="material-icons light-mode-only theme-buttons"
+                >
+                  nights_stay
+                </i>
+                <i
+                  class="material-icons dark-mode-only theme-buttons"
+                >
+                  wb_sunny
+                </i>
+              </button>
+            </li>
             <li
               class="nav__tabs"
             >