From a6b1240bfe92629befe6f8d260864ab84424ac0a Mon Sep 17 00:00:00 2001 From: Maria Hutt Date: Thu, 27 Aug 2026 14:47:07 -0700 Subject: [PATCH 1/2] feat(theme): add system color mode to the theme toggle --- .prettierignore | 2 + docusaurus.config.js | 1 + src/styles/components/_theme-toggle.scss | 52 ------------------------ src/styles/custom.scss | 1 - src/theme/Icon/DarkMode/index.tsx | 24 +++++++++++ src/theme/Icon/LightMode/index.tsx | 24 +++++++++++ 6 files changed, 51 insertions(+), 53 deletions(-) delete mode 100644 src/styles/components/_theme-toggle.scss create mode 100644 src/theme/Icon/DarkMode/index.tsx create mode 100644 src/theme/Icon/LightMode/index.tsx diff --git a/.prettierignore b/.prettierignore index aeedd95d45f..8b0126b66ef 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,7 +3,9 @@ # Wrapped components are our own code, so they follow the repo's formatting. src/theme/DocItem/Layout/index.tsx src/theme/EditMetaRow/index.tsx +src/theme/Icon/DarkMode/index.tsx src/theme/Icon/Edit/index.tsx +src/theme/Icon/LightMode/index.tsx src/theme/Icon/Language/index.tsx src/theme/Layout/index.tsx src/theme/NavbarItem/LocaleDropdownNavbarItem/index.tsx diff --git a/docusaurus.config.js b/docusaurus.config.js index 0b3061a8f7b..150fdc3b38e 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -162,6 +162,7 @@ module.exports = { ], colorMode: { defaultMode: 'light', + respectPrefersColorScheme: true, }, navbar: { hideOnScroll: true, diff --git a/src/styles/components/_theme-toggle.scss b/src/styles/components/_theme-toggle.scss deleted file mode 100644 index 850ad8d9216..00000000000 --- a/src/styles/components/_theme-toggle.scss +++ /dev/null @@ -1,52 +0,0 @@ -[class^='toggle_'] { - position: relative; - padding: 0; - - display: flex; - align-items: center; - justify-content: center; - - [class^='toggleTrack'] { - display: none; - } - - input[type='checkbox'] { - display: block; - position: relative; - height: 1.25rem; - width: 1.25rem; - clip: unset; - cursor: pointer; - } - - &::before { - content: ''; - position: absolute; - z-index: 1; - pointer-events: none; - top: 0; - left: 0; - width: 100%; - height: 100%; - - background: var(--token-primary-bg-c); - } - - &::after { - content: ''; - width: 1rem; - height: 1rem; - display: block; - pointer-events: none; - - position: absolute; - z-index: 2; - } -} - -html[data-theme='light'] [class^='toggle_']::after { - content: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuMzA3NjkgMy4zODQ2MkM0LjMwNzY5IDIuMjA2OTIgNC40ODExNSAxLjAxNSA0LjkyMzA4IDBDMS45ODM0NiAxLjI3OTYyIDAgNC4yODE1NCAwIDcuNjkyMzFDMCAxMi4yODA0IDMuNzE5NjIgMTYgOC4zMDc2OSAxNkMxMS43MTg1IDE2IDE0LjcyMDQgMTQuMDE2NSAxNiAxMS4wNzY5QzE0Ljk4NSAxMS41MTg4IDEzLjc5MzEgMTEuNjkyMyAxMi42MTU0IDExLjY5MjNDOC4wMjczMSAxMS42OTIzIDQuMzA3NjkgNy45NzI2OSA0LjMwNzY5IDMuMzg0NjJaIiBmaWxsPSIjOTJBMEIzIi8+Cjwvc3ZnPgo='); -} -html[data-theme='dark'] [class^='toggle_']::after { - content: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGgKICAgIGQ9Ik04IDMuMmEuNzcuNzcgMCAwIDEtLjc3LS43N1YuNzdhLjc3Ljc3IDAgMSAxIDEuNTQgMHYxLjY2QS43Ny43NyAwIDAgMSA4IDMuMlpNOCAxNmEuNzcuNzcgMCAwIDEtLjc3LS43N3YtMS42N2EuNzcuNzcgMCAwIDEgMS41NCAwdjEuNjdBLjc3Ljc3IDAgMCAxIDggMTZaTTExLjk0IDQuODNhLjc3Ljc3IDAgMCAxLS41NS0xLjNsMS4xOC0xLjE5YS43Ny43NyAwIDAgMSAxLjA5IDEuMDlMMTIuNDggNC42YS43Ni43NiAwIDAgMS0uNTQuMjJaTTIuODggMTMuODhhLjc3Ljc3IDAgMCAxLS41NC0xLjNsMS4xOC0xLjE5YS43Ny43NyAwIDEgMSAxLjA5IDEuMDlsLTEuMTggMS4xOGEuNzYuNzYgMCAwIDEtLjU1LjIyWk0xNS4yMyA4Ljc3aC0xLjY2YS43Ny43NyAwIDAgMSAwLTEuNTRoMS42NmEuNzcuNzcgMCAwIDEgMCAxLjU0Wk0yLjQzIDguNzdILjc3YS43Ny43NyAwIDEgMSAwLTEuNTRoMS42NmEuNzcuNzcgMCAxIDEgMCAxLjU0Wk0xMy4xMiAxMy44OGEuNzYuNzYgMCAwIDEtLjU1LS4yMmwtMS4xOC0xLjE4YS43Ny43NyAwIDAgMSAxLjA5LTEuMDlsMS4xOCAxLjE4YS43Ni43NiAwIDAgMS0uNTQgMS4zMVpNNC4wNiA0LjgzYS43Ni43NiAwIDAgMS0uNTQtLjIyTDIuMzQgMy40M2EuNzcuNzcgMCAwIDEgMS4wOS0xLjA5TDQuNiAzLjUyYS43Ny43NyAwIDAgMS0uNTUgMS4zMVpNOCAxMS41NWEzLjU1IDMuNTUgMCAxIDEgMC03LjEgMy41NSAzLjU1IDAgMCAxIDAgNy4xWiIKICAgIGZpbGw9IiNmZmZmZmYiIC8+Cjwvc3ZnPg=='); -} diff --git a/src/styles/custom.scss b/src/styles/custom.scss index b518dd5de32..f1133013798 100644 --- a/src/styles/custom.scss +++ b/src/styles/custom.scss @@ -21,7 +21,6 @@ @use './components/search'; @use './components/table'; @use './components/tabs'; -@use './components/theme-toggle'; @use './components/toc'; :root { diff --git a/src/theme/Icon/DarkMode/index.tsx b/src/theme/Icon/DarkMode/index.tsx new file mode 100644 index 00000000000..149f654cb33 --- /dev/null +++ b/src/theme/Icon/DarkMode/index.tsx @@ -0,0 +1,24 @@ +/** + * Original source: + * @link https://github.com/facebook/docusaurus/blob/v3.10.2/packages/docusaurus-theme-classic/src/theme/Icon/DarkMode/index.tsx + * + * Reason for overriding: + * - Changed the icon to Ionic's moon mark. The artwork is drawn on a 16x16 + * grid, so only the `viewBox` differs from upstream; the rendered size still + * matches the light and system icons. + * - `currentColor` is kept from upstream so the icon inherits `--navbar-icon-link-c`. + */ + +import React, {type ReactNode} from 'react'; +import type {Props} from '@theme/Icon/DarkMode'; + +export default function IconDarkMode(props: Props): ReactNode { + return ( + + + + ); +} diff --git a/src/theme/Icon/LightMode/index.tsx b/src/theme/Icon/LightMode/index.tsx new file mode 100644 index 00000000000..8ea848270d0 --- /dev/null +++ b/src/theme/Icon/LightMode/index.tsx @@ -0,0 +1,24 @@ +/** + * Original source: + * @link https://github.com/facebook/docusaurus/blob/v3.10.2/packages/docusaurus-theme-classic/src/theme/Icon/LightMode/index.tsx + * + * Reason for overriding: + * - Changed the icon to Ionic's sun mark. The artwork is drawn on a 16x16 + * grid, so only the `viewBox` differs from upstream; the rendered size still + * matches the dark and system icons. + * - `currentColor` is kept from upstream so the icon inherits `--navbar-icon-link-c`. + */ + +import React, {type ReactNode} from 'react'; +import type {Props} from '@theme/Icon/LightMode'; + +export default function IconLightMode(props: Props): ReactNode { + return ( + + + + ); +} From 8b07269a59788ca5aead0447d04174a34482392e Mon Sep 17 00:00:00 2001 From: Maria Hutt Date: Fri, 28 Aug 2026 10:40:25 -0700 Subject: [PATCH 2/2] chore(docusaurus): remove defaultMode --- docusaurus.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/docusaurus.config.js b/docusaurus.config.js index 150fdc3b38e..8c0abad72fb 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -161,7 +161,6 @@ module.exports = { }, ], colorMode: { - defaultMode: 'light', respectPrefersColorScheme: true, }, navbar: {