diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 8c782f076..bf11c906e 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -37,6 +37,7 @@ * Markdown API docs for members now use section-based layout (per-member `####` headings) instead of a Markdown table, eliminating embedded `
` separators, `|` pipe escaping, and improving rendering of multi-line content and code examples. [#725](https://github.com/fsprojects/FSharp.Formatting/issues/725) * Update FCS to 43.10.100. [#935](https://github.com/fsprojects/FSharp.Formatting/pull/966) * Reduce dark mode header border contrast to match the visual subtlety of light mode borders. [#885](https://github.com/fsprojects/FSharp.Formatting/issues/885) +* **breaking** Migrate theme color variables to use CSS `light-dark()` function, eliminating the separate `[data-theme=dark]` block of variable overrides and automatically honouring `prefers-color-scheme` media query when the user has not manually set a preference. [#1004](https://github.com/fsprojects/FSharp.Formatting/issues/1004) ## 21.0.0 - 2025-11-12 diff --git a/docs/content/fsdocs-default.css b/docs/content/fsdocs-default.css index 5ec19a281..6a91c57e6 100644 --- a/docs/content/fsdocs-default.css +++ b/docs/content/fsdocs-default.css @@ -50,26 +50,28 @@ --api-docs-first-column-min-width: 320px; --api-docs-second-column-min-width: 240px; - /* light theme */ - --primary: #1e8bc3; - --background: #f5f5f6; - --text-color: #020202; - --text-hover: #282828; - --heading-color: #2e293a; - --code-background: #ffffff; - --code-color: #1a4b0b; - --header-background: #f9fbfc; - --header-border: #e8ecf1; + color-scheme: light dark; + + /* theme colors — light-dark(light-value, dark-value) */ + --primary: light-dark(#1e8bc3, #81cfe0); + --background: light-dark(#f5f5f6, rgb(20, 21, 26)); + --text-color: light-dark(#020202, #F7F7F7); + --text-hover: light-dark(#282828, #FFF); + --heading-color: light-dark(#2e293a, rgb(229, 231, 235)); + --code-background: light-dark(#ffffff, #28282D); + --code-color: light-dark(#1a4b0b, #f5f5f6); + --header-background: light-dark(#f9fbfc, #0c1318); + --header-border: light-dark(#e8ecf1, #3a3a42); --header-link-color: var(--text-color); --mobile-menu-background: var(--header-background); --menu-color: var(--text-color); - --menu-item-hover-background: #eff0f1; + --menu-item-hover-background: light-dark(#eff0f1, #2c2624); --menu-item-hover-color: var(--menu-color); - --doc-tip-background: #F7F7F7; - --link-color: #4871f7; + --doc-tip-background: light-dark(#F7F7F7, #2e293a); + --link-color: light-dark(#4871f7, #c5eff7); --link-hover: #91aafa; - --search-background: rgb(229, 231, 235); - --nav-category: rgb(156, 163, 175); + --search-background: light-dark(rgb(229, 231, 235), #020202); + --nav-category: light-dark(rgb(156, 163, 175), rgb(207, 211, 215)); --scrollbar-track-background: #424242; --scrollbar-track-border: #4A4A4A; --scrollbar-thumb-background: #686868; @@ -94,27 +96,27 @@ --header-brand-text-transform: none; - --code-strings-color: #0093A1; + --code-strings-color: light-dark(#0093A1, #86b4b9); --code-printf-color: #6B2FBA; --code-escaped-color: #EA8675; - --code-identifiers-color: #6B2FBA; - --code-module-color: #009999; - --code-reference-color: #4974D1; - --code-value-color: #1B6600; + --code-identifiers-color: light-dark(#6B2FBA, #d1b3f5); + --code-module-color: light-dark(#009999, #15e1e1); + --code-reference-color: light-dark(#4974D1, #40fddd); + --code-value-color: light-dark(#1B6600, #ffb4e9); --code-interface-color: #43AEC6; --code-typearg-color: #43AEC6; - --code-disposable-color: #43AEC6; - --code-property-color: #43AEC6; + --code-disposable-color: light-dark(#43AEC6, #6dd6f1); + --code-property-color: light-dark(#43AEC6, #6acfe7); --code-punctuation-color: #43AEC6; --code-punctuation2-color: var(--text-color); --code-function-color: #6B2FBA; - --code-function2-color: #6B2FBA; + --code-function2-color: light-dark(#6B2FBA, #cbda9d); --code-activepattern-color: #4ec9b0; --code-unioncase-color: #4ec9b0; --code-enumeration-color: #8C6C41; - --code-keywords-color: #0F54D6; - --code-comment-color: #707070; - --code-operators-color: #0F54D6; + --code-keywords-color: light-dark(#0F54D6, #a7c2f8); + --code-comment-color: light-dark(#707070, #84d16e); + --code-operators-color: light-dark(#0F54D6, #b4c6ee); --code-numbers-color: #009999; --code-linenumbers-color: #80b0b0; --code-mutable-color: #1b6600; @@ -124,51 +126,16 @@ --code-tooltip-color: #d1d1d1; } -/* dark theme */ +/* Explicit color-scheme overrides for the manual theme toggle. + light-dark() values in :root are resolved based on color-scheme, + which also automatically follows prefers-color-scheme when not overridden. */ [data-theme=dark] { - --primary: #81cfe0; - --background: rgb(20, 21, 26); - --text-color: #F7F7F7; - --text-hover: #FFF; - --heading-color: rgb(229, 231, 235); - --code-background: #28282D; - --code-color: #f5f5f6; - --header-background: #0c1318; - --header-border: #3a3a42; - --menu-item-hover-background: #2c2624; - --doc-tip-background: #2e293a; - --link-color: #c5eff7; - --search-background: #020202; - --nav-category: rgb(207, 211, 215); - --code-strings-color: #86b4b9; - --code-printf-color: #6B2FBA; - --code-escaped-color: #EA8675; - --code-identifiers-color: #d1b3f5; - --code-module-color: #15e1e1; - --code-reference-color: #40fddd; - --code-value-color: #ffb4e9; - --code-interface-color: #43AEC6; - --code-typearg-color: #43AEC6; - --code-disposable-color: #6dd6f1; - --code-property-color: #6acfe7; - --code-punctuation-color: #43AEC6; - --code-punctuation2-color: var(--text-color); - --code-function-color: #6B2FBA; - --code-function2-color: #cbda9d; - --code-activepattern-color: #4ec9b0; - --code-unioncase-color: #4ec9b0; - --code-enumeration-color: #8C6C41; - --code-keywords-color: #a7c2f8; - --code-comment-color: #84d16e; - --code-operators-color: #b4c6ee; - --code-numbers-color: #009999; - --code-linenumbers-color: #80b0b0; - --code-mutable-color: #1b6600; - --code-inactive-color: #808080; - --code-preprocessor-color: #af75c1; - --code-fsioutput-color: #808080; - --code-tooltip-color: #d1d1d1; + color-scheme: dark; +} + +[data-theme=light] { + color-scheme: light; } /* CSS Reset, source: https://www.joshwcomeau.com/css/custom-css-reset/ */ diff --git a/docs/content/fsdocs-theme-set-dark.js b/docs/content/fsdocs-theme-set-dark.js index b6eeaba3f..23a1b270f 100644 --- a/docs/content/fsdocs-theme-set-dark.js +++ b/docs/content/fsdocs-theme-set-dark.js @@ -1,5 +1,4 @@ -const prefersDark = window.matchMedia("@media (prefers-color-scheme: dark)").matches; -let currentTheme = localStorage.getItem('theme') ?? (prefersDark ? 'dark' : 'light'); -if (currentTheme === 'dark') { - window.document.documentElement.setAttribute("data-theme", 'dark'); +const savedTheme = localStorage.getItem('theme'); +if (savedTheme) { + window.document.documentElement.setAttribute("data-theme", savedTheme); } diff --git a/docs/styling.md b/docs/styling.md index 5716029c9..a30b35213 100644 --- a/docs/styling.md +++ b/docs/styling.md @@ -112,16 +112,14 @@ found [here](https://github.com/fsprojects/FSharp.Formatting/blob/main/docs/cont ```css :root { - --text-color: red; -} - -[data-theme=dark] { - --text-color: darkred; + --text-color: light-dark(red, darkred); } ``` -Please be aware that the `dark` mode in the default theme is using the same variables. -When you override a variable, it will also be used in `dark` mode unless redefined in a `[data-theme=dark]` CSS query. +The default theme uses the CSS [`light-dark()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark) +function so that each variable carries both its light and dark values. +The active value is resolved automatically based on the `color-scheme` property. +When you override a variable, use `light-dark(light-value, dark-value)` to supply both variants in a single declaration. ### CSS classes