@vscode/webview-ui-toolkit
Version:
A component library for building webview-based extensions in Visual Studio Code.
83 lines (82 loc) • 3.92 kB
JavaScript
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
* Configures a MutationObserver to watch for Visual Studio Code theme changes and
* applies the current Visual Studio Code theme to the toolkit components.
*/
export function initThemeChangeListener(tokenMappings) {
window.addEventListener('load', () => {
const observer = new MutationObserver(() => {
applyCurrentTheme(tokenMappings);
});
observer.observe(document.body, {
attributes: true,
attributeFilter: ['class'],
});
applyCurrentTheme(tokenMappings);
});
}
/**
* Applies the current Visual Studio Code theme to the toolkit components.
*/
function applyCurrentTheme(tokenMappings) {
// Get all the styles applied to the <body> tag in the webview HTML
// Importantly this includes all the CSS variables associated with the
// current Visual Studio Code theme
const styles = getComputedStyle(document.body);
const body = document.querySelector('body');
if (body) {
const themeKind = body.getAttribute('data-vscode-theme-kind');
for (const [vscodeTokenName, toolkitToken] of tokenMappings) {
let value = styles.getPropertyValue(vscodeTokenName).toString();
// Handle a couple of styling edge cases when a high contrast theme is applied
if (themeKind === 'vscode-high-contrast') {
// Developer note:
//
// There are a handful of VS Code theme tokens that have no value when a high
// contrast theme is applied.
//
// This is an issue because when no value is set the toolkit tokens will fall
// back to their default color values (aka the VS Code dark theme color palette).
// This results in the backgrounds of a couple of components having default dark
// theme colors––thus breaking the high contrast theme.
//
// The below code, catches these tokens which have no value and are also background
// tokens, then overrides their value to be transparent.
if (value.length === 0 &&
toolkitToken.name.includes('background')) {
value = 'transparent';
}
// Set icon button hover to be transparent in high contrast themes
if (toolkitToken.name === 'button-icon-hover-background') {
value = 'transparent';
}
}
else if (themeKind === 'vscode-high-contrast-light') {
if (value.length === 0 &&
toolkitToken.name.includes('background')) {
// Set button variant hover backgrounds to correct values based on VS Code core source:
// https://github.com/microsoft/vscode/blob/fd0ee4f77e354de10ae591c9e97fe5ad41b398fc/src/vs/platform/theme/common/colorRegistry.ts#L270-L276
switch (toolkitToken.name) {
case 'button-primary-hover-background':
value = '#0F4A85';
break;
case 'button-secondary-hover-background':
value = 'transparent';
break;
case 'button-icon-hover-background':
value = 'transparent';
break;
}
}
}
else {
// Set contrast-active-border token to be transparent in non-high-contrast themes
if (toolkitToken.name === 'contrast-active-border') {
value = 'transparent';
}
}
toolkitToken.setValueFor(body, value);
}
}
}