Guides
Styling and themes
Backgrounds, borders, shadows and gradients, and the theme that follows the desktop.
Background, Border, Radius, Shadow and Opacity style an
element's box, and Cursor sets the pointer over it:
ui.Column(c).Padding(18).Gap(12).Radius(10).
Background(t.Background).Border(1, t.Border).
Shadow(0, 1, 3, 0, ui.RGBA(0, 0, 0, 0.06))- Borders.
Border(1, c)draws one inside every edge;BorderWidthsets the sides apart, CSS style, withBorderColor, as a line under a header withBorderWidth(0, 0, 1, 0), andBorderStyle(ui.BorderDashed)dashes it. - Shadows.
Shadow(x, y, blur, spread, c)casts a box shadow, as CSS'sbox-shadowdoes: several stack, and each shows only outside the box, so a translucent background never shows its own shadow through. - Gradients and stripes.
Gradient(from, to, angle)fills the box with a linear gradient;LinearGradientalso places its colors along the line (Start,End) and mixes them in Oklab, which keeps their lightness, instead of sRGB.Stripes(c, width, gap, angle)draws stripes over the background, as on what is unavailable. - Materials.
Material(m)fills the box with a material a package paints, in place of a background, as the glass plugin's Liquid Glass, which what is under it shows through, frosted and bent along its edges. - Pointer.
Cursortakes the shapes of the platforms:CursorPointer,CursorText,CursorMove,CursorGrabandCursorGrabbing, the resize cursors (both ways, toward one side asCursorResizeE, and of columns and rows),CursorCopyandCursorAliasfor drops,CursorContextMenu,CursorVerticalText,CursorNotAllowed,CursorCrosshair, andCursorNone, which hides it.
Colors come from ui.RGB, ui.RGBA and ui.Hex("#2563eb"); Mix blends
two, and Alpha makes one translucent.
State, not selectors
There are no style sheets and no state selectors: the view is code, so an
element's look follows the state in the view itself, as
if row.Hovered() { row.Background(t.SurfaceHover) }, and one element's
state can style another, as a group's hover does in CSS.
A widget returns its element, so a call after it styles it differently
from the rest: ui.Button(c, "Save").Padding(10, 20).Radius(999). For a
look of your own, build on the widgets' bases, which have none: see
custom widgets.
Themes
Widgets take their colors and metrics from the theme, c.Theme(): the
light or the dark theme, following the system's appearance as it changes,
and the settings of the desktop that the system's own controls follow. Use
its colors in your own elements so they follow too. To change it, set a
copy:
t := *c.Theme() // the default, which follows the system
t.Accent, t.Radius = ui.Hex("#7c3aed"), 8
t.Spacing = 3 // compact
c.SetTheme(&t)Spacing is the unit of the room widgets leave: their paddings and gaps,
and the sizes of check boxes, switches, sliders and the rows of tables and
trees, are multiples of it. It is 4 by default; 3 makes every widget
compact, 5 roomy. FontSize sizes their text, Radius rounds their
corners, and ScrollbarWidth sets the width of scroll bars. On macOS,
rounded corners, the widgets' and your elements', curve continuously as
AppKit's and SwiftUI's do, and elsewhere as quarter circles, as Windows
and GTK draw them. Size your own
elements with the theme too, and they follow it: t.Space(3) is three
units of its spacing, and t.Rem(2) twice its font size, as CSS's rem.
The desktop's preferences
c.Preferences() returns the settings of the desktop, which the default
theme follows and a frame follows the changes of:
Accent. The accent color the user chose (macOS, Windows, and desktops whose portal gives one, as GNOME 47 and KDE do), which colors primary buttons, the choice and the focus ring, with text on it that stands out.HighContrast. macOS's Increase Contrast, Windows's contrast themes, the portal's higher contrast: borders and secondary text are darker (lighter in the dark), and the focus ring opaque.TextScale. Windows's and GNOME's text size:FontSizeis that many times larger.ReduceMotion. macOS's Reduce Motion, Windows's animation effects and GNOME's animations turned off:Animategoes to its target at once.