Skip to content

Commit a91fdcd

Browse files
watch prefers-color-scheme
it's the same as the visual toggle except we don't set local storage
1 parent 7f211ce commit a91fdcd

File tree

4 files changed

+94
-40
lines changed

4 files changed

+94
-40
lines changed

src/resources/formats/html/templates/quarto-html-after-body.ejs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,41 +22,7 @@
2222
2323
window.document.body.appendChild(a);
2424
}
25-
26-
const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
27-
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
28-
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
29-
30-
let newTheme = '';
31-
32-
if(darkModeDefault) {
33-
newTheme = isAlternate ? baseTheme : alternateTheme;
34-
} else {
35-
newTheme = isAlternate ? alternateTheme : baseTheme;
36-
}
37-
38-
const changeGiscusTheme = () => {
39-
40-
// From: https://github.com/giscus/giscus/issues/336
41-
const sendMessage = (message) => {
42-
const iframe = document.querySelector('iframe.giscus-frame');
43-
if (!iframe) return;
44-
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
45-
}
46-
47-
sendMessage({
48-
setConfig: {
49-
theme: newTheme
50-
}
51-
});
52-
}
53-
54-
const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
55-
if (isGiscussLoaded) {
56-
changeGiscusTheme();
57-
}
58-
}
59-
25+
6026
<% } %>
6127
6228
<% if (tabby) { %>

src/resources/formats/html/templates/quarto-html-before-body.ejs

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,46 @@
128128
return localAlternateSentinel;
129129
}
130130
}
131+
132+
const toggleGiscusIfUsed = (isAlternate, darkModeDefault) => {
133+
const baseTheme = document.querySelector('#giscus-base-theme')?.value ?? 'light';
134+
const alternateTheme = document.querySelector('#giscus-alt-theme')?.value ?? 'dark';
135+
136+
let newTheme = '';
137+
138+
if(darkModeDefault) {
139+
newTheme = isAlternate ? baseTheme : alternateTheme;
140+
} else {
141+
newTheme = isAlternate ? alternateTheme : baseTheme;
142+
}
143+
144+
const changeGiscusTheme = () => {
145+
146+
// From: https://github.com/giscus/giscus/issues/336
147+
const sendMessage = (message) => {
148+
const iframe = document.querySelector('iframe.giscus-frame');
149+
if (!iframe) return;
150+
iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app');
151+
}
152+
153+
sendMessage({
154+
setConfig: {
155+
theme: newTheme
156+
}
157+
});
158+
}
159+
160+
const isGiscussLoaded = window.document.querySelector('iframe.giscus-frame') !== null;
161+
if (isGiscussLoaded) {
162+
changeGiscusTheme();
163+
}
164+
};
165+
131166
<% if (respectUserColorScheme) { %>
132-
const darkModeDefault = window.matchMedia('(prefers-color-scheme: dark)').matches;
167+
const queryPrefersDark = window.matchMedia('(prefers-color-scheme: dark)');
168+
const darkModeDefault = queryPrefersDark.matches;
133169
<% } else { %>
134-
const darkModeDefault = <%= darkModeDefault %>;
170+
const darkModeDefault = <%= darkModeDefault %>;
135171
<% } %>
136172
137173
let localAlternateSentinel = darkModeDefault ? 'alternate' : 'default';
@@ -145,6 +181,14 @@
145181
toggleGiscusIfUsed(toAlternate, darkModeDefault);
146182
};
147183
184+
<% if (respectUserColorScheme) { %>
185+
queryPrefersDark.addEventListener("change", e => {
186+
const alternate = e.matches
187+
toggleColorMode(alternate);
188+
toggleGiscusIfUsed(alternate, darkModeDefault);
189+
});
190+
<% } %>
191+
148192
// Switch to dark mode if need be
149193
if (hasAlternateSentinel()) {
150194
toggleColorMode(true);

tests/integration/playwright/tests/html-dark-mode-defaultdark.spec.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { test, expect } from '@playwright/test';
22

3+
async function check_background(page, class_, bkcolor) {
4+
const locatr = await page.locator('body').first();
5+
await expect(locatr).toHaveClass(`fullcontent ${class_}`);
6+
await expect(locatr).toHaveCSS('background-color', bkcolor);
7+
}
8+
39
async function check_backgrounds(page, class_, primary, secondary) {
410
const locatr = await page.locator('body').first();
511
await expect(locatr).toHaveClass(`fullcontent ${class_}`);
@@ -16,7 +22,6 @@ test.use({
1622
const blue = 'rgb(204, 221, 255)';
1723
const red = 'rgb(66, 7, 11)';
1824

19-
2025
// brands used in these documents have background colors
2126

2227
test('Dark and light brand after user themes', async ({ page }) => {
@@ -44,8 +49,24 @@ test('Project specifies light and dark brands and respect-user-color-scheme', as
4449
await check_backgrounds(page, 'quarto-dark', red, blue);
4550
});
4651

52+
test('Project specifies light and dark brands, dynamic respect-user-color-scheme', async ({ page }) => {
53+
await page.goto('./html/dark-brand/project-light/simple-respect-color-scheme.html');
54+
const locatr = await page.locator('body').first();
55+
await expect(locatr).toHaveClass(`fullcontent quarto-dark`);
56+
await expect(locatr).toHaveCSS('background-color', red);
57+
58+
await page.emulateMedia({ colorScheme: 'light' });
59+
await expect(locatr).toHaveClass(`fullcontent quarto-light`);
60+
await expect(locatr).toHaveCSS('background-color', blue);
61+
});
4762

48-
test('Project specifies dark and light brands and respect-user-color-scheme', async ({ page }) => {
63+
test('Project specifies dark and light brands, dynamic respect-user-color-scheme', async ({ page }) => {
4964
await page.goto('./html/dark-brand/project-dark/simple-respect-color-scheme.html');
50-
await check_backgrounds(page, 'quarto-dark', red, blue);
65+
const locatr = await page.locator('body').first();
66+
await expect(locatr).toHaveClass(`fullcontent quarto-dark`);
67+
await expect(locatr).toHaveCSS('background-color', red);
68+
69+
await page.emulateMedia({ colorScheme: 'light' });
70+
await expect(locatr).toHaveClass(`fullcontent quarto-light`);
71+
await expect(locatr).toHaveCSS('background-color', blue);
5172
});

tests/integration/playwright/tests/html-dark-mode-defaultlight.spec.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,26 @@ test('Project specifies dark and light brands and respect-user-color-scheme', as
4747
await page.goto('./html/dark-brand/project-dark/simple-respect-color-scheme.html');
4848
await check_backgrounds(page, 'quarto-light', blue, red);
4949
});
50+
51+
52+
test('Project specifies light and dark brands, dynamic respect-user-color-scheme', async ({ page }) => {
53+
await page.goto('./html/dark-brand/project-light/simple-respect-color-scheme.html');
54+
const locatr = await page.locator('body').first();
55+
await expect(locatr).toHaveClass(`fullcontent quarto-light`);
56+
await expect(locatr).toHaveCSS('background-color', blue);
57+
58+
await page.emulateMedia({ colorScheme: 'dark' });
59+
await expect(locatr).toHaveClass(`fullcontent quarto-dark`);
60+
await expect(locatr).toHaveCSS('background-color', red);
61+
});
62+
63+
test('Project specifies dark and light brands, dynamic respect-user-color-scheme', async ({ page }) => {
64+
await page.goto('./html/dark-brand/project-dark/simple-respect-color-scheme.html');
65+
const locatr = await page.locator('body').first();
66+
await expect(locatr).toHaveClass(`fullcontent quarto-light`);
67+
await expect(locatr).toHaveCSS('background-color', blue);
68+
69+
await page.emulateMedia({ colorScheme: 'dark' });
70+
await expect(locatr).toHaveClass(`fullcontent quarto-dark`);
71+
await expect(locatr).toHaveCSS('background-color', red);
72+
});

0 commit comments

Comments
 (0)