Skip to contentEnma

VS Code webviews

A webview should feel native to the editor. Keep Enma's structure, type, spacing, radius and numbers, but take colors from the user's VS Code theme. @enma/css/vscode.css maps every color role Enma needs onto VS Code's theme variables.

Load the styles

ts
// extension.ts
const css = (file: string) =>
  panel.webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri, 'media', file));

panel.webview.html = `<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="Content-Security-Policy"
    content="default-src 'none'; style-src ${panel.webview.cspSource}; font-src ${panel.webview.cspSource}; script-src 'nonce-${nonce}';">
  <link rel="stylesheet" href="${css('enma.css')}">
  <link rel="stylesheet" href="${css('vscode.css')}">
  <link rel="stylesheet" href="${css('fonts/graphite.css')}">
</head>
<body data-enma="graphite" class="e-canvas">
  <main id="app"></main>
  <script nonce="${nonce}" src="${panel.webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri, 'media', 'main.js'))}"></script>
</body>
</html>`;

Copy enma.css, vscode.css and the fonts folder from @enma/css/dist into media/ at build time. Fonts load through asWebviewUri and must be allowed by font-src in the Content Security Policy.

Follow the editor's theme

VS Code adds vscode-dark, vscode-light or vscode-high-contrast to the body. Set data-theme from it, and again when it changes:

ts
// media/main.ts
const body = document.body;
const sync = () => (body.dataset.theme = body.classList.contains('vscode-light') ? 'light' : 'dark');
sync();
new MutationObserver(sync).observe(body, { attributes: true, attributeFilter: ['class'] });

What the mapping does

css
[data-enma='graphite'],
[data-enma='graphite'][data-theme],
[data-enma='graphite'] [data-theme]:not([data-enma]) {
  --e-bg: var(--vscode-editor-background);
  --e-surface: var(--vscode-sideBar-background);
  --e-raised: var(--vscode-list-hoverBackground);
  --e-field: var(--vscode-input-background);
  --e-line: var(--vscode-panel-border);
  --e-line-strong: var(--vscode-input-border, var(--vscode-panel-border));
  --e-ink: var(--vscode-foreground);
  --e-ink-2: var(--vscode-descriptionForeground);
  --e-primary: var(--vscode-button-background);
  --e-on-primary: var(--vscode-button-foreground);
  --e-accent: var(--vscode-focusBorder);
  --e-focus: var(--vscode-focusBorder);
}

Tips

  • Use compact density: sm buttons and fields, 13px text, tables for lists of things.
  • Numbers still use the number face (JetBrains Mono in Graphite) with tabular figures.
  • Keep keyboard shortcuts out of VS Code's way; register commands in the extension instead of listening for global keys in the webview.
  • High contrast themes: VS Code's variables already carry the contrast; don't add Enma shadows on top.

↑ ↓ to move, Enter to open, Esc to close

Keyboard shortcuts

Open the command palette
Ctrl then K
Search
/
Show keyboard shortcuts
?
Close the top overlay
Esc
Go to Home
G then H
Go to Themes
G then T
Go to Playground
G then P
Go to Components
G then C
Go to Guides
G then G
Go to Samples
G then S