Skip to content

Theming

The Blueprint AI panel is styled by a CSS-flavored split stylesheet under Plugins/BlueprintAI/Resources/Theme/. Every visible element — text, borders, buttons, code blocks, the terminal — reads from this stylesheet. Changes hot-reload as soon as you save a .json file under the directory.

Resources/Theme/
├── _shared/ ← design tokens, typography, icons, scroll
│ ├── _tokens.json ← :root design tokens (--brand-blue, --panel-bg, ...)
│ ├── typography.json
│ ├── icon-base.json
│ ├── icon-button.json
│ └── scroll.json
├── ChatPanel/ ← message bubbles, tool-use blocks, thinking, etc.
├── InputBar/ ← input field, action row, attachments, send button
├── Session/ ← session drawer
├── Terminal/ ← terminal-specific colors and font
├── Onboarding/ ← login screen
├── Mode/ ← mode selector modal
└── ... (one folder per widget feature-area)

The subdirectories are grouped by panel area (chat, input bar, terminal, sessions, …), so finding the stylesheet for a particular widget is usually a one-folder hop.

Each .json file is a flat list of CSS-style selector → property maps:

{
":root": {
"--brand-blue": "#5a9abf",
"--brand-cream": "#f5eed6"
},
".message-bubble": {
"background-color": "var(--panel-bg)",
"padding": "12px 14px",
"border-radius": "var(--border-radius)"
},
".send-button:hover": {
"background-color": "var(--button-hover)"
}
}
  • Top-level keys are CSS-style selectors (.class-name, :root, .foo:hover, .foo.bar).
  • Nested objects hold the CSS properties.
  • :root defines --variables that any rule can reference via var(--name).

The authoritative tokens live in _shared/_tokens.json. Every widget references these, so flipping a token here cascades to every chat bubble, button, border, and font that uses it.

{
":root": {
"--brand-blue": "#5a9abf", // primary accent
"--brand-cream": "#f5eed6", // secondary accent
"--text": "#C0C0C0",
"--text-muted": "#808080",
"--panel-bg": "#242424",
"--input-bg": "#0E0E0E",
"--code-bg": "#151515",
"--terminal-bg": "#151515",
"--border": "#575757",
// ...
}
}

Edit a token here and every widget that references it updates on the next save.

The stylesheet engine understands a subset of CSS that maps cleanly to Slate’s brush / font / margin model:

PropertyMaps to
background-color, border-colorSlate brush color
colorText color
padding, marginFMargin (CSS shorthand: 12px 14px, 12px 14px 8px 10px)
border-radius, border-widthBrush corners + outline
font-family, font-size, font-weightFont info
width, heightFOptionalSize
gapSlot padding inside containers
opacityRender opacity

linear-gradient(...) is supported for backgrounds (background: linear-gradient(135deg, #5a9abf 0%, #f5eed6 100%)) — the engine resolves it into a UE gradient brush.

Properties the engine doesn’t understand are ignored, with a warning in the editor Output Log.

SelectorWhat it matches
:rootThe global token scope
.fooAny widget tagged with the foo style class
.foo.barWidgets tagged with both foo and bar
.foo:hoverfoo widgets while hovered
.foo:activefoo widgets while pressed
.foo:focusfoo widgets with keyboard focus
.foo.disabledUsed when the widget is in a disabled state

Every panel widget is pre-tagged with the right style classes, so dropping a new property into an existing rule (.message-bubble, .send-button, …) takes effect immediately — no recompile, no editor restart.

Saving a .json file under Resources/Theme/ triggers an immediate re-parse and re-style of every visible Blueprint AI panel. There’s no editor restart, no recompile.

If you make a typo (invalid JSON, unknown property), the engine logs a structured warning and keeps the previous valid stylesheet. You’ll see the diagnostic in the Output Log filtered to BlueprintAI/Stylesheet.

The loader walks the directory tree recursively in sorted path order and merges rules. When two files set the same (selector, property) pair, the later one wins.

This lets you keep:

  • Shared / token files near the top (_shared/_tokens.json is loaded first because _ sorts first)
  • Feature-specific overrides under the matching subdirectory

You don’t need to worry about file order beyond that — the sort is deterministic.

To keep your overrides separate from the bundled stylesheets:

  1. Create Resources/Theme/_custom.json (the underscore prefix loads it early, but not before _shared/; alphabetically _custom_shared).

  2. Override any tokens you want:

    {
    ":root": {
    "--brand-blue": "#ff6b35",
    "--brand-cream": "#ffeaa7"
    }
    }
  3. Save. Every Blueprint AI panel re-renders in your palette.

Removing the file restores the defaults.

The panel is dark-only by design — it lives inside Unreal’s dark editor and a white block would clash. To run it light anyway, override the dark tokens in _custom.json:

{
":root": {
"--panel-bg": "#faf7eb",
"--text": "#1a1a1a",
"--input-bg": "#ece5cd",
"--border": "#b9b6a5"
}
}

Revisit the gradient stops too — the cream-on-blue contrast is tuned for dark.