UI Color System

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.

Overview

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.

Color Names

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.

UIColorValue Enum

Color intensity values (50-950):

ValueDescription
V_50Lightest
V_100Very light
V_200Light
V_300Light-medium
V_400Medium-light
V_500Medium (default)
V_600Medium-dark
V_700Dark
V_800Very dark
V_900Darkest
V_950Near black

UIColor Class

Combines a color name and value to generate USS class names.

Constructor

csharp
public UIColor() // Default: "sky", V_50 public UIColor(string name, UIColorValue value)

Methods

MethodReturnsExample Output
GetUssClassBG()Background classbg-blue-500
GetUssClassBorder()Border classborder-blue-500
GetUssClassText()Text classtext-blue-500
GetUssClassImageTint()Tint classtint-blue-500
GetColor(VisualElement)Unity ColorReads from USS variables

Basic Usage

csharp
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); } } }

Dynamic Color Changes

csharp
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()); }

Getting Unity Color

To get the actual Unity Color value from USS variables:

csharp
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}.

Generated USS Classes

The system generates classes following this pattern:

TypePatternExample
Backgroundbg-{name}-{value}bg-sky-500
Borderborder-{name}-{value}border-red-600
Texttext-{name}-{value}text-slate-100
Tinttint-{name}-{value}tint-green-400

For the special name transparent, the value suffix is omitted:

  • bg-transparent
  • border-transparent
  • text-transparent
  • tint-transparent

USS Variables

Each generated class is a one-property route onto a --color-{name}-{tone} token:

css
: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.

Inspector Integration

UIColor is serializable and works in the Unity Inspector:

csharp
public class MyComponent : MonoBehaviour { [SerializeField] private UIColor _backgroundColor; [SerializeField] private UIColor _borderColor; [SerializeField] private UIColor _textColor; }

Example: Data-Driven Rarity Colors

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:

csharp
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.

Tips

  • Color names are plain strings — they must match a family in your theme's USS palette
  • For theme-able elements, define your own semantic families (custom --color-* variables + utility classes) and reference them by name
  • The 500 value is typically the "default" shade of each color
  • Lower values (50-400) are lighter, higher values (600-950) are darker

See also

  • Colors — the full --color-{name}-{tone} reference and the Palette Generator
  • Theme Stack — where custom color families and overrides live
  • UI Toolkit Basics — the class-toggling pattern this system builds on

Settings

Theme

Light

Contrast

Material

Dark

Dim

Material Dark

System

Sidebar(Light & Contrast only)

Light
Dark

Font Family

DM Sans

Wix

Inclusive Sans

AR One Sans

Direction

LTR
RTL