GGUI/Public/UIStyle.h file

Styles: how a class of element looks.

styles.Token("accent", GGColor::Hex(0x8B5CF6FF));
styles.Token("radius", 5.0f);

styles.Rule("button",         { .Fill = Token("surface-raised"), .Radius = Token("radius") });
styles.Rule("button:hover",   { .Fill = Token("surface-hover") });   // sets one property; the rest carry over
styles.Rule("button primary", { .Fill = Token("accent") });          // an element with both classes
styles.Rule("textfield::text", { .Text = Token("text") });           // a part of a widget

Selector: one or more classes, any number of states, at most one part.

class class:state:state::part        states: hover pressed focus checked disabled

An element's style is every matching rule layered together. Precedence: more classes, then the higher-priority state, then the later rule. A rule only sets the properties it names.

There are no descendant selectors. A style depends only on the element's classes, state, and part, never on where it sits in the tree.

Elements take classes as space-separated text: .Class = "button primary". Widget parts use "::".

Style sheet syntax (StyleTable::SetSheet):

@tokens {
    surface:       #20242E;
    accent:        #2D7FF9;
    accent-strong: accent;          /* alias */
    radius:        5;
}

button, dropdown {
    fill:       surface;
    border:     1 #4C566A;          /* width, colour, or both */
    radius:     radius;
    padding:    4 10;               /* vertical, horizontal */
    transition: fill 80ms, border 80ms ease-out;
}
button:hover       { fill: #3B4252; }
button primary     { fill: linear-gradient(180deg, accent, #1B5FD0); }
button:focus       { outline: 2 #EBCB8B; }
popup              { shadow: 0 4 12 #00000080; }
textfield::text    { color: #ECEFF4; font: mono; font-size: 13; }

Colours     #RGB  #RGBA  #RRGGBB  #RRGGBBAA  rgb(r, g, b)  rgba(r, g, b, a)  transparent, or a token
Lengths     UI units: 8 or 8px, or a token
Times       80ms  0.2s
States      :hover  :pressed (or :active)  :focus  :checked  :disabled

fill (or background)   colour, or linear-gradient([180deg | to right, ] from, to)
border, outline        colour, width, or both;  border-width, outline-width
radius (or border-radius)
shadow (or box-shadow) x, y, blur, colour; or none
color, font, font-size                       inherited by children
accent, knob                                 colours a widget uses for its own parts
padding, gap, min-width, min-height          applied only where the builder set none
width, height          length, 50%, grow, grow 2, fit;  align, justify: start, center, end,
                       stretch, baseline. Applied only where the builder set none
transition             property (fill border color accent knob radius outline shadow all),
                       duration, and ease-out (the default), ease-in-out, ease-in, linear, or
                       step; comma-separated; or none

Comments are /* ... */ or //. A sheet that fails to parse changes nothing.

Namespaces

namespace GGUI

Classes

struct GGUI::GGToken
A named style value (colour, length, number). Rules reference tokens; a theme defines them.
struct GGUI::GGEdges
Per-side spacing, e.g. padding.
struct GGUI::GGSize
Size along one axis. A bare number is a fixed size (.Width = 84); otherwise GGSize::Grow() etc., or the short names in GGUI::StyleKeywords.
struct GGUI::GGFont
A font by the name the font loader registered: .Font = FontNamed("mono").
struct GGUI::GGTransitions
Per-property transition durations for a rule:
template<typename T>
struct GGUI::GGStyleValue
One rule property: unset, a literal value, or a token.