Skip to content

Commit 9b28007

Browse files
Update Live Preview theme when VS Code theme changes (#1517)
1 parent 5f94ace commit 9b28007

File tree

2 files changed

+71
-0
lines changed

2 files changed

+71
-0
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the VS Code Swift open source project
4+
//
5+
// Copyright (c) 2025 the VS Code Swift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of VS Code Swift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
export class ThemeObserver {
16+
private readonly body: HTMLElement;
17+
private readonly observer: MutationObserver;
18+
19+
constructor() {
20+
this.body = document.body;
21+
this.observer = new MutationObserver(mutationsList => {
22+
for (const mutation of mutationsList) {
23+
if (mutation.type === "attributes" && mutation.attributeName === "class") {
24+
this.updateTheme();
25+
}
26+
}
27+
});
28+
}
29+
30+
/**
31+
* Updates the `data-color-scheme` attribute on <body/> based on the
32+
* current VS Code theme.
33+
*/
34+
updateTheme() {
35+
if (this.body.classList.contains("vscode-dark")) {
36+
this.body.setAttribute("data-color-scheme", "dark");
37+
} else if (this.body.classList.contains("vscode-light")) {
38+
this.body.setAttribute("data-color-scheme", "light");
39+
} else if (this.body.classList.contains("vscode-high-contrast")) {
40+
if (this.body.classList.contains("vscode-high-contrast-light")) {
41+
this.body.setAttribute("data-color-scheme", "light");
42+
} else {
43+
this.body.setAttribute("data-color-scheme", "dark");
44+
}
45+
}
46+
}
47+
48+
/** Begin listening for theme updates. */
49+
start() {
50+
this.observer.observe(this.body, {
51+
attributes: true,
52+
subtree: false,
53+
attributeFilter: ["class"],
54+
});
55+
}
56+
57+
/** Stop listening for theme updates. */
58+
stop() {
59+
this.observer.disconnect();
60+
}
61+
}

src/documentation/webview/webview.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,17 @@
1515
import { RenderNode, WebviewContent, WebviewMessage } from "./WebviewMessage";
1616
import { createCommunicationBridge } from "./CommunicationBridge";
1717
import { ErrorMessage } from "./ErrorMessage";
18+
import { ThemeObserver } from "./ThemeObserver";
1819

20+
// Remove VS Code's default styles as they conflict with swift-docc-render
21+
document.getElementById("_defaultStyles")?.remove();
22+
23+
// Hook up the automatic theme switching
24+
const themeObserver = new ThemeObserver();
25+
themeObserver.updateTheme();
26+
themeObserver.start();
27+
28+
// Set up the communication bridges to VS Code and swift-docc-render
1929
createCommunicationBridge().then(async bridge => {
2030
const vscode = acquireVsCodeApi();
2131
let activeDocumentationPath: string | undefined;

0 commit comments

Comments
 (0)