styles¶
every blob takes init-only properties. you've already seen them: Padding, BackgroundColor, BorderRadius. this article covers how to keep them dry across many blobs, plus a full property reference for each blob.
the basics¶
set what you need:
new Container { Padding = 16, BackgroundColor = Color.White, BorderRadius = 8 }
nullable properties you don't set fall back to the engine default.
a few behavior rules worth knowing:
-
shorthand vs per-edge - when both are set, the per-edge value wins.
new Container { Padding = 16, PaddingTop = 32 } // 32 top, 16 elsewheresame rule for
Margin,BorderColor,BorderWidth,BorderRadius, andGap. -
FlexDirection - defaults to
Row. this is the only non-nullable property. -
font inheritance.
FontFamily,FontSize, and the rest of the font family set on aContainerapply to descendantTextblobs through the engine.
tokens¶
instead of repeating literal values, declare them once and reference them everywhere:
internal static class Tokens
{
public static readonly Color CardBg = Color.White;
public static readonly Color TextDark = Color.FromBytes(0x09, 0x0B, 0x10, 255);
public static readonly Length CardPad = 16f;
public static readonly Length CardGap = 8f;
public const string FontDisplay = "Space Grotesk";
public const int WeightSemibold = 600;
}
new Container
{
BackgroundColor = Tokens.CardBg,
FontColor = Tokens.TextDark,
Padding = Tokens.CardPad,
Gap = Tokens.CardGap,
FontFamily = Tokens.FontDisplay,
}
Length accepts float implicitly (pixels), so static readonly Length CardPad = 16f works.
int-typed properties (FontWeight, TransitionMs, Order, ZIndex) and string-typed ones (FontFamily, Cursor, animation names) can be const.
helpers¶
the more reusable unit is a function that returns a fully-styled blob, children included. extract once, call wherever:
public class CardListUI : GooPanel<Container>
{
protected override Container Build() => new Container
{
FlexDirection = FlexDirection.Column,
Gap = 12,
Children =
{
Card("welcome", "first card"),
Card("status", "second card"),
},
};
static Container Card(string title, string body) => new Container
{
FlexDirection = FlexDirection.Column,
BackgroundColor = Color.White,
BorderRadius = 8,
Padding = 16,
Gap = 8,
Children =
{
new Text(title) { FontWeight = 600 },
new Text(body),
},
};
}
caveat only Container carries pooled storage. its children list comes from a per-frame pool that's alive only while Build() is running. helpers that build a Container must be called from inside Build().
static readonly Container Header = new Container { ... }; crashes at static init. so does keeping a Container reference between rebuilds. the children list goes back to the pool the moment Build() returns.
Text and Image have none of this. no children, no pool. build them as static readonly fields.
the reusable unit is the function that builds the Container, not the Container itself.
reference¶
every property each blob exposes, grouped by family: