Luna UI provides a theming system through the UIColor class and UIColorValue enum. This system generates USS class names for consistent color styling across your UI.
The UIColor system maps color names and values to USS class names following a utility-first approach similar to Tailwind CSS. It supports backgrounds, borders, text, and image tints.
UIColor.Name is a plain string that must match a color family defined in your theme's USS palette. The default Luna theme (from the Essentials sample) ships these families:
amber, azure, blue, cobalt, coral, crimson, cyan, emerald, forest, fuchsia, gold, green, indigo, jade, lavender, lime, magenta, mint, navy, neutral, orange, peach, pink, purple, red, rose, ruby, scarlet, sky, slate, stone, teal, turquoise, violet, yellow
The special name transparent is also supported — its generated classes omit the value suffix (see below).
Because the name is a free-form string, custom palettes work automatically: define --color-{name}-{value} variables and the matching utility classes in your theme USS, and UIColor can reference them with no code changes.
Color intensity values (50-950):
| Value | Description |
|---|---|
| V_50 | Lightest |
| V_100 | Very light |
| V_200 | Light |
| V_300 | Light-medium |
| V_400 | Medium-light |
| V_500 | Medium (default) |
| V_600 | Medium-dark |
| V_700 | Dark |
| V_800 | Very dark |
| V_900 | Darkest |
| V_950 | Near black |
Combines a color name and value to generate USS class names.
public UIColor() // Default: "sky", V_50
public UIColor(string name, UIColorValue value)| Method | Returns | Example Output |
|---|---|---|
| GetUssClassBG() | Background class | bg-blue-500 |
| GetUssClassBorder() | Border class | border-blue-500 |
| GetUssClassText() | Text class | text-blue-500 |
| GetUssClassImageTint() | Tint class | tint-blue-500 |
| GetColor(VisualElement) | Unity Color | Reads from USS variables |
using UnityEngine;
using UnityEngine.UIElements;
using CupkekGames.Luna;
public class ColorExample : MonoBehaviour
{
[SerializeField] private UIColor _buttonColor = new UIColor("sky", UIColorValue.V_500);
private PanelRenderer _panelRenderer;
private Button _button;
private void Awake()
{
_panelRenderer = GetComponent<PanelRenderer>();
if (_panelRenderer != null)
{
_panelRenderer.RegisterUIReloadCallback(OnUIReload);
}
}
// PanelRenderer delivers the visual tree asynchronously —
// query elements in the reload callback, not in Awake/Start.
private void OnUIReload(PanelRenderer renderer, VisualElement root, int version)
{
if (_button != null) return; // sentinel: only init once
_button = root.Q<Button>("MyButton");
// Apply background color class
_button.AddToClassList(_buttonColor.GetUssClassBG());
// Apply border color class
_button.AddToClassList(_buttonColor.GetUssClassBorder());
}
private void OnDestroy()
{
if (_panelRenderer != null)
{
_panelRenderer.UnregisterUIReloadCallback(OnUIReload);
}
}
}public void SetButtonState(Button button, bool isActive)
{
// Remove old classes
button.RemoveFromClassList(_inactiveColor.GetUssClassBG());
button.RemoveFromClassList(_activeColor.GetUssClassBG());
// Add new class based on state
var color = isActive ? _activeColor : _inactiveColor;
button.AddToClassList(color.GetUssClassBG());
}To get the actual Unity Color value from USS variables:
UIColor myColor = new UIColor("blue", UIColorValue.V_500);
// Element must be in the hierarchy for custom styles to be resolved
Color actualColor = myColor.GetColor(myElement);This reads from the USS custom property --color-{name}-{value}.
The system generates classes following this pattern:
| Type | Pattern | Example |
|---|---|---|
| Background | bg-{name}-{value} | bg-sky-500 |
| Border | border-{name}-{value} | border-red-600 |
| Text | text-{name}-{value} | text-slate-100 |
| Tint | tint-{name}-{value} | tint-green-400 |
For the special name transparent, the value suffix is omitted:
bg-transparentborder-transparenttext-transparenttint-transparentEach generated class is a one-property route onto a --color-{name}-{tone} token:
:root { --color-sky-500: #3ba5ed; /* …11 tones × every family… */ }
.bg-sky-500 { background-color: var(--color-sky-500); }
.text-slate-100 { color: var(--color-slate-100); }
.tint-green-400 { -unity-background-image-tint-color: var(--color-green-400); }The full token scheme — all 35 shipped ramps, tone conventions, and the Palette Generator that exports these files — is documented on Colors.
UIColor is serializable and works in the Unity Inspector:
public class MyComponent : MonoBehaviour
{
[SerializeField] private UIColor _backgroundColor;
[SerializeField] private UIColor _borderColor;
[SerializeField] private UIColor _textColor;
}UIColor earns its keep when the color is decided by data at runtime — something USS alone can't express. Static state styling (hover, pressed, focus) does not belong here: declare those with :hover / :active / :focus pseudo-class rules in USS instead of C# callbacks (see UI Toolkit Basics — Pseudo-classes).
A typical data-driven case — item slots tinted by rarity, with the rarity→color mapping tuned in the Inspector:
using UnityEngine;
using UnityEngine.UIElements;
using CupkekGames.Luna;
public class RarityColorizer : MonoBehaviour
{
// Designers tune the mapping in the Inspector — no USS edits needed.
[SerializeField] private UIColor _commonColor = new UIColor("slate", UIColorValue.V_500);
[SerializeField] private UIColor _rareColor = new UIColor("sky", UIColorValue.V_500);
[SerializeField] private UIColor _legendaryColor = new UIColor("amber", UIColorValue.V_400);
private UIColor _applied;
// Call when binding item data to a slot element.
public void ApplyRarity(VisualElement slot, int rarity)
{
if (_applied != null)
{
slot.RemoveFromClassList(_applied.GetUssClassBorder());
slot.RemoveFromClassList(_applied.GetUssClassText());
}
_applied = rarity switch
{
2 => _legendaryColor,
1 => _rareColor,
_ => _commonColor,
};
slot.AddToClassList(_applied.GetUssClassBorder()); // e.g. border-amber-400
slot.AddToClassList(_applied.GetUssClassText()); // e.g. text-amber-400
}
}Because the classes resolve through your theme's --color-* variables, a reskin (or a colorblind-mode palette swap) recolors every rarity tint without touching this code.
--color-* variables + utility classes) and reference them by name--color-{name}-{tone} reference and the Palette GeneratorSettings
Theme
Light
Contrast
Material
Dark
Dim
Material Dark
System
Sidebar(Light & Contrast only)
Font Family
DM Sans
Wix
Inclusive Sans
AR One Sans
Direction