Styling & Layout
Chain style methods on elements or on ui.Style(). Append children with .Child(...) or .Children(...), and reuse a style with .Style(shared).
return ui.View().Children(ui.Text("hello"), ui.Input().Value("xxx")).
FlexCol().PaddingLeft(20).RoundedLg().TextAlign("center")#Style modifiers
Later values override the same property. Lengths are logical pixels; strings also accept percentages.
func Card() *ui.Element {
return ui.View().Child(ui.Text("Hello").TextColor("#e2e8f0")).
Padding(20).BorderRadius(12).Bg("#111827")
}Helpers such as .FlexCol(), .P4(), .GridCols(3), and .RoundedLg() match the TypeScript presets.
#Merging styles
.Style(base).Style(overrides) applies declarations in order. Use .Merge(...) to combine reusable builders.
func MergedCard() *ui.Element {
base := ui.Style().Padding(20).BorderRadius(8).Bg("#111827")
overrides := ui.Style().BorderRadius(12)
return ui.View().Child("Merged styles").Style(base).Style(overrides)
}#Reusable styles
ui.Style() returns a value. Methods return a new value, so a shared style is never mutated. Assign the result when you derive a variation.
func SharedCard() *ui.Element {
card := ui.Style().Padding(20).BorderRadius(12)
emphasized := card.PaddingLeft(28).Bg("#1e293b")
return ui.View().Gap(12).Children(
ui.View().Child("Hello").Style(card).Bg("#111827"),
ui.View().Child("Another card").Style(emphasized),
)
}.When(condition, style) applies extra styles while the condition is true. For a reactive condition, pass a getter: .When(selected, ui.Style().Bg("#2563eb")). Passing width() during setup captures the current number; pass width (the getter) when it should stay live.
#Flexbox
.Flex(), .FlexRow(), or .FlexCol() start a flex layout. Give scrolling children .MinHeight(0) or .MinWidth(0) so they can shrink.
func Row() *ui.Element {
return ui.View().Children(
ui.Text("Flexible content").Flex1().MinWidth(0),
ui.Button().Child("Action").FlexShrink(0),
).Flex().Gap(12).ItemsCenter()
}#Grid
func Grid() *ui.Element {
return ui.View().Children(ui.Text("Sidebar"), ui.Text("Content")).
Display("grid").GridTemplateColumns("220px 1fr").Gap(16)
}.GridCols(3) and .ColSpanFull() are also available.
#Text and color
Typography inherits to children. Colors accept hex, rgb() / rgba(), or packed RGBA values. Padding and borders do not inherit.
func TypographyExample() *ui.Element {
return ui.View().Children(
ui.Text("Inbox").FontSize(24).FontWeight(600),
ui.Text("All caught up."),
).TextColor("#334155").FontSize(14).Padding(20)
}#Interaction states
Use .Hover(...), .Active(...), .FocusStyle(...), .DisabledStyle(...), and .SelectedStyle(...). Add .Transition(...) on the base style to animate paint changes. See Transitions & Animation.
func SelectableButton() *ui.Element {
selected, setSelected := ui.CreateSignal(false)
button := ui.Style().Padding(12).Bg("#e5e7eb").
Hover(func(s ui.StyleBuilder) ui.StyleBuilder { return s.Opacity(0.85) })
return ui.Button().Child("Toggle selection").Style(button).
When(selected(), ui.Style().Bg("#2563eb").TextColor("white")).
OnClick(func() { setSelected(!selected()) })
}#Groups and named group hover
.Group(true) marks an unnamed group; .Group("card") names it. .GroupHover(...) follows the nearest ancestor group. .GroupHoverNamed("card", ...) follows the nearest ancestor with that name.
func GroupExample() *ui.Element {
return ui.View().Child(
ui.Text("Changes when the card is hovered").
TextColor("#64748b").
GroupHoverNamed("card", func(s ui.StyleBuilder) ui.StyleBuilder {
return s.TextColor("#2563eb")
}),
).Group("card").Padding(20)
}.GroupActive(...) and .FocusWithin(...) work the same way for pressed and focused groups. These states accept paint properties; they cannot set the cursor.
