ux-theming
Skill221 starsChanged 6 months agoApache-2.0View on GitHub
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.
2 other projects use a version of this, 2 of them edited.
Adopted by
Most recently taken up by
- microsoft/vscodeedited, first seen Nov 2, 2026
- posit-dev/positronedited, first seen Oct 8, 2026
Other versions2 projects use a version of this.
Word for word · 0
None found.
Edited · 2
- microsoft/vscode★ 195k99% same
- posit-dev/positron★ 4.3k99% same
Wrote their own version · 0
None found.
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository27 other files it gives its agents.
- AGENTS.mdAGENTS.md
- .github/copilot-instructions.mdCopilot instructions
- launchSkill
- accessibilitySkill
- add-policySkill
- author-contributionsSkill
- auto-perf-optimizeSkill
- azure-pipelinesSkill
- chat-customizations-editorSkill
- chat-perfSkill
- code-oss-logsSkill
- component-fixturesSkill
- cpu-profile-analysisSkill
- fix-ci-failuresSkill
- fix-errorsSkill
- heap-snapshot-analysisSkill
- hygieneSkill
- integration-testsSkill
- memory-leak-auditSkill
- otelSkill
- sessionsSkill
- smoke-testsSkill
- tool-rename-deprecationSkill
- unit-testsSkill
- update-screenshotsSkill
- ux-css-layoutSkill
- vscode-dev-workbenchSkill
The file
We split this skill into the rules it gives an agent
7 rules. About 0 are common, 2 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 23
Use color transforms for derived colors: transparent(), darken(), lighten(), oneOf().
- Distinctive: line 64
Every widget type has a default style object and an override factory:
- Very specific: line 92
Use var(--vscode-focusBorder) — never hardcode a focus color.
- Very specific: line 93
Default outline-offset: -1px (inset).
- Very specific: line 95
Use .synthetic-focus class for programmatic focus indication.
- Distinctive: line 113
Box shadows: must be removed or replaced in HC mode (shadows are invisible/distracting with high contrast borders):
- Very specific: line 141
Rule: If a value relates to color, shadow, or border — it must come from a CSS variable or registered color token.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
This skill covers color registration, CSS variable usage, widget style patterns, focus indicators, and high-contrast theme requirements.
1. Registering Colors
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:
- Provide defaults for all four theme types:
light,dark,hcDark,hcLight. - HC themes must use solid colors (avoid transparency) and set explicit borders via
contrastBorder. - Use color transforms for derived colors:
transparent(),darken(),lighten(),oneOf(). - Reference existing colors when possible instead of hardcoding hex values.
2. Color Categories
| 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 |
3. Using Colors in CSS
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);
}4. Widget Styles Pattern
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.
5. Focus Indicators
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:
- Use
var(--vscode-focusBorder)— never hardcode a focus color. - Default
outline-offset: -1px(inset). Exception: checkboxes use2px. - Active elements suppress focus ring:
.my-widget:active { outline: 0 !important; } - Use
.synthetic-focusclass for programmatic focus indication. - Toggle buttons use
border: 1px dashed var(--vscode-focusBorder)instead of outline.
Focus Trapping
Modal dialogs must trap focus within the dialog until dismissed. Use dom.trackFocus() and handle Tab/Shift+Tab cycling.
6. High Contrast Theme Rules
- Always provide
hcDarkandhcLightdefaults when registering colors. - HC backgrounds:
Color.black(hcDark),Color.white(hcLight). - HC borders: reference
contrastBorder— it isnullin normal themes, visible in HC. - HC focus: use
activeContrastBorder(derived fromfocusBorder). - In CSS, use
.hc-black/.hc-lightclass selectors for HC-specific overrides:.hc-black .my-widget { border: 1px solid var(--vscode-contrastBorder); } - In TypeScript, check
isHighContrast(theme.type)for runtime behavior changes. - Box shadows must be removed or replaced in HC mode (shadows are invisible/distracting with high contrast borders):
.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); }
7. No Hardcoded Visual Values
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-bodyFontSize, agents --vscode-agents-fontSize-*) |
font-weight: 500 | 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.
Key Files
| 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 |
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

