microsoft/ux-theming
VS Code theming, color tokens, widget styles, focus indicators, and high-contrast theme support. Use when registering colors, styling widgets with theme tokens, or ensuring HC/focus compliance.
npx skills add https://github.com/microsoft/vscode --skill ux-theming
This skill covers color registration, CSS variable usage, widget style patterns, focus indicators, and high-contrast theme requirements.
File: src/vs/platform/theme/common/colorUtils.ts
export const myWidgetBackground = registerColor('myWidget.background',
{ light: '#ffffff', dark: '#252526', hcDark: Color.black, hcLight: Color.white },
nls.localize('myWidgetBackground', "Background color of My Widget."));
Rules:
light, dark, hcDark, hcLight.contrastBorder.transparent(), darken(), lighten(), oneOf().| File | Colors |
|------|--------|
| src/vs/platform/theme/common/colors/baseColors.ts | foreground, focusBorder, contrastBorder, text links |
| src/vs/platform/theme/common/colors/editorColors.ts | Editor widgets, find match, errors/warnings |
| src/vs/platform/theme/common/colors/inputColors.ts | Input, toggle, validation |
| src/vs/platform/theme/common/colors/listColors.ts | List/tree selection, focus, hover, drop |
| src/vs/platform/theme/common/colors/miscColors.ts | Badge, scrollbar, progress bar, sash |
| src/vs/workbench/common/theme.ts | Tabs, sidebar, status bar, panels, editor groups, banner |
Colors are injected as CSS custom properties on .monaco-workbench:
Color ID: editor.background
CSS variable: --vscode-editor-background
Usage: var(--vscode-editor-background)
Conversion functions in colorUtils.ts:
asCssVariable(colorId) → 'var(--vscode-editor-background)'asCssVariableName(colorId) → '--vscode-editor-background'In CSS files, reference directly:
.my-widget {
background-color: var(--vscode-editor-background);
color: var(--vscode-foreground);
border: 1px solid var(--vscode-contrastBorder);
}
File: src/vs/platform/theme/browser/defaultStyles.ts
Every widget type has a default style object and an override factory:
// Use defaults:
const button = new Button(container, defaultButtonStyles);
// Override specific colors:
const button = new Button(container, getButtonStyles({
buttonBackground: myCustomBackgroundColor
}));
Available defaults: defaultButtonStyles, defaultInputBoxStyles, defaultCheckboxStyles, defaultToggleStyles, defaultDialogStyles, defaultListStyles, defaultSelectBoxStyles, defaultMenuStyles, defaultProgressBarStyles, defaultCountBadgeStyles, defaultBreadcrumbsWidgetStyles, defaultKeybindingLabelStyles, defaultFindWidgetStyles.
Defined in src/vs/workbench/browser/media/style.css:
.my-widget:focus {
outline-width: 1px;
outline-style: solid;
outline-offset: -1px;
outline-color: var(--vscode-focusBorder);
}
Rules:
var(--vscode-focusBorder) — never hardcode a focus color.outline-offset: -1px (inset). Exception: checkboxes use 2px..my-widget:active { outline: 0 !important; }.synthetic-focus class for programmatic focus indication.border: 1px dashed var(--vscode-focusBorder) instead of outline.Modal dialogs must trap focus within the dialog until dismissed. Use dom.trackFocus() and handle Tab/Shift+Tab cycling.
hcDark and hcLight defaults when registering colors.Color.black (hcDark), Color.white (hcLight).contrastBorder — it is null in normal themes, visible in HC.activeContrastBorder (derived from focusBorder)..hc-black / .hc-light class selectors for HC-specific overrides: .hc-black .my-widget { border: 1px solid var(--vscode-contrastBorder); }
isHighContrast(theme.type) for runtime behavior changes. .my-widget {
box-shadow: 0 1px 3px var(--vscode-widget-shadow);
}
.vscode-high-contrast .my-widget {
box-shadow: none;
border: 1px solid var(--vscode-contrastBorder);
}
Reviewers will always flag hardcoded colors, shadows, sizes that should use theme tokens or CSS variables.
| Hardcoded (flagged) | Correct |
|---------------------|---------|
| rgba(0, 0, 0, 0.12) | var(--vscode-widget-shadow) or theme-aware variable |
| #252526 | var(--vscode-editor-background) |
| color: white | var(--vscode-button-foreground) |
| border: 1px solid #ccc | var(--vscode-editorWidget-border) |
| border: 1px solid … (width) | var(--vscode-strokeThickness) for the 1px width |
| border-radius: 6px | var(--vscode-cornerRadius-medium) (radius ramp) |
| padding: 8px 12px (off-scale) | spacing ramp (--vscode-spacing-size*) |
| font-size: 14px (arbitrary) | size ramp (--vscode-fontSize-*, agents --vscode-agents-fontSize-*) |
| font-weight: 500 | --vscode-fontWeight-semiBold (agents --vscode-agents-fontWeight-semiBold; no 500) |
| codicon font-size: 14px | --vscode-codiconFontSize (16) / -compact (12) |
Rule: If a value relates to color, shadow, or border — it must come from a CSS variable or registered color token. The only exception is 0 (zero) values and purely structural measurements like 100%.
Size, spacing, radius, font and stroke values have their own design-system
size tokens (and decision logic — snap maps, the pill→circle rule, and the
compact-glyph convention). Those live in the ux-css-layout skill (§10
Design-System Size Tokens) and the auto-injected
.github/instructions/design-tokens.instructions.md. Reach for those when a flag
is about *how big / how round / how bold* something is rather than *what color*.
| Area | File |
|------|------|
| Color registration | src/vs/platform/theme/common/colorUtils.ts |
| Color registry (barrel) | src/vs/platform/theme/common/colorRegistry.ts |
| Base colors | src/vs/platform/theme/common/colors/baseColors.ts |
| Workbench colors | src/vs/workbench/common/theme.ts |
| Default widget styles | src/vs/platform/theme/browser/defaultStyles.ts |
| Global workbench styles | src/vs/workbench/browser/media/style.css |
Take microsoft/ux-theming from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.