AgentSkillsCN

rstudio-theming

从单一主色调出发,为RStudio的全部29个UI区域生成完全覆盖的深色主题。在需要“创建RStudio主题”“生成RStudio主题”“补充缺失的RStudio选择器”“审计RStudio主题覆盖率”或“将VS Code主题移植到RStudio”时使用此功能。生成完整的.rstheme CSS文件,涵盖Ace编辑器、IDE Chrome、终端、对话框以及额外的界面元素。

SKILL.md
--- frontmatter
name: 'rstudio-theming'
description: 'Generates fully-covered RStudio dark themes from a single primary hex color across all 29 UI regions. Use when asked to "create an RStudio theme", "generate rstheme", "add missing RStudio selectors", "audit rstheme coverage", or "port VS Code theme to RStudio". Produces complete .rstheme CSS files with Ace editor, IDE chrome, terminal, dialog, and extras coverage.'
version: '1.0.0'
author: 'theme-framework'

This skill generates comprehensive RStudio .rstheme dark themes from a single primary hex color using OKLCH palette derivation. The governing principle is complete coverage — every customizable UI region in RStudio must receive themed selectors so no default light surfaces leak through in dark mode. Begin with <step_1_derive_palette> to generate the foundational color scales.

<use_cases>

  • Generate a new RStudio dark theme from a primary hex color with full coverage across all 29 UI regions
  • Add coverage for missing UI regions (dialogs, terminal, menus) to an existing .rstheme that only covers the Ace editor
  • Audit an existing .rstheme for selector coverage gaps and contrast failures using dual-check verification
  • Adapt a VS Code Radiant Teal palette to RStudio format while maintaining cross-editor semantic consistency
  • Regenerate a theme after upstream RStudio version changes break selectors or introduce new UI regions

</use_cases>

<workflow>

Execute steps sequentially. Each step produces output that feeds the next — palette feeds semantic mapping, semantic mapping feeds CSS generation, CSS sections combine into the final .rstheme file.

<step_1_derive_palette>

Generate six 12-step Radix scales from the primary hex using OKLCH color space via coloraide.

Load color-derivation.instructions.md for: OKLCH-first derivation rules, Radix 12-step architecture, coloraide usage patterns, and contrast enforcement requirements.

Required scales:

ScalePurposeHue derivation
primaryAccents, selection, cursor, links, active statesPrimary hex hue (constant)
neutralBackgrounds, borders, text, gutter, surfacesPrimary hue with chroma 0.005–0.02
redErrors, invalid syntax, deletions, git removedHue rotation to ~25°
amberWarnings, deprecated syntax, modified indicatorsHue rotation to ~70°
greenSuccess states, git additions, string literalsHue rotation to ~145°
blueInfo states, links, type annotationsHue rotation to ~245°

Derivation rules:

  • Hold hue constant within each scale — vary only L and C across the 12 steps
  • Dark mode lightness range: step 1 ~L 0.13–0.15, step 12 ~L 0.93–0.97
  • Chroma curve: low (steps 1–2), rising (steps 3–8), peak (steps 9–10), moderate (steps 11–12)
  • Apply coloraide gamut mapping (fit('srgb')) on every OKLCH→sRGB conversion
  • Output all hex values in 6-digit lowercase format

</step_1_derive_palette>

<step_2_map_semantic_roles>

Assign palette scale steps to UI semantic roles following the cross-editor mapping.

Load theme-conventions.instructions.md for: the <semantic_mapping> table and RStudio-specific format constraints.

Core role assignments:

Semantic roleScale/stepCSS target
App background (deepest)neutral/1.ace_gutter background
Editor backgroundneutral/2.ace_editor background
Component backgroundneutral/3Toolbar, sidebar, panel backgrounds
Hover stateneutral/4.ace_marker-layer .ace_active-line
Selectionprimary/4.ace_marker-layer .ace_selection
Subtle borderneutral/6Panel dividers, gutter border
Default borderneutral/7Input borders, dropdown borders
Strong borderneutral/8Focus rings
Accent solidprimary/9Active indicators, buttons
Accent hoverprimary/10Cursor, links, hover accents
Secondary textneutral/11Line numbers, placeholder text
Primary textneutral/12Editor foreground, UI labels

Constraint: Every foreground/background pair formed by these assignments must pass dual-check contrast before proceeding — verify in <step_8_audit_contrast>.

</step_2_map_semantic_roles>

<step_3_generate_ace_css>

Generate Ace editor CSS for code syntax highlighting. This is the core editing surface.

Token selectors and their scale assignments:

TokenSelectorTypical scale
Keywords.ace_keywordprimary/9
Strings.ace_stringgreen/9
Constants.ace_constant, .ace_constant.ace_language, .ace_constant.ace_numericamber/9
Comments.ace_commentneutral/11 (desaturated)
Functions.ace_support.ace_functionblue/9
Types/classes.ace_support.ace_class, .ace_storage.ace_typeprimary/11
Operators.ace_keyword.ace_operatorneutral/12
Variables.ace_variable, .ace_identifierneutral/12
Tags (HTML/XML).ace_meta.ace_tag, .ace_entity.ace_name.ace_tagred/9
Attributes.ace_entity.ace_other.ace_attribute-nameamber/11
Support/built-in.ace_support, .ace_support.ace_typeblue/11
Invalid.ace_invalidred/9 bg with neutral/12 fg
Deprecated.ace_invalid.ace_deprecatedamber/9 with strikethrough
Headings (Rmd).ace_markup.ace_headingprimary/10 bold

Critical constraint: NEVER use !important on Ace syntax selectors — Ace applies specificity correctly and !important causes cascading conflicts with RStudio's built-in style management.

</step_3_generate_ace_css>

<step_4_generate_ide_chrome_css>

Generate CSS for the GWT-based IDE chrome — all non-editor UI surfaces.

Load references/rstudio-selectors.md for: the complete selector catalog organized by UI region. JIT-load this reference when mapping selectors per region.

UI regions to cover (13 regions):

  1. Toolbar — main toolbar, project toolbar, button containers
  2. Sidebar — files pane, environment pane, history pane
  3. Menu bar — top menu, dropdown menus, menu items, separators
  4. Status bar — bottom status indicators
  5. Scrollbar — all scrollbar tracks, thumbs, and corners
  6. Tabs — editor tabs, pane tabs, active/inactive/hover states
  7. Panels — output panel, console panel, viewer panel
  8. Environment pane — variable browser, data viewer grid
  9. File pane — file browser, path bar, filter controls
  10. Help pane — help viewer, search results, topic display
  11. Plots pane — plot output area, navigation controls
  12. Packages pane — package list, install controls, checkboxes
  13. Connections pane — connection browser, status indicators

Critical constraint: ALWAYS use !important on IDE chrome selectors — GWT applies inline styles that override normal CSS specificity. Without !important, chrome styles are silently ignored.

Selector pattern: Use only stable, documented selector patterns — .rstheme_ prefixed classes, #rstudio_ ID selectors, and role-based attribute selectors. Never use obfuscated GWT class names.

</step_4_generate_ide_chrome_css>

<step_5_generate_dialog_css>

Generate CSS for all dialog boxes and modal overlays. Missing dialog styles are the most common cause of light surfaces in dark themes.

Dialog categories (~50 selectors):

  • Preferences dialog — settings panels, category list, input controls
  • New file dialog — file type selector, name input, template preview
  • Git commit dialog — diff viewer, commit message, staged files list
  • Install packages dialog — package search, repository selector, install button
  • Search/replace dialog — find input, replace input, match controls, result highlights
  • About dialog — version info, credits panel
  • Keyboard shortcuts dialog — shortcut list, filter input, category headers
  • Global options dialog — appearance, code editing, pane layout settings
  • Project options dialog — build tools, environments, version control settings

Critical constraint: ALWAYS use !important on dialog selectors — dialogs render via GWT overlay panels with inline styles.

Common selector patterns:

  • .gwt-DialogBox — outer dialog container
  • .gwt-DialogBox .dialogMiddleCenter — dialog content area
  • .gwt-DialogBox .dialogTopCenter — dialog title bar
  • .rstudio-themes-dark-menus .gwt-PopupPanel — popup overlay panels
  • .gwt-TabLayoutPanelTab — tabbed dialog panels

</step_5_generate_dialog_css>

<step_6_generate_terminal_css>

Generate CSS for the xterm.js-based terminal emulator.

Terminal surface selectors:

  • .terminal — terminal foreground and background
  • .xterm-viewport — scrollable terminal viewport
  • .xterm-screen — terminal screen area
  • Terminal cursor — .xterm-cursor-layer cursor styling
  • Terminal selection — .xterm .xterm-selection div selection highlight
  • Terminal scrollbar — .xterm-viewport::-webkit-scrollbar and thumb

ANSI 16 colors — map to palette scales:

ANSI colorNormal scale/stepBright scale/step
Blackneutral/1neutral/5
Redred/9red/10
Greengreen/9green/10
Yellowamber/9amber/10
Blueblue/9blue/10
Magentaprimary/9 (hue ~320°)primary/10 (hue ~320°)
Cyanprimary/9primary/10
Whiteneutral/11neutral/12

xterm-256 extended palette (P3 — nice to have): Generate the 216-color cube (indices 16–231) and 24-step grayscale ramp (indices 232–255) using OKLCH lightness interpolation.

Critical constraint: ALWAYS use !important on terminal selectors — xterm.js applies inline styles for theming.

</step_6_generate_terminal_css>

<step_7_generate_extras_css>

Generate CSS for supplementary editor features that enhance the coding experience.

Feature selectors:

  • Rainbow parentheses.ace_paren_color_0 through .ace_paren_color_6, use hue rotation from primary
  • Matching brackets.ace_bracket, highlight with primary/8 border
  • Find highlights.ace_marker-layer .ace_selected-word, .ace_search-result, use amber/4 background
  • Marker bar.ace_marker-layer .ace_step, vertical scroll annotations
  • Navigation banner.rstudio-themes-flat .rstheme_secondaryToolbar, breadcrumb and scope navigation
  • Indent guides.ace_indent-guide, subtle neutral/4 border
  • Fold widgets.ace_gutter-cell .ace_fold-widget, collapse/expand indicators in gutter
  • Chunk backgrounds.ace_marker-layer .ace_foreign_chunk_bg, background for embedded code chunks (R Markdown)
  • Console output — differentiate standard output, error output, and message output in the R console

Constraint: Use !important only on non-Ace chrome selectors (navigation banner, marker bar). Ace editor extras (rainbow parens, brackets, fold widgets) follow the no-!important rule from <step_3_generate_ace_css>.

</step_7_generate_extras_css>

<step_8_audit_contrast>

Run WCAG 2.1 AA + APCA dual-check on all foreground/background pairs generated in steps 2–7.

Load contrast-audit/SKILL.md for: the complete pair collection, classification, calculation, and reporting workflow.

Threshold quick reference:

ContextWCAG minimumAPCA minimumAPCA preferred
Body text (code, comments)4.5:1Lc 75Lc 90
Large text (headings, titles)3:1Lc 60Lc 75
UI components (buttons, tabs)3:1Lc 60Lc 75
Sub-text (line numbers, hints)3:1Lc 45Lc 60
Non-text (borders, indicators)3:1Lc 30Lc 45

Remediation: When a pair fails contrast, adjust lightness in OKLCH — NEVER adjust hue or chroma to fix contrast. Increase foreground L or decrease background L until both thresholds pass.

Radix scale validation: Verify step 11 vs step 2 achieves Lc >= 60 and step 12 vs step 2 achieves Lc >= 90 for every scale.

</step_8_audit_contrast>

<step_9_validate_css>

Validate the generated CSS for correctness and convention compliance before assembly.

Syntax validation:

  • Parse all CSS rules — no missing semicolons, no unclosed braces, no invalid property values
  • Verify all hex colors match #[0-9a-f]{6} (6-digit lowercase, no shorthand)
  • Confirm no duplicate selectors with conflicting declarations

Convention compliance:

  • !important present on ALL IDE chrome, dialog, and terminal selectors
  • !important absent from ALL Ace syntax selectors
  • No obfuscated GWT class names (patterns like .gwt-ABC123, .GNKJF3BCHB) — only stable selectors
  • No font-family or font-size declarations — RStudio controls these via user preferences (exception: @font-face for Server mode)

Coverage completeness:

  • Cross-reference generated selectors against the selector catalog in references/rstudio-selectors.md
  • Flag any region from the catalog that has zero selectors in the output
  • Minimum coverage: all 13 IDE chrome regions from <step_4_generate_ide_chrome_css> plus Ace editor and terminal

</step_9_validate_css>

<step_10_assemble_rstheme>

Combine all CSS sections into a single .rstheme file.

File structure:

  1. Metadata comment header — theme name, version, primary hex, generation date, generator script
  2. Ace editor base — .ace_editor background/foreground, .ace_gutter, .ace_cursor
  3. Ace syntax tokens — all token selectors from <step_3_generate_ace_css>
  4. Ace editor features — selection, active line, matching brackets, find highlights
  5. IDE chrome — toolbar, sidebar, menu, tabs, panels from <step_4_generate_ide_chrome_css>
  6. Dialog boxes — all modal and dialog selectors from <step_5_generate_dialog_css>
  7. Terminal — xterm.js surface and ANSI colors from <step_6_generate_terminal_css>
  8. Extras — rainbow parens, indent guides, fold widgets from <step_7_generate_extras_css>
  9. Console — R console-specific styling (input, output, error, message)
  10. Scrollbars — unified scrollbar styling across all panes

File naming: {Theme-Name}.rstheme — title case with hyphens, .rstheme extension.

Dark mode detection: RStudio auto-detects dark mode when .ace_editor background luminance < 0.2. Ensure the neutral/2 step used for editor background has OKLCH L < 0.20. Include rs-theme-name and rs-theme-is-dark comments as explicit overrides at the top of the file, even though RStudio auto-detects dark mode from luminance.

Installation verification: After generation, verify the file loads without error via rstudioapi::addTheme("path/to/Theme.rstheme").

</step_10_assemble_rstheme>

</workflow>

<important_rules>

Critical rules that govern all RStudio theme generation. Violations cause silent failures or broken themes.

  • !important split rule — ALWAYS use !important on IDE chrome, dialog, and terminal selectors (GWT inline styles override normal specificity). NEVER use !important on Ace editor syntax selectors (Ace handles specificity correctly, and !important causes cascading conflicts)
  • No obfuscated GWT classes — NEVER target minified/obfuscated GWT class names like .gwt-ABC123 or .GNKJF3BCHB. These change between RStudio versions and break themes on update. Use only .rstheme_ prefixed classes, .ace_ classes, .xterm classes, .rstudio-themes-dark-menus, and officially documented selectors
  • Dark mode detection — RStudio auto-detects dark mode when .ace_editor background has luminance < 0.2. Ensure neutral/2 has OKLCH L < 0.20. Include rs-theme-name and rs-theme-is-dark comments as explicit overrides at the top of the file, even though RStudio auto-detects dark mode from luminance
  • No font stylingfont-family and font-size are controlled by RStudio user preferences, not CSS. Do not set them in .rstheme (exception: @font-face declarations work in RStudio Server mode only)
  • OKLCH-only derivation — All colors derive from the primary hex via OKLCH. Cross-reference color-derivation.instructions.md for pipeline rules. No hardcoded hex values anywhere
  • Selector catalog — The complete selector reference is in references/rstudio-selectors.md. JIT-load this file when mapping selectors per UI region — do not memorize or inline the full catalog
  • Hex format — All color values in 6-digit lowercase hex with # prefix. No shorthand, no uppercase, no named colors, no alpha channels (RStudio CSS does not support #rrggbbaa)

</important_rules>

<pitfalls>

Common mistakes that cause broken or incomplete RStudio themes.

  • Missing !important on GWT chrome — Styles are silently ignored because GWT applies inline styles with higher specificity. The theme appears to partially work but chrome surfaces remain default. Fix: add !important to every non-Ace selector
  • Using obfuscated GWT classes — Theme works on one RStudio version but breaks on the next update when GWT recompiles and reassigns class names. Fix: use only stable .rstheme_, .ace_, and documented selectors
  • Hardcoding colors instead of deriving from palette — Produces an inconsistent theme where some surfaces feel disconnected. Fix: trace every hex value back through the OKLCH pipeline from the primary hex
  • Missing dialog box selectors — The most visible dark theme failure: opening Preferences or Install Packages reveals a white modal over a dark editor. Fix: always include the ~50 dialog selectors from <step_5_generate_dialog_css>
  • Untested terminal ANSI colors — Certain ANSI color combinations produce invisible text (e.g., dark blue on dark background). Fix: verify all 16 ANSI colors against the terminal background with dual-check contrast
  • Setting font-family in CSS — Conflicts with the user's RStudio font preferences, causing unexpected font changes or fallback to system fonts. Fix: let RStudio manage fonts via its Appearance preferences
  • Using HSL for palette math — HSL has non-uniform lightness perception, producing visible hue shifts at low lightness values typical of dark themes. Fix: use OKLCH for all derivation, convert to sRGB only for final hex output
</pitfalls>

<error_handling>

  • If a contrast check fails on a foreground/background pair, then adjust the foreground lightness (L) in OKLCH — increase L for light-on-dark, decrease L for dark-on-light. Never adjust hue or chroma to fix contrast. Re-run dual-check after adjustment
  • If a selector from the catalog is not found in the target RStudio version, then flag it as version-dependent, wrap it in a comment noting the minimum version, and exclude it from P1 coverage requirements
  • If CSS validation reports a syntax error, then check for missing semicolons, unclosed braces, or invalid property values. Common in generated CSS: missing semicolon on last property before closing brace
  • If the .rstheme file fails to load via rstudioapi::addTheme(), then verify: file has .rstheme extension, CSS parses without syntax errors, no BOM characters at file start, file uses UTF-8 encoding
  • If the editor background is not detected as dark mode, then check that neutral/2 has OKLCH L < 0.20 — if it is marginally above 0.20, reduce L by 0.01 increments until dark mode triggers
  • If a UI region has no stable selectors available, then return BLOCKED with the region name and RStudio version — do not fabricate selectors

</error_handling>

<validation>

P1 — Blocking (must pass before delivery):

  • All Ace syntax token selectors present (keyword, string, constant, comment, function, type, operator, variable, tag, attribute, support, invalid, deprecated)
  • All 13 IDE chrome regions have at least one selector each
  • !important convention correct: present on all chrome/dialog/terminal selectors, absent from all Ace syntax selectors
  • No obfuscated GWT class names in any selector
  • All foreground/background pairs pass WCAG 2.1 AA + APCA dual-check
  • .ace_editor background has OKLCH L < 0.20 (dark mode detection)
  • All hex values are 6-digit lowercase format
  • No hardcoded colors — every value traces to the OKLCH pipeline

P2 — Quality (should pass):

  • All dialog box categories covered (preferences, new file, git, install packages, search/replace)
  • Terminal ANSI 16 colors complete with all normal/bright pairs
  • Rainbow parentheses included with 7 hue-rotated colors
  • Metadata comment header present with theme name, version, primary hex, and date
  • Radix scale step 11 vs step 2 achieves Lc >= 60 for all scales
  • Radix scale step 12 vs step 2 achieves Lc >= 90 for all scales

P3 — Polish (nice to have):

  • xterm-256 extended palette (216-color cube + 24-step grayscale)
  • Navigation banner and breadcrumb styling
  • Indent guides with subtle visual treatment
  • Fold widgets with themed expand/collapse indicators
  • Body text pairs reach preferred APCA Lc 90 (not just minimum Lc 75)
  • Console output differentiation (standard, error, message styling)
</validation> <resources> </resources>