From 5bee9569447c2fe21f202694b839a4c3d98261e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Wed, 4 Sep 2024 09:41:45 +0200 Subject: [PATCH 1/2] dark(element) closes #1339 --- docs/lib/generators.md | 53 ++++++++++++++++++++++++++-- src/client/stdlib/generators/dark.ts | 13 +++---- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/docs/lib/generators.md b/docs/lib/generators.md index 1beb3c579..f5913b7df 100644 --- a/docs/lib/generators.md +++ b/docs/lib/generators.md @@ -81,9 +81,9 @@ const width = Generators.width(document.querySelector("main")); width ``` -## dark() +## dark(*element*) -[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/dark.ts) · Returns an async generator that yields a boolean indicating whether the page is currently displayed with a dark [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme). +[Source](https://github.com/observablehq/framework/blob/main/src/client/stdlib/generators/dark.ts) · Returns an async generator that yields a boolean indicating whether the given target *element* is currently displayed with a dark [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme). If the page supports both light and dark mode (as with the [default theme](../themes)), the value reflects the user’s [preferred color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme). The generator will yield a new value if the preferred color changes — as when the user changes their system settings, or if the user’s system adapts automatically to the diurnal cycle — allowing you to update the display as needed without requiring a page reload. @@ -95,7 +95,7 @@ The current theme is: *${dark ? "dark" : "light"}*. The current theme is: *${dark ? "dark" : "light"}*. ``` -This generator is available by default as `dark` in Markdown. It can be used to pick a [color scheme](https://observablehq.com/plot/features/scales#color-scales) for a chart, or an appropriate [mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode): +This generator for the document `body` is available by default as `dark` in Markdown. It can be used to pick a [color scheme](https://observablehq.com/plot/features/scales#color-scales) for a chart, or an appropriate [mix-blend-mode](https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode): ```js echo Plot.plot({ @@ -118,3 +118,50 @@ Plot.plot({ ] }) ``` + +The following card uses a ${darkTarget ? "dark" : "light"} color scheme, which slightly varies based on the page’s scheme, but is always ${darkTarget ? "dark" : "light"}. This is reflected, for example, in the colors that the browser selects for the inputs. + +```js +const target = display(html`
+
+ ${Inputs.range([0, 100], {step: 1, label: "What a scheme!"})} +
+
`); + +const darkTarget = Generators.dark(target.querySelector(".card > div")); +``` + +```js +const toggleCard = view(Inputs.toggle({label: "toggle card scheme"})); +``` + +```js +toggleCard ? html` +` +: +html` +` +``` + + + diff --git a/src/client/stdlib/generators/dark.ts b/src/client/stdlib/generators/dark.ts index 9996ec7d3..e1c2fce1f 100644 --- a/src/client/stdlib/generators/dark.ts +++ b/src/client/stdlib/generators/dark.ts @@ -1,18 +1,19 @@ import {observe} from "./observe.js"; // Watches dark mode based on theme and user preference. -// TODO: in preview, also watch for changes in the theme meta. -export function dark() { +export function dark(target: HTMLElement = document.body) { return observe((notify: (dark: boolean) => void) => { let dark: boolean | undefined; - const media = matchMedia("(prefers-color-scheme: dark)"); + target.style.setProperty("transition-property", "color"); + target.style.setProperty("transition-duration", "0.001s"); + target.style.setProperty("transition-behavior", "allow-discrete"); // TODO: not sure this is necessary const changed = () => { - const d = getComputedStyle(document.body).getPropertyValue("color-scheme") === "dark"; + const d = getComputedStyle(target).getPropertyValue("color-scheme") === "dark"; if (dark === d) return; // only notify if changed notify((dark = d)); }; changed(); - media.addEventListener("change", changed); - return () => media.removeEventListener("change", changed); + target.addEventListener("transitionstart", changed); + return () => target.removeEventListener("transitionstart", changed); }); } From 343a1bf395b2d53d6414659eb6242ee311fe4738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Rivi=C3=A8re?= Date: Wed, 4 Sep 2024 09:44:46 +0200 Subject: [PATCH 2/2] not necessary --- src/client/stdlib/generators/dark.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client/stdlib/generators/dark.ts b/src/client/stdlib/generators/dark.ts index e1c2fce1f..540198653 100644 --- a/src/client/stdlib/generators/dark.ts +++ b/src/client/stdlib/generators/dark.ts @@ -6,7 +6,6 @@ export function dark(target: HTMLElement = document.body) { let dark: boolean | undefined; target.style.setProperty("transition-property", "color"); target.style.setProperty("transition-duration", "0.001s"); - target.style.setProperty("transition-behavior", "allow-discrete"); // TODO: not sure this is necessary const changed = () => { const d = getComputedStyle(target).getPropertyValue("color-scheme") === "dark"; if (dark === d) return; // only notify if changed