diff --git a/src/pydata_sphinx_theme/assets/styles/variables/_color.scss b/src/pydata_sphinx_theme/assets/styles/variables/_color.scss
index c7b85341c..08ddb4d43 100644
--- a/src/pydata_sphinx_theme/assets/styles/variables/_color.scss
+++ b/src/pydata_sphinx_theme/assets/styles/variables/_color.scss
@@ -80,53 +80,71 @@ $pst-semantic-colors: (
/*******************************************************************************
* write the color rules for each theme (light/dark)
-*
-* NOTE: @each {...} is like a for-loop
-* https://sass-lang.com/documentation/at-rules/control/each
-* and #{...} inserts a variable into a CSS selector or property name
-* https://sass-lang.com/documentation/interpolation
*/
-@each $mode in (light, dark) {
- html[data-theme="#{$mode}"] {
- @each $name, $value in $pst-semantic-colors {
- // check if this color is defined differently for light/dark
- @if type-of($value) == map {
- $value: map-get($value, $mode);
- }
+
+/* NOTE:
+ * Mixins enable us to reuse the same definitions for the different modes
+ * https://sass-lang.com/documentation/at-rules/mixin
+ * #{...} inserts a variable into a CSS selector or property name
+ * https://sass-lang.com/documentation/interpolation
+ */
+@mixin theme-colors($mode) {
+ // check if this color is defined differently for light/dark
+ @each $name, $value in $pst-semantic-colors {
+ @if type-of($value) == map {
+ $value: map-get($value, $mode);
+ }
+ & {
--pst-color-#{$name}: #{$value};
}
- // assign the "duplicate" colors (ones that just reference other variables)
+ }
+ // assign the "duplicate" colors (ones that just reference other variables)
+ & {
--pst-color-link: var(--pst-color-primary);
--pst-color-link-hover: var(--pst-color-warning);
- // adapt to light/dark-specific content
- @if $mode == "light" {
- .only-dark {
- display: none !important;
- }
- } @else {
- .only-light {
- display: none !important;
- }
- /* Adjust images in dark mode (unless they have class .only-dark or
- * .dark-light, in which case assume they're already optimized for dark
- * mode).
- */
- img:not(.only-dark):not(.dark-light) {
- filter: brightness(0.8) contrast(1.2);
- }
- /* Give images a light background in dark mode in case they have
- * transparency and black text (unless they have class .only-dark or .dark-light, in
- * which case assume they're already optimized for dark mode).
- */
- .bd-content img:not(.only-dark):not(.dark-light) {
- background: rgb(255, 255, 255);
- border-radius: 0.25rem;
- }
- // MathJax SVG outputs should be filled to same color as text.
- .MathJax_SVG * {
- fill: var(--pst-color-text-base);
- }
+ }
+ // adapt to light/dark-specific content
+ @if $mode == "light" {
+ .only-dark {
+ display: none !important;
+ }
+ } @else {
+ .only-light {
+ display: none !important;
+ }
+ /* Adjust images in dark mode (unless they have class .only-dark or
+ * .dark-light, in which case assume they're already optimized for dark
+ * mode).
+ */
+ img:not(.only-dark):not(.dark-light) {
+ filter: brightness(0.8) contrast(1.2);
}
+ /* Give images a light background in dark mode in case they have
+ * transparency and black text (unless they have class .only-dark or .dark-light, in
+ * which case assume they're already optimized for dark mode).
+ */
+ .bd-content img:not(.only-dark):not(.dark-light) {
+ background: rgb(255, 255, 255);
+ border-radius: 0.25rem;
+ }
+ // MathJax SVG outputs should be filled to same color as text.
+ .MathJax_SVG * {
+ fill: var(--pst-color-text-base);
+ }
+ }
+}
+
+/* Defaults to light mode if data-theme is not set */
+html:not([data-theme]) {
+ @include theme-colors("light");
+}
+
+/* NOTE: @each {...} is like a for-loop
+ * https://sass-lang.com/documentation/at-rules/control/each
+ */
+@each $mode in (light, dark) {
+ html[data-theme="#{$mode}"] {
+ @include theme-colors($mode);
}
}
diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/navbar-logo.html b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/navbar-logo.html
index c96399788..6336e1371 100644
--- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/navbar-logo.html
+++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/navbar-logo.html
@@ -13,8 +13,16 @@
{% set is_logo = "light" in theme_logo["image_relative"] %}
{% set alt = theme_logo.get("alt_text", "Logo image") %}
{% if is_logo %}
-
-
+ {# Theme switching is only available when JavaScript is enabled.
+ # Thus we should add the extra image using JavaScript, defaulting
+ # depending on the value of default_mode; and light if unset.
+ #}
+ {% if default_mode is undefined %}
+ {% set default_mode = "light" %}
+ {% endif %}
+ {% set js_mode = "light" if default_mode == "dark" else "dark" %}
+
+
{% endif %}
{% if not is_logo or theme_logo.get("text") %}
{{ theme_logo.get("text") or docstitle }}
diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/search-button.html b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/search-button.html
index 13262852b..76fc231f9 100644
--- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/search-button.html
+++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/search-button.html
@@ -1,4 +1,11 @@
-{# A button that, when clicked, will trigger a search popup overlay #}
-
+{# A button that, when clicked, will trigger a search popup overlay.
+ #
+ # As this function will only work when JavaScript is enabled, we add it through JavaScript.
+ #}
+
diff --git a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/theme-switcher.html b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/theme-switcher.html
index 65c483166..63c8cd239 100644
--- a/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/theme-switcher.html
+++ b/src/pydata_sphinx_theme/theme/pydata_sphinx_theme/components/theme-switcher.html
@@ -1,5 +1,11 @@
-