diff --git a/graph/ui-theme/src/lib/theme-resolver.tsx b/graph/ui-theme/src/lib/theme-resolver.tsx index 298870ef1fbf7..2dd3774e12b24 100644 --- a/graph/ui-theme/src/lib/theme-resolver.tsx +++ b/graph/ui-theme/src/lib/theme-resolver.tsx @@ -3,12 +3,29 @@ export const localStorageThemeKey = 'nx-dep-graph-theme'; export type Theme = 'light' | 'dark' | 'system'; export let currentTheme: Theme; +// listen for (prefers-color-scheme: dark) changes function mediaListener(ev: MediaQueryListEvent) { const resolver = ev.matches ? 'dark' : 'light'; toggleHtmlClass(resolver); currentTheme = resolver; } +// listen for body.vscode-dark changes +const vscodeDarkOberserver = new MutationObserver((mutations) => { + for (let mutation of mutations) { + if (mutation.type === 'attributes') { + const isVSCodeDark = document.body.classList.contains('vscode-dark'); + const isVSCodeLight = document.body.classList.contains('vscode-light'); + if (!isVSCodeDark && !isVSCodeLight) { + return; + } + const resolver = isVSCodeDark ? 'dark' : 'light'; + toggleHtmlClass(resolver); + currentTheme = resolver; + } + } +}); + function toggleHtmlClass(theme: Theme) { if (theme === 'dark') { htmlEl.classList.add('dark'); @@ -25,9 +42,14 @@ export function themeInit() { themeResolver(theme); } -export function getSystemTheme() { - const darkMedia = window.matchMedia('(prefers-color-scheme: dark)'); - return darkMedia.matches ? 'dark' : 'light'; +export function getSystemTheme(): 'light' | 'dark' { + const isVSCodeDark = document.body.classList.contains('vscode-dark'); + const isVSCodeLight = document.body.classList.contains('vscode-light'); + if (isVSCodeDark || isVSCodeLight) { + return isVSCodeDark ? 'dark' : 'light'; + } + const isDarkMedia = window.matchMedia('(prefers-color-scheme: dark)').matches; + return isDarkMedia || isVSCodeDark ? 'dark' : 'light'; } export function themeResolver(theme: Theme) { @@ -38,12 +60,17 @@ export function themeResolver(theme: Theme) { const darkMedia = window.matchMedia('(prefers-color-scheme: dark)'); if (theme !== 'system') { darkMedia.removeEventListener('change', mediaListener); + vscodeDarkOberserver.disconnect(); toggleHtmlClass(theme); currentTheme = theme; } else { - const resolver = darkMedia.matches ? 'dark' : 'light'; + const resolver = getSystemTheme(); darkMedia.addEventListener('change', mediaListener); + vscodeDarkOberserver.observe(document.body, { + attributes: true, + attributeFilter: ['class'], + }); toggleHtmlClass(resolver); currentTheme = resolver; }