Merge pull request #12711 from Kilo-Org/add-icon-jetbrains-skill

docs: add icon-jetbrains skill for authoring JetBrains plugin icons
This commit is contained in:
Kirill Kalishev
2026-07-31 12:25:05 -04:00
committed by GitHub
5 changed files with 443 additions and 14 deletions
+137
View File
@@ -0,0 +1,137 @@
---
name: icon-jetbrains
description: Create or review IntelliJ New UI SVG icons, theme variants, sizes, and palette.
---
# IntelliJ Platform New UI Icons
Guidance for authoring SVG icons for the JetBrains plugin. This skill is the single source of truth for icon sizing, palette, dark variants, composition rules, and placement. Other docs (including `packages/kilo-jetbrains/AGENTS.md`) defer here for SVG authoring details.
Icons follow IntelliJ New UI conventions: a fixed canvas per role, a strict light/dark palette, and explicit per-shape colors (the IntelliJ SVG loader recolors by matching literal hex values, so `currentColor` and CSS do not work). The plugin loads icons directly from its resource folder — see [Where the SVGs live](#where-the-svgs-live).
## Golden rules
1. **Always ship two SVGs** — one for the light theme (e.g. `add-file.svg`) and one for the dark theme with the `_dark` suffix (`add-file_dark.svg`). Geometry must be identical between them; only the palette swaps.
- **Tool-window icons ship as a quartet, not a pair.** When a tool window has both a 16×16 base (`name.svg` / `name_dark.svg`) and a 20×20 stripe variant (`name@20x20.svg` / `name@20x20_dark.svg`), they must share the same metaphor. The stripe is only one surface — the 16×16 base also appears in **Search Everywhere**, **Find Action**, context menus, the Services tool window, recent locations, and the View ▸ Tool Windows menu. Changing only the @20x20 leaves users seeing two different icons for the same tool window depending on where they encounter it. Always update all four files together (this repo's tool-window quartet is `kilo.svg` / `kilo_dark.svg` + `kilo@20x20.svg` / `kilo@20x20_dark.svg`).
2. **Only use colors from the canonical palette.** See [palette.md](./palette.md). Picking a one-off color breaks theming and contrast.
3. **One canvas size per icon role.** See [Icon roles](#icon-roles). Do not invent new sizes or pad with empty space — IntelliJ scales the canvas as a single unit.
4. **No raster, no gradients, no filters, no embedded fonts.** Path geometry only (`<path>`, `<rect>`, `<circle>`, `<line>`, `<polyline>`, `<polygon>`). Text must be converted to outlines.
5. **Use `fill="none"` on the root `<svg>`** and set `fill` / `stroke` explicitly per shape — never rely on CSS or `currentColor`.
6. **Strokes use `stroke-width="1"`, `stroke-linecap="round"`, `stroke-linejoin="round"`** (or `stroke-miterlimit="10"` for hard joins). Heavier strokes are reserved for hero glyphs inside a circle badge (e.g. status checkmarks) and use `stroke-width="1.5"` or `"2"`. The `1` applies to the **primary glyph stroke** — do not force *every* stroke to 1. Hairline/decorative strokes (e.g. a thin stroke used to fatten a filled dot) and strokes whose width is coupled to geometry (e.g. a badge ring meant to sit flush with a fill edge) must keep their intended weight (scale with the artwork), or they fatten and misalign.
7. **Pixel-grid align**: keep stroke axes on half-pixel centers (`x.5`) and fills on whole pixels so the icon stays crisp at 1× rendering. Getting the base grid right also keeps it crisp on HiDPI/Retina; fine sub-pixel detail blurs at fractional scales (125%/150%), so keep geometry simple rather than chasing detail that won't survive scaling. SVGs are resolution-independent — ship one vector per theme, never `@2x` raster variants.
8. **File names use kebab-case and stay ASCII-only** (e.g. `arrow-down-to-line.svg`, `book-open-check.svg`, `kilo@20x20.svg`), matching every existing icon in `packages/kilo-jetbrains/frontend/src/main/resources/icons/`.
## Icon roles
Pick the canvas size from the role, not the other way around. All icons land in this repo's `packages/kilo-jetbrains/frontend/src/main/resources/icons/` (with a `views/` subfolder for in-view icons — see [Where the SVGs live](#where-the-svgs-live)).
| Role | Canvas | Filename pattern |
|---|---|---|
| Action icons (menus, popups, toolbars) | **16×16** | `name.svg` + `name_dark.svg` |
| Tree node icons (PSI, structure view) | **16×16** | `name.svg` + `name_dark.svg` |
| Tool-window stripe icons (compact/16) | **16×16** | `name.svg` + `name_dark.svg` |
| Tool-window stripe icons (New UI) | **20×20** | `name@20x20.svg` + `name@20x20_dark.svg` |
| Main toolbar (New UI) | **20×20** | `name@20x20.svg` + `name@20x20_dark.svg` |
| Editor gutter icons | **14×14** (small marks **12×12**, **9×9**) | `name.svg` + `name_dark.svg` |
| Status bar / inline status | **16×16** | `name.svg` + `name_dark.svg` |
| Breakpoint marks | **14×14** (12×12 for sub-marks) | `name.svg` + `name_dark.svg` |
| Run-config tags & disclosure chevrons | **16×16** (`chevron*.svg` may be 9×9 to 16×16) | `name.svg` + `name_dark.svg` |
| Welcome/onboarding & logos | **16, 20, 28, 48** (per surface) | `name.svg` + `name_dark.svg` |
When in doubt, find a sibling icon of the same role already in the icons folder and copy its `width` / `height` / `viewBox`.
## Where the SVGs live
Plugin icons go into `packages/kilo-jetbrains/frontend/src/main/resources/icons/` (action icons, tool-window icons) or the `icons/views/` subfolder (in-view icons used by the chat/session UI). Icons are loaded directly via `IconLoader` — there is no role-based subfolder structure and no mapping file. Place both the light SVG and its `_dark` sibling in the folder and reference them from the plugin's icon-holder class.
## SVG skeleton
```svg
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- shapes, ordered back-to-front -->
</svg>
```
The dark variant is the same file with light-palette colors swapped for their dark-theme partner — see [palette.md](./palette.md). Never change geometry between the two.
## Composition rules
- **One semantic meaning per icon.** A status badge, an accent dot, or a "+" overlay is fine; two unrelated glyphs in one icon is not.
- **Optical centering, not geometric.** Plus/arrow/refresh glyphs sit slightly above center; round badges (class, method, status) are centered on `(cx=8, cy=8)` for 16×16 and `(cx=10, cy=10)` for 20×20.
- **Outer keep-out**: leave at least **1 px** of empty padding on each side of a 16×16 icon (so meaningful geometry lives within `1..15`). For 20×20 use **2 px** of padding. Stripe icons must stay visually balanced inside their 20×20 cell.
- **Round caps overshoot the endpoint.** A round `stroke-linecap`/`stroke-linejoin` extends **half the stroke width past the endpoint**, so a 1px round-capped stroke ending at `0` or `16` is clipped by the canvas. Keep stroke endpoints within `0.5..15.5` (this is stricter than the fill keep-out).
- **Stroke + fill pairing for node-style icons** (class/method nodes): a light-tinted fill at radius 6.5 with a stroke in the accent color, plus a glyph filled with the same accent.
- Light: `<circle cx="8" cy="8" r="6.5" fill="<accent-bg-light>" stroke="<accent-light>"/>` then glyph `fill="<accent-light>"`.
- Dark: same circle with `fill="<accent-bg-dark>" stroke="<accent-dark>"` and glyph filled with `<accent-dark>`.
- **Stroke-only icons** (chevrons, refresh, edit pencil): a single-color path using the neutral stroke (`#6C707E` light / `#CED0D6` dark) at `stroke-width="1"`. Use `#818594` (light) / `#6F737A` (dark) for "secondary" stroke glyphs like dropdown chevrons.
- **Status badges** (error/warning/success/info) follow this template:
- Light: filled circle/triangle in the *accent* color, glyph painted in `white`.
- Dark: filled circle/triangle in the *dark accent* color, glyph painted in the matching *muted dark fill* (e.g. `#5E4D33` inside `#F2C55C` warning) — never plain white.
- **Two-tone action icons** (a base glyph plus a small modifier): the base glyph uses the neutral gray, and the small modifier (`+`, ✕, ↻, gear) uses the primary blue accent. Light gray + blue accent → dark gray + blue accent in the dark variant.
- **Disabled / stroke-only variants** (e.g. `*-stroke.svg`): outline-only, same neutral stroke color, no fills.
## Palette quick reference
The full lookup is in [palette.md](./palette.md). Most icons only need:
| Role | Light | Dark |
|---|---|---|
| Primary stroke / fill | `#6C707E` | `#CED0D6` |
| Secondary stroke | `#818594` | `#6F737A` |
| Disabled / faint fill | `#EBECF0` | `#43454A` |
| Accent — Blue | `#3574F0` | `#548AF7` |
| Accent — Blue (bg) | `#EDF3FF` / `#E7EFFD` | `#25324D` |
| Accent — Red | `#DB3B4B` | `#DB5C5C` |
| Accent — Red (bg) | `#FFF7F7` | `#402929` |
| Status — Error fill | `#E55765` | `#DB5C5C` |
| Status — Warning fill | `#FFAF0F` | `#F2C55C` |
| Status — Success fill | `#55A76A` | `#57965C` |
| Accent — Green | `#208A3C` | `#57965C` |
| Accent — Green (bg) | `#F2FCF3` | `#253627` |
| Accent — Orange | `#E66D17` | `#C77D55` |
| Accent — Orange (bg) | `#FFF4EB` | `#45322B` |
| Accent — Yellow/Gold | `#FFAF0F` / `#C27D04` | `#F2C55C` / `#D6AE58` |
| Accent — Purple | `#834DF0` | `#B589EC` |
| Accent — Purple (bg) | `#FAF5FF` | `#2F2936` |
| White on dark badge | `white` | matching muted-dark fill (e.g. `#5E4D33`) |
Do not use plain `#000000` or off-the-palette grays.
## Generation workflow
1. **Pick the role and canvas size** from the table above. Find at least two visually similar sibling icons already in the icons folder and mirror their stroke/fill mix.
2. **Lay out geometry on the pixel grid** (whole-pixel fills, half-pixel stroke centers). Optical-center the glyph.
3. **Apply the canonical light palette** from [palette.md](./palette.md). Never invent colors.
4. **Save the light SVG** with `width`/`height`/`viewBox` matching the role and `fill="none"` on `<svg>`.
5. **Duplicate to the `_dark` filename** and swap each color for its dark-theme partner from the palette mapping. Keep paths byte-identical otherwise.
6. **Place and wire the file** → drop both files into `packages/kilo-jetbrains/frontend/src/main/resources/icons/` (action icons, tool-window icons) or `icons/views/` (in-view chat/session icons), then reference the icon from the plugin's icon-holder class.
7. **Verify visually** in both themes via the image preview in the IDE, or run the IDE and toggle *View ▸ Appearance ▸ New UI* to compare. Check selection states for stripe icons.
## Adapting or rescaling an existing icon
Importing a Lucide/Codicon-style icon (often drawn on a 20- or 24-unit grid) or moving one onto the 16×16 grid is not a blanket "set everything to the 16 defaults" operation:
1. **Scale geometry *and* every `stroke-width`** by the same factor (`16 ÷ source size`). This keeps the render faithful before you change anything intentionally.
2. **Only then re-weight the primary glyph stroke** to `1` if it wasn't already ~1px effective. Leave hairlines and geometry-coupled strokes at their scaled value (see rule 6).
3. **Re-check what scaling breaks:**
- Round caps clipping at the edge → nudge stroke endpoints into `0.5..15.5`.
- Strokes that were flush with a fill edge (e.g. a badge ring around a status dot) → the stroke must still straddle the fill boundary after scaling; scale its width too.
4. **Crispness is a separate pass.** Scaling rarely lands coordinates on the pixel grid, so the result is faithful but not automatically crisp; the pixel-grid snap (rule 7) is manual and per-icon.
## Common mistakes
- Off-palette colors (e.g. importing from Figma without remapping). They will not theme correctly and reviewers will reject the PR.
- Different geometry between light and dark variants — selection animations and HiDPI overlays will glitch.
- A 16-px glyph saved into a 20×20 canvas without re-balancing. Tool-window/main-toolbar icons need geometry tuned for 20×20, not a 16×16 reused with extra whitespace.
- Using `currentColor`, CSS, or `<style>` blocks. The IntelliJ icon loader requires explicit colors on every shape so it can do palette-based recoloring.
- Forgetting the `_dark` variant. The icon will look fine in Light theme then turn invisible in Dark.
- Pure-black (`#000`) or pure-white (`#FFF`) fills outside the status-badge glyph pattern. They break under accent recoloring.
- Blanket-setting every `stroke-width` to `1` when rescaling. Only the primary glyph stroke is 1px; hairlines and fill-coupled/ring strokes must scale with the geometry or they fatten and misalign.
- Round caps at the canvas edge. A round cap overshoots its endpoint by half the stroke width, so an endpoint at `0` or `16` clips — keep stroke endpoints within `0.5..15.5`.
## References
- [palette.md](./palette.md) — full color palette with light↔dark mapping.
- [examples.md](./examples.md) — annotated SVG snippets for each icon role.
- `packages/kilo-jetbrains/AGENTS.md` — repository-specific JetBrains plugin constraints; use it together with this skill for icon work.
- `packages/kilo-jetbrains/frontend/src/main/resources/icons/` (with its `views/` subfolder) — where plugin icons live; this is the ground truth for placement.
+176
View File
@@ -0,0 +1,176 @@
# Annotated New UI Icon Examples
Each example below is paired with a dark variant and a short note on the pattern it represents. Use these as templates when generating new icons. Place generated icons in `packages/kilo-jetbrains/frontend/src/main/resources/icons/` (or the `icons/views/` subfolder for in-view chat/session icons).
---
## 1. Single-color action (16×16) — primary gray stroke + filled glyph
Plus / add action — the most common action icon shape.
**Light:**
```svg
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 1C7.77614 1 8 1.22386 8 1.5V7H13.5C13.7761 7 14 7.22386 14 7.5C14 7.77614 13.7761 8 13.5 8H8V13.5C8 13.7761 7.77614 14 7.5 14C7.22386 14 7 13.7761 7 13.5V8H1.5C1.22386 8 1 7.77614 1 7.5C1 7.22386 1.22386 7 1.5 7H7V1.5C7 1.22386 7.22386 1 7.5 1Z" fill="#6C707E"/>
</svg>
```
**Dark:** swap `#6C707E``#CED0D6`.
Why it works: one filled path, primary gray. Drop in any glyph and you have a complete action icon.
---
## 2. Two-tone action (16×16) — neutral base + blue accent modifier
Add-file action — base glyph in neutral gray, "+" sticker in primary blue.
**Light:**
```svg
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 9C12.7761 9 13 9.22386 13 9.5V12H15.5C15.7761 12 16 12.2239 16 12.5C16 12.7761 15.7761 13 15.5 13H13V15.5C13 15.7761 12.7761 16 12.5 16C12.2239 16 12 15.7761 12 15.5V13H9.5C9.22386 13 9 12.7761 9 12.5C9 12.2239 9.22386 12 9.5 12H12V9.5C12 9.22386 12.2239 9 12.5 9Z" fill="#3574F0"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3 13V5.82843C3 5.29799 3.21071 4.78929 3.58579 4.41421L6.41421 1.58579C6.78929 1.21071 7.29799 1 7.82843 1H11C12.1046 1 13 1.89543 13 3V8H12V3C12 2.44772 11.5523 2 11 2H8V4C8 5.10457 7.10457 6 6 6H4V13C4 13.5523 4.44772 14 5 14H8V15H5C3.89543 15 3 14.1046 3 13ZM4.41421 5L7 2.41421V4C7 4.55228 6.55228 5 6 5H4.41421Z" fill="#6C707E"/>
</svg>
```
**Dark:** `#3574F0``#548AF7`, `#6C707E``#CED0D6`.
Pattern: stick the small modifier glyph in the bottom-right of the canvas (`(9..15, 9..15)` for 16×16) and let the base glyph occupy the top-left two-thirds.
---
## 3. Stroke-only action (16×16) — chevrons, refresh, edit
Refresh action — multiple stroked sub-paths sharing one color.
**Light:**
```svg
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.5 9V8C2.5 4.96243 4.96243 2.5 8 2.5C9.10679 2.5 10.1372 2.82692 11 3.38947" stroke="#6C707E" stroke-linecap="round"/>
<path d="M5 12.6105C5.86278 13.1731 6.89321 13.5 8 13.5C11.0376 13.5 13.5 11.0376 13.5 8V7" stroke="#6C707E" stroke-linecap="round"/>
<path d="M0.49997 7.50027L2.5 9.5L4.49998 7.50023" stroke="#6C707E" stroke-linecap="round"/>
<path d="M11.5 8.49982L13.5 6.5L15.5 8.49982" stroke="#6C707E" stroke-linecap="round"/>
</svg>
```
`stroke-width` defaults to `1`. `stroke-linecap="round"` softens path ends; pair it with `stroke-linejoin="round"` whenever paths bend.
For secondary glyphs (chevrons in popups, dropdown arrows) use `#818594` light / `#6F737A` dark instead of the primary gray.
---
## 4. Node icon (16×16) — tinted circle with stroke + glyph
Class / method nodes — the canonical PSI-node shape.
**Light (class — blue):**
```svg
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="6.5" fill="#E7EFFD" stroke="#3574F0"/>
<path d="M8.13295 11.5C9.61223 11.5 10.8836 10.6105 11.2075 9.33909H10.2213C9.90229 10.0739 9.11914 10.6057 8.13295 10.6057C6.77936 10.6057 5.80284 9.51796 5.80284 8C5.80284 6.48204 6.77936 5.39434 8.13295 5.39434C9.11914 5.39434 9.90229 5.92611 10.2213 6.66091H11.2075C10.8836 5.3895 9.61223 4.5 8.13295 4.5C6.21859 4.5 4.79248 5.99378 4.79248 8C4.79248 10.0062 6.21859 11.5 8.13295 11.5Z" fill="#3574F0"/>
</svg>
```
**Dark (class):**
```svg
<circle cx="8" cy="8" r="6.5" fill="#25324D" stroke="#548AF7"/>
<path d="M8.13295 11.5C9.61223 11.5 10.8836 10.6105 11.2075 9.33909H10.2213C9.90229 10.0739 9.11914 10.6057 8.13295 10.6057C6.77936 10.6057 5.80284 9.51796 5.80284 8C5.80284 6.48204 6.77936 5.39434 8.13295 5.39434C9.11914 5.39434 9.90229 5.92611 10.2213 6.66091H11.2075C10.8836 5.3895 9.61223 4.5 8.13295 4.5C6.21859 4.5 4.79248 5.99378 4.79248 8C4.79248 10.0062 6.21859 11.5 8.13295 11.5Z" fill="#548AF7"/>
```
**Method (red) follows the same template** with `#FFF7F7`/`#DB3B4B` (light) → `#402929`/`#DB5C5C` (dark).
Rules:
- Circle is always `cx="8" cy="8" r="6.5"` (so the 1-px stroke is centered between pixels 1 and 15).
- Fill = soft background pair, stroke = accent.
- Glyph inside uses the same accent color filled — never stroked.
---
## 5. Status badge (16×16) — circle/triangle with white glyph
Error badge:
```svg
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="8" cy="8" r="7" fill="#E55765"/>
<path d="M9 5C9 4.44772 8.55228 4 8 4C7.44772 4 7 4.44772 7 5V7.5C7 8.05229 7.44772 8.5 8 8.5C8.55229 8.5 9 8.05228 9 7.5L9 5Z" fill="white"/>
<path d="M8 12C8.55228 12 9 11.5523 9 11C9 10.4477 8.55228 10 8 10C7.44772 10 7 10.4477 7 11C7 11.5523 7.44772 12 8 12Z" fill="white"/>
</svg>
```
The warning badge is the same idea but with a rounded triangle filled `#FFAF0F` (light) / `#F2C55C` (dark). In the dark theme, the glyph inside the warning triangle uses `#5E4D33` instead of `white` (white on warm yellow is unreadable).
The success badge uses a 2-px stroked checkmark inside a `#55A76A` (light) / `#57965C` (dark) circle — `stroke="white"` and `stroke-width="2"`.
---
## 6. Tool window stripe (20×20) — single-tone glyph on a larger canvas
Build tool-window stripe:
```svg
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.25 1C4.44891 1 4.63962 1.07907 4.78027 1.21973L5.56055 2H6.43945L7.21973 1.21973L7.33398 1.12598C7.45628 1.04445 7.60085 1 7.75 1H13.125C14.9473 1 16.4277 1.87993 17.4346 3.08105C18.4322 4.27143 19 5.81492 19 7.25C19 7.51735 18.8572 7.76425 18.626 7.89844C18.3948 8.03247 18.11 8.0339 17.8779 7.90137L15.4258 6.5H14.0605L13 7.56055V18.25C13 18.6642 12.6642 19 12.25 19H7.75C7.33579 19 7 18.6642 7 18.25V7.56055L6.43945 7H5.56055L4.78027 7.78027C4.63962 7.92093 4.44891 8 4.25 8H1.75C1.33579 8 1 7.66421 1 7.25V1.75C1 1.33579 1.33579 1 1.75 1H4.25ZM8.5 17.5H11.5V8H8.5V17.5ZM2.5 6.5H3.93945L4.71973 5.71973L4.83398 5.62598C4.95628 5.54445 5.10085 5.5 5.25 5.5H6.75C6.94891 5.5 7.13962 5.57907 7.28027 5.71973L8.06055 6.5H11.9395L13.2197 5.21973L13.334 5.12598C13.4563 5.04445 13.6008 5 13.75 5H15.625C15.7555 5 15.8838 5.03392 15.9971 5.09863L17.2637 5.82227C17.0602 5.19249 16.7287 4.57423 16.2842 4.04395C15.5098 3.12029 14.4276 2.5 13.125 2.5H8.06055L7.28027 3.28027C7.13962 3.42093 6.94891 3.5 6.75 3.5H5.25C5.05109 3.5 4.86038 3.42093 4.71973 3.28027L3.93945 2.5H2.5V6.5Z" fill="#6C707E"/>
</svg>
```
Notes:
- 20×20 canvas with **at least 2 px** breathing room on each edge (geometry lives in `2..18`).
- Re-balance vs. a 16×16 sibling — do not just paste a 16×16 path into a 20×20 viewBox.
- Keep a 16×16 sibling (`name.svg`) for compact mode; the `@20x20` variant is used by default.
---
## 7. Main toolbar action (20×20) — same template as tool window
Add action (20×20):
```svg
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.75586 17.25C9.34165 17.25 9.00586 16.9142 9.00586 16.5V10.5059H3C2.58594 10.5059 2.25025 10.1699 2.25 9.75586C2.25 9.34165 2.58579 9.00586 3 9.00586H9.00586V3C9.00607 2.58597 9.34178 2.25 9.75586 2.25C10.1699 2.25 10.5056 2.58597 10.5059 3V9.00586H16.5C16.9142 9.00586 17.25 9.34165 17.25 9.75586C17.2498 10.1699 16.9141 10.5059 16.5 10.5059H10.5059V16.5C10.5059 16.9142 10.1701 17.25 9.75586 17.25Z" fill="#6C707E"/>
</svg>
```
Main-toolbar icons reuse the 20×20 conventions of tool window stripes — the canvas size and stroke weights are identical, only the visual semantics differ.
---
## 8. Gutter icon (14×14) — thin stroke, no padding
Edit-doc gutter mark:
```svg
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5973 6.65471L12.6882 4.56049C13.1053 4.15406 13.1003 3.49602 12.6948 3.08627L11.0267 1.3136L11.0224 1.30932C10.6123 0.900035 9.94199 0.893268 9.53311 1.31079L7.3867 3.44406M10.5973 6.65471L7.3867 3.44406M10.5973 6.65471L4.74041 12.5H1.50036L1.5 9.32001L7.3867 3.44406" stroke="#6C707E" stroke-miterlimit="10"/>
</svg>
```
Gutter icons:
- Canvas is 14×14 (not 16×16). Glyph extends to the edge — there is *no* outer padding margin in the gutter.
- Prefer `stroke-miterlimit="10"` for hard-pointed glyphs (pencil tip), `stroke-linecap="round"` for chevrons / arrows.
- Compound gutter glyphs (e.g. implemented + override marker) layer two badges; keep each badge ≤ 9 px so the composition stays legible.
---
## 9. Breakpoint mark (14×14) — solid filled circle
Breakpoint mark:
```svg
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 13C10.3137 13 13 10.3137 13 7C13 3.68629 10.3137 1 7 1C3.68629 1 1 3.68629 1 7C1 10.3137 3.68629 13 7 13Z" fill="#E55765"/>
</svg>
```
Breakpoint marks read at a glance — a single solid fill in the status-error red. Variants (disabled, conditional, log) layer a small overlay in the bottom-right corner.
---
## 10. Dark-variant gotcha — white-on-warm vs. muted-dark
The warning badge dark variant shows the only common case where a literal find-and-replace from the light SVG would produce a broken icon:
```svg
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1.27603 10.8634L6.3028 1.98903C7.04977 0.670323 8.94893 0.670326 9.69589 1.98903L14.7227 10.8634C15.516 12.2639 14.5047 14 12.8956 14H3.10308C1.494 14 0.482737 12.2639 1.27603 10.8634Z" fill="#F2C55C"/>
<path d="M9 5C9 4.44772 8.55228 4 8 4C7.44772 4 7 4.44772 7 5V7.5C7 8.05229 7.44772 8.5 8 8.5C8.55229 8.5 9 8.05228 9 7.5L9 5Z" fill="#5E4D33"/>
<path d="M8 12C8.55228 12 9 11.5523 9 11C9 10.4477 8.55228 10 8 10C7.44772 10 7 10.4477 7 11C7 11.5523 7.44772 12 8 12Z" fill="#5E4D33"/>
</svg>
```
`white``#5E4D33` inside the warning triangle. Apply the same swap whenever a light icon paints a glyph as `white` over a warm fill (`#FFAF0F`, `#E66D17`, etc.). For cool fills (`#3574F0`, `#208A3C`, `#DB3B4B`), the dark-theme glyph stays `white` because contrast is still sufficient.
+118
View File
@@ -0,0 +1,118 @@
# New UI Icon Palette
Canonical color palette used by New UI icons. When picking colors, always pull from this table; the IntelliJ icon engine recolors by exact-string match, so a one-off hue will fail to theme.
## How to read the mapping
- **Light** column is the color used in the default (light) SVG file: `foo.svg`.
- **Dark** column is its replacement in the `_dark` partner: `foo_dark.svg`.
- Always swap **all** light colors at once when generating the dark variant. Do not mix-and-match — the palette pairs are tuned for contrast.
## Neutrals (most icons need only these)
| Role | Light | Dark |
|---|---|---|
| **Primary stroke / fill** (main glyph) | `#6C707E` | `#CED0D6` |
| Secondary stroke (chevrons, faint glyph) | `#818594` | `#6F737A` |
| Tertiary stroke (very faint) | `#A8ADBD` | `#9DA0A8` |
| Disabled / inert fill background | `#EBECF0` | `#43454A` |
| Background plate (rare) | `#F0F1F2` | `#5A5D63` / `#1E1F22` |
| Plain white (status glyph only) | `white` | per-status muted (see below) |
`#6C707E``#CED0D6` is the single most-used pair across the entire icon set. If you only remember one pair, remember this one.
## Accent — Blue (primary action, info, default node)
| Role | Light | Dark |
|---|---|---|
| Stroke / fill | `#3574F0` | `#548AF7` |
| Soft background fill (node circle) | `#E7EFFD` | `#25324D` |
| Tinted-panel fill | `#EDF3FF` | `#25324D` |
| Alt blue (rare) | `#4682FA` | `#5F93FF` |
## Accent — Red (delete, error nodes, breakpoints)
| Role | Light | Dark |
|---|---|---|
| Stroke / fill | `#DB3B4B` | `#DB5C5C` |
| Soft background fill | `#FFF7F7` | `#402929` |
| Status badge fill (error circle) | `#E55765` | `#DB5C5C` |
The slightly different `#DB3B4B` (line / accent) vs `#E55765` (badge fill) split is intentional — the filled status circle is a touch more saturated than the line accent.
## Accent — Green (run, success, version-control add)
| Role | Light | Dark |
|---|---|---|
| Stroke / fill | `#208A3C` | `#57965C` |
| Soft background fill | `#F2FCF3` | `#253627` |
| Status badge fill (success circle) | `#55A76A` | `#57965C` |
| Alt green (rare) | `#369650` | `#5FAD65` |
## Accent — Orange / Yellow (warning, modified, bookmark)
| Role | Light | Dark |
|---|---|---|
| Orange stroke / fill | `#E66D17` | `#C77D55` |
| Orange soft fill | `#FFF4EB` | `#45322B` |
| Warning yellow (status triangle) | `#FFAF0F` | `#F2C55C` |
| Warning soft fill | `#FFFAEB` / `#F7E4CD` | `#3D3223` |
| Brown / gold deep | `#C27D04` | `#D6AE58` |
| Muted dark glyph inside warning fill | n/a (uses `white`) | `#5E4D33` |
The "white on yellow" combination is illegible in Dark theme; that's why the dark warning glyph uses `#5E4D33` (a deep brown). Apply the same idea — muted-dark glyph inside the warm fill — for any other warm-color badge in the dark theme.
## Accent — Purple (annotations, special / preview)
| Role | Light | Dark |
|---|---|---|
| Stroke / fill | `#834DF0` | `#B589EC` |
| Soft background fill | `#FAF5FF` | `#2F2936` |
| Alt purple (rare) | n/a | `#A571E6` |
## Reserved / utility
| Role | Light/Dark |
|---|---|
| Inside-circle glyph (light status) | `white` |
| Empty / placeholder | `#231F20` (avoid) |
| Tool window panel base (very rare) | `#1E1F22` (dark) |
| Other repository-specific tints | only when a sibling icon already uses them |
If your icon needs a color that is not in this table, find a sibling icon that uses something similar and reuse its exact hex string. If no sibling uses it, change your design — do not introduce a new color.
## Algorithmic light→dark swap (for scripted generation)
```text
#6C707E -> #CED0D6 primary stroke/fill
#818594 -> #6F737A secondary stroke
#A8ADBD -> #9DA0A8 tertiary stroke
#EBECF0 -> #43454A disabled fill
#3574F0 -> #548AF7 blue
#EDF3FF -> #25324D blue soft
#E7EFFD -> #25324D blue node fill
#DB3B4B -> #DB5C5C red
#FFF7F7 -> #402929 red soft
#E55765 -> #DB5C5C error badge fill
#208A3C -> #57965C green
#55A76A -> #57965C success badge fill
#F2FCF3 -> #253627 green soft
#369650 -> #5FAD65 alt green
#E66D17 -> #C77D55 orange
#FFF4EB -> #45322B orange soft
#FFAF0F -> #F2C55C warning yellow
#FFFAEB -> #3D3223 warning soft
#F7E4CD -> #3D3223 warning soft alt
#C27D04 -> #D6AE58 gold
#834DF0 -> #B589EC purple
#FAF5FF -> #2F2936 purple soft
white -> (status-glyph specific muted dark — see Orange/Yellow section)
```
A script can do a literal find-and-replace using this map to produce a `_dark.svg` from a light SVG; review the result manually for any white-on-warm cases that need the muted-dark glyph treatment.
@@ -138,6 +138,10 @@ JetBrains Kotlin toolchain is Java 21. Gradle commands report missing or incompa
Run `Plugin DevKit | Code | Frontend and Backend API Usage` inspection when moving code across split boundary.
## Icon skill
For plugin icon creation, modification, or review, use the `icon-jetbrains` skill at `.kilo/skills/icon-jetbrains/SKILL.md` together with `packages/kilo-jetbrains/AGENTS.md`. The skill covers IntelliJ New UI SVG roles, sizing, palette, dark variants, and icon validation guidance.
## Source map
Paths below are relative to [`Kilo-Org/kilocode`](https://github.com/Kilo-Org/kilocode).
+8 -14
View File
@@ -574,30 +574,24 @@ child.align(HAlign.TRACK, VAlign.TRACK) // fill all available space
### Icons and SVG Assets
Official references:
- [IntelliJ Platform UI Guidelines](https://jetbrains.design/intellij/)
- [User Interface Components](https://plugins.jetbrains.com/docs/intellij/user-interface-components.html)
- [UI FAQ (colors, borders, icons)](https://plugins.jetbrains.com/docs/intellij/ui-faq.html)
The `icon-jetbrains` skill (`.kilo/skills/icon-jetbrains/SKILL.md`) is the single source of truth for SVG icon authoring: canvas sizes, palette colors, dark variants, composition rules, placement, and validation. Always load that skill when creating, modifying, or reviewing icon assets. Do not duplicate its guidance here.
This section covers only the Kotlin/runtime integration side:
- For compact icon-only actions, use `ai.kilocode.client.ui.HoverIcon` so the control gets the standard 24×24 hover treatment. Do not create `JButton(icon)` or wrap a bare icon in a button just to make it clickable.
- **Reuse platform icons**: browse at https://intellij-icons.jetbrains.design. Access via `AllIcons.*` constants.
- Custom icons: SVG files in `resources/icons/`. Load via `IconLoader.getIcon("/icons/foo.svg", MyClass::class.java)`.
- Organize in an `icons` package or a `*Icons` object with `@JvmField` on each constant.
- **Sizing**: actions/nodes = 16×16, tool window = 13×13 (classic) or 20×20 + 16×16 compact (New UI), editor gutter = 12×12 (classic) / 14×14 (New UI).
- **Dark variants**: `icon.svg` + `icon_dark.svg`. HiDPI: `icon@2x.svg` + `icon@2x_dark.svg`.
- **New UI support**: place New UI icons in `expui/` directory, create `*IconMappings.json`, register via `com.intellij.iconMapper` extension point. New UI icon colors: light `#6C707E`, dark `#CED0D6`.
- **Sizing, dark variants, and filename patterns**: see the `icon-jetbrains` skill for the authoritative Icon roles table, canvas sizes, filename patterns, and dark variant conventions. Do not duplicate sizing or palette values here.
IntelliJ does not theme SVG icons with `currentColor`, CSS classes, CSS variables, `<style>` blocks, or inherited styles. `SVGLoader` patches icon colors by matching literal hex values in `fill` and `stroke` attributes against the active theme palette. Use hardcoded palette hex values in SVG assets and provide dark variants. This exception applies to icon asset files only; runtime Swing UI code must still derive colors from theme APIs.
| Do | Do not |
|---|---|
| `fill="#6E6E6E"` | `fill="currentColor"` |
| `stroke="#3574F0"` | CSS variables or classes |
| `icon.svg` plus `icon_dark.svg` | `<style>` blocks for theming |
| `fill-opacity="0.5"` | Inherited styling |
Themes can override palette colors through `icons.ColorPalette` in the theme JSON.
Official references:
- [IntelliJ Platform UI Guidelines](https://jetbrains.design/intellij/)
- [UI FAQ (colors, borders, icons)](https://plugins.jetbrains.com/docs/intellij/ui-faq.html)
### Before Returning UI Code
Review generated UI code and remove: