Create new AiderDesk UI themes by defining SCSS color variables, registering theme types, and adding i18n display names. Use when adding a theme, creating a color scheme, customizing appearance, or implementing dark mode and light mode variants.
65
77%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Optimize this skill with Tessl
npx tessl skill review --optimize ./.aider-desk/skills/theme-factory/SKILL.mdUse this skill when you need to add a new theme to AiderDesk.
AiderDesk themes are implemented as SCSS files that define a .theme-<name> class with a full set of CSS custom properties (variables). The UI uses Tailwind utilities mapped to these CSS variables.
src/renderer/src/themes/theme-<name>.scsssrc/renderer/src/themes/themes.scsspackages/common/src/types/common.ts (THEMES)src/renderer/src/components/settings/GeneralSettings.tsxsrc/renderer/src/App.tsx (applies theme-<name> class to document.body)packages/common/src/locales/en.json (themeOptions.<name>)packages/common/src/locales/zh.json (themeOptions.<name>)Each theme is a class:
.theme-<name>--color-* variables.Best workflow: copy an existing theme (e.g. theme-dark.scss) and adjust values.
Pick a kebab-case name, e.g. sunset, nord, paper.
You will reference it consistently in:
.theme-<name>theme-<name>.scssTHEMES array value: '<name>'themeOptions.<name>Create:
src/renderer/src/themes/theme-<name>.scssStart by copying a similar theme (dark -> dark-ish, light -> light-ish), then update the hex colors.
Minimum requirement: define all variables expected by the app.
Practical way to ensure completeness:
src/renderer/src/themes/theme-dark.scss (or another full theme)Edit:
src/renderer/src/themes/themes.scssAdd:
@use 'theme-<name>.scss';If the file is not imported here, it won’t be included in the built CSS.
Edit:
packages/common/src/types/common.tsAdd '<name>' to the exported THEMES array.
This makes the theme selectable and type-safe.
Edit:
packages/common/src/locales/en.jsonpackages/common/src/locales/zh.jsonAdd entries under themeOptions:
{
"themeOptions": {
"<name>": "Your Theme Name"
}
}Each variable maps from --color-<group>-<variant> in SCSS to a Tailwind utility like bg-<group>-<variant>, text-<group>-<variant>, or border-<group>-<variant>. The mapping is defined in tailwind.config.js.
--color-bg-*)The app uses a 5-tier surface hierarchy from darkest to lightest (for dark themes; reversed for light):
| Variable | Usage | Where visible |
|---|---|---|
bg-primary | Deepest background — app body, outer containers | body, outer page wrapper, main content areas, inline edit panels |
bg-primary-light | Primary raised surface — task bars, sidebar items, file viewers, content panels | TaskBar, TaskItem (idle), file viewer scrollable area, top-bar gradient end |
bg-primary-light-strong | Semi-transparent overlay — selected items, diff/file headers, notifications, tooltip arrows, reflected messages | TaskItem (selected), PierreDiffViewer header, toast notification bg |
bg-secondary | Card/panel surface — input fields, dialog content, chips, selected/hovered task items | Model dialog, chip items, settings cards, hover on menu items |
bg-secondary-light | Elevated input container — search/dropdown wrappers, dropdown menus, merge button popover | Tag input containers, settings dropdown focus wrappers |
bg-secondary-light-strongest | Opaque elevated surface — dialogs (BaseDialog), thinking blocks, inactive tab hover | BaseDialog bg, ThinkingAnswerBlock, inactive project tab hover |
bg-tertiary | Hover/highlight surface — icon button hover, menu item hover, scrollbar thumb, diff gutter omit, CodeMirror autocomplete border | All icon button hovers, menu item hovers, scrollbar thumbs |
bg-tertiary-emphasis | Accent-tinted hover — uses the theme's accent color at ~25% opacity for tinted hover states | Header icon button hover, delete button hover backgrounds, task badges |
bg-tertiary-strong | Stronger tinted hover — accent color at ~50% opacity | Active project tab hover |
bg-fourth | Separator / small control surface — vertical dividers in TaskBar, checkbox checked state, close button bg, tab hover for active tab | TaskBar dividers, Checkbox checked bg, BaseDialog close button |
bg-fourth-muted | Accent-tinted subtle bg — accent color at ~20% opacity | Decorative/special accent backgrounds |
bg-fourth-emphasis | Accent-tinted medium bg — accent color at ~30% opacity | Decorative/special accent backgrounds |
bg-fifth | Highest hover state — used for "close" button hover in dialogs | BaseDialog close button hover |
bg-selection | Text selection highlight — used in PromptField for text selection color | PromptField ::selection color |
bg-code-block | Code block background — standalone code blocks, diff file items, log viewer | CodeBlock component, DiffFileItem, LogsPage pre blocks |
--color-bg-diff-viewer-*)| Variable | Usage |
|---|---|
diff-viewer-old-primary | Deleted line background (used in DiffViewer.scss, CompactDiffViewer) |
diff-viewer-old-secondary | Deleted line character-level edit highlight |
diff-viewer-new-primary | Inserted line background |
diff-viewer-new-secondary | Inserted line character-level edit highlight |
--color-text-*)| Variable | Usage | Visible on |
|---|---|---|
text-primary | Primary text — labels, headings, button text, body text | Most text throughout the app |
text-secondary | Secondary text — icons in header, model subtitles, status text | Header icons (notebook, chart, settings), model provider text |
text-tertiary | Tertiary text — hover state for muted items, diff modified markers, toolbar button hover | Hover state text, diff line numbers, expanded toolbar buttons |
text-muted-light | Dimmed text — reflected messages, placeholder labels | ReflectedMessageBlock, disabled-state labels |
text-muted | Muted text — description paragraphs, log viewer text, empty states | Settings descriptions, log output, chip empty labels |
text-muted-dark | Dark muted — input placeholders, section dividers | PromptField placeholder, TaskSectionHeader |
text-dark | Darkest text — very deep background text, decorative | Rarely used, deepest layer text |
--color-border-*)| Variable | Usage | Visible on |
|---|---|---|
border-dark | Subtlest border — outer container edges, sticky headers | Home page outer border, UpdatedFilesDiffModal header, bash blocks |
border-dark-light | Light subtle border — code blocks, sidebar section separators, task item borders | CodeBlock border, TaskSectionHeader top border, TaskItem border |
border-dark-light-strong | Semi-transparent subtle border — reflected messages, code block <hr> | ReflectedMessageBlock, CodeBlock horizontal rules |
border-default-dark | Medium border — prompt input borders (unfocused), diff comment panel | PromptField unfocused border |
border-default | Standard border — inputs, cards, dividers, containers (most common) | Settings inputs, Home container, inline edit panels, TaskItem |
border-accent | Accent border — focused inputs, checked checkboxes/radios, diff headers, badge borders | PromptField focus, Checkbox checked, PierreDiffViewer header |
border-light | Lightest border — selected/focused inputs, active tab indicators | Settings active option border, input focus state |
--color-accent-*)| Variable | Usage |
|---|---|
accent-primary | Brand accent — AI sparkle icon, welcome message bullets, commit badges, voice recording indicator |
accent-secondary | Secondary accent — selected answer highlights, decorative accents |
accent-light | Highlight accent — token usage bar fill, hover text for commit links |
--color-success-*, --color-warning-*, --color-error-*, --color-info-*)Each has up to 7 variants with consistent suffix semantics:
--color-button-*)Three button palettes (primary, secondary, danger) each with 5 variants. See Button.tsx for the full mapping:
| Variant | Usage in contained | Usage in text | Usage in outline |
|---|---|---|---|
(base) | Background | — | Border color |
-light | Hover background | — | — |
-subtle | — | Hover background | Hover background |
-emphasis | Hover background (danger) | — | — |
-text | Text color | Text color | Text color |
The tertiary button color uses bg-primary/bg-secondary + text-primary instead of dedicated button tokens.
Disabled buttons use: bg-bg-tertiary-strong background + text-text-muted text.
--color-input-*)Currently not directly used in TSX components — inputs use bg-bg-secondary + border-border-default + text-text-primary instead. These are defined for potential future use or custom components.
--color-agent-*)Semantic colors for tool/badge indicators in the AgentSelector and related UI:
agent-auto-approve — auto-approve toggle indicatoragent-aider-tools — aider tools iconagent-power-tools — power tools iconagent-todo-tools — todo tool badgeagent-tasks-tools — tasks tool badgeagent-memory-tools — memory tool badgeagent-skills-tools — skills tool badgeagent-subagents-tools — subagents tool badgeagent-context-files — context file indicatoragent-repo-map — repo map indicatoragent-ai-request — AI request indicatoragent-sub-agent — sub-agent indicatorDark themes (those that need a dark code editor) must also be added to the isCodeEditorDarkTheme array in packages/common/src/types/common.ts.
Many variables include an inline hex alpha suffix (e.g. #D4A05440 = accent at ~25% opacity). The convention is:
1a ≈ 10% — subtle19 ≈ 10% — subtle (alternate)26 ≈ 15% — muted33 ≈ 20% — muted4c ≈ 30% — emphasis4d ≈ 30% — emphasis (alternate)50 ≈ 31% — selection60 ≈ 38% — strong7f ≈ 50% — strong (alternate)80 ≈ 50% — semi-transparentf2 ≈ 95% — almost opaqueSome components use CSS variables directly via var(--color-*) instead of Tailwind utilities:
main.css: body background/text, CodeMirror editor styling, resize handleDiffViewer.scss / PierreDiffViewer.scss: diff line backgrounds, guttersnotifications.ts: toast background/text stylingPromptField.tsx: text selection colorTheme not showing up:
@use import in src/renderer/src/themes/themes.scssTHEMES array in packages/common/src/types/common.ts.theme-<name> and the <name> stored in settingsSome UI areas look "unstyled":
--color-* variables; compare against a known-good theme and fill in the missing ones.Input fields don't match theme:
bg-bg-secondary + border-border-default for inputs, not the input-* tokens. Focus on the bg/border/text hierarchies instead.e82a91f
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.