Documentation
¶
Overview ¶
Package theme holds the colors, text sizes and fonts every UI module reads. Apply changes the global palette under the UI frame lock.
Index ¶
- Constants
- Variables
- func Apply(p Palette)
- func CurrentName() string
- func FetchFonts(urls ...string) error
- func FollowSystemMotion()
- func LoadFonts(files ...[]byte) error
- func Names() []string
- func NewShaper(extra ...font.FontFace) *text.Shaper
- func RGB(c uint32) color.NRGBA
- func Register(name string, p Palette)
- func Revision() uint64
- func Scope(p Palette) (restore func())
- func SetReducedMotion(reduce bool)
- func SetSystemReducedMotion(reduce bool)
- func Use(name string) error
- type Elevation
- type Gradient
- type Palette
- type ThemeWatcher
Constants ¶
const ( RadiusSm = 4 // small marks: links, keycaps, compact chips RadiusMd = 6 // controls: buttons, fields, menu items RadiusLg = 8 // cards, popovers, menus, navigation rows RadiusXl = 12 // dialogs, sheets, chat bubbles RadiusFull = 9999 )
Radius steps, in dp. RadiusFull makes a pill or a circle: el clamps a radius to half the shorter side.
const ( TextXs = 11 // axis labels, badges TextSm = 12 // captions, errors, group titles TextMd = 13 // secondary text TextControl = 14 // buttons, tabs, toggles TextBody = 15 // body text TextLg = 17 // panel and dialog titles TextXl = 20 // page titles TextHeading = 22 )
Text size steps, in sp. BodySize, SmallSize and HeadingSize are TextBody, TextMd and TextHeading.
const ( SpaceXxs = 2 // hairline gaps: stacked labels, tight icon pairs SpaceXs = 4 // inside compact controls, between a label and its hint SpaceSm = 6 // between an icon and its text SpaceMd = 8 // between controls in a row, list rows SpaceLg = 12 // control padding, between form fields SpaceXl = 16 // card padding, between groups Space2xl = 24 // dialog and page padding, between sections Space3xl = 32 // between page regions )
Spacing steps, in dp, for gaps, padding and margins. Most layouts need only Xs to Xl; off-scale values are for optical adjustments such as centering an icon.
const ( BodySize unit.Sp = 15 SmallSize unit.Sp = 13 HeadingSize unit.Sp = 22 // ControlHeight is the height of every single-line field: inputs, // selects, pickers and search boxes, so fields side by side line up. ControlHeight unit.Dp = 36 )
Text sizes.
const Face font.Typeface = "PingFang SC, Hiragino Sans GB, Microsoft YaHei, Noto Sans CJK SC, Noto Sans SC, Go"
Face lists font families in priority order. Pinning a CJK family avoids tofu from a system fallback font that lacks some simplified Chinese glyphs.
const MonoFace font.Typeface = "SF Mono, Menlo, Cascadia Mono, Consolas, DejaVu Sans Mono, Go Mono, PingFang SC, Microsoft YaHei, Noto Sans CJK SC"
MonoFace lists monospaced families for code, numbers in columns and keycaps; CJK falls back to Face's fonts.
Variables ¶
var ( ElevationSm = Elevation{Offset: 1, Blur: 3} // cards that lift on hover ElevationMd = Elevation{Offset: 4, Blur: 12} // popovers, menus, dropdowns, toasts ElevationLg = Elevation{Offset: 12, Blur: 32} // dialogs, sheets, command palette )
Elevation steps: menus and popovers float a little, dialogs more.
var ( Bg = RGB(0xf5f6f8) // window background Surface = RGB(0xffffff) // cards and fields Border = RGB(0xe3e5e8) // borders and dividers Text = RGB(0x1f2328) // body text Muted = RGB(0x6b7280) // secondary text, hints, unchecked icons Primary = RGB(0x2563eb) // primary buttons, links, focus, checked icons DangerText = RGB(0xb91c1c) // danger text on surfaces PrimaryText = RGB(0x1d4ed8) // text on selected surfaces CodeBg = RGB(0xf0f1f3) CodeText = RGB(0x1f2328) PrimaryHover = RGB(0x1d4ed8) DangerHover = RGB(0xb91c1c) SubtleHover = RGB(0xe2e5e9) Success = RGB(0x15803d) // positive status Warning = RGB(0xa16207) // caution status Info = RGB(0x0369a1) // informational status Danger = RGB(0xdc2626) // danger buttons Subtle = RGB(0xeceef1) // secondary buttons OnColor = RGB(0xffffff) // text on Primary and Danger Highlight = RGB(0xdbeafe) // selected rows and options Scrim = color.NRGBA{A: 0x66} // dims the window behind a dialog Shadow = color.NRGBA{R: 0x10, G: 0x18, B: 0x28, A: 0x2e} // tints raised surfaces' shadows // Chart is the categorical order for data series; see Palette.Chart. Chart = Light().Chart // BgGradient and PrimaryGradient are optional; see Palette. BgGradient, PrimaryGradient Gradient )
Colors. Components read them at layout time.
var Material = newMaterial()
Material is the underlying Gio theme: text shaper and icons.
var ReducedMotion bool
ReducedMotion is the effective preference. It follows the system by default; SetReducedMotion gives the application an explicit override.
Functions ¶
func Apply ¶
func Apply(p Palette)
Apply synchronously replaces the global palette and redraws every window. Call before opening windows or from a UI callback under the frame lock. Other goroutines must use core.Update(func() { theme.Apply(p) }). Apply never acquires the frame lock itself, so callbacks cannot deadlock on it. Fonts, the text shaper and the Material pointer remain unchanged.
func CurrentName ¶
func CurrentName() string
CurrentName is the theme last chosen with Use; "light" by default. Apply with an unnamed palette does not change it.
func FetchFonts ¶
FetchFonts is for WebAssembly builds, where it downloads font files with the browser. Elsewhere it returns an error: read the files and LoadFonts.
func FollowSystemMotion ¶
func FollowSystemMotion()
FollowSystemMotion removes the application override and applies the latest system value. Unsupported platforms default to allowing motion.
func LoadFonts ¶
LoadFonts adds font files (TTF, OTF or TTC collections) to the text shaper and redraws every window. Text picks them by family name from Face, so load a family listed there, such as Noto Sans SC. A web build needs this: the browser gives a WebAssembly app no system fonts, and without a CJK font Chinese shows as boxes. Desktop apps can use it to ship a font.
Call it before window.Main or from a callback; from another goroutine wrap it in core.Update, like Apply.
func NewShaper ¶
NewShaper builds an independent shaper with extra faces ahead of the fonts loaded through LoadFonts and the Go fallback fonts. System font fallback follows the same platform defaults as Material.Shaper.
func Register ¶
Register adds a named palette, or replaces one, for Named and Names; an app offers them in its theme picker. Built in: light, dark, nord, paper, solarized-dark, high-contrast and aurora (with gradients).
func Revision ¶
func Revision() uint64
Revision changes whenever Apply replaces the palette. Use it in custom render cache keys. Read under the UI lock, like Current.
func Scope ¶
func Scope(p Palette) (restore func())
Scope sets the palette for a part of the window and returns the function that puts the previous one back. el.Themed uses it around a subtree's Render and paint, so the rest of the window keeps its colors; it does not redraw anything. Call it under the frame lock and always restore.
func SetReducedMotion ¶
func SetReducedMotion(reduce bool)
SetReducedMotion overrides the system preference. Call under the UI frame lock.
func SetSystemReducedMotion ¶
func SetSystemReducedMotion(reduce bool)
SetSystemReducedMotion is the window backend's preference bridge. Native changes are remembered while an application override is active.
Types ¶
type Elevation ¶
type Elevation struct{ Offset, Blur float32 }
Elevation is a soft shadow under a raised surface, in dp: Offset moves it down, Blur is how far it fades out. Its color is Shadow.
type Gradient ¶
Gradient is a linear blend from From to To. Angle is in degrees: 0 runs left to right, 90 top to bottom. The zero Gradient means none.
type Palette ¶
type Palette struct {
PrimaryText, DangerText, CodeBg, CodeText color.NRGBA
Bg, Surface, Border, Text, Muted color.NRGBA
Primary, PrimaryHover, Danger, DangerHover color.NRGBA
Success, Warning, Info color.NRGBA
Subtle, SubtleHover, OnColor, Highlight, Scrim color.NRGBA
// Shadow tints the shadows of raised surfaces (Elevation); dark themes
// need a stronger one to read against a dark background.
Shadow color.NRGBA
// Chart is the categorical order for data series: slot i always means
// series i. Validated for color-vision deficiency against Surface.
Chart [8]color.NRGBA
// BgGradient, when set, paints the window background instead of Bg;
// PrimaryGradient paints primary buttons, progress bars and the user's
// chat bubbles instead of Primary. Bg and Primary stay the solid colors
// for everything else, so set them to a color from the gradient.
BgGradient, PrimaryGradient Gradient
}
Palette contains every global color token. Start from Light or Dark when customizing: Apply replaces all colors, including zero (transparent) values.
func Current ¶
func Current() Palette
Current returns a copy of the current colors. Read it under the UI lock, like the public color variables, or before opening the first window.
func ParseTheme ¶
ParseTheme reads a theme file: a base palette ("light" or "dark", or any registered name) and the colors it changes, by Palette field name in any case, as #rgb, #rgba, #rrggbb or #rrggbbaa. Chart takes up to eight colors; bgGradient and primaryGradient take {"from", "to", "angle"}.
{"name": "Nord", "base": "dark",
"colors": {"bg": "#2e3440", "surface": "#3b4252", "primary": "#88c0d0",
"bgGradient": {"from": "#2e3440", "to": "#3b4252", "angle": 90}}}
type ThemeWatcher ¶
type ThemeWatcher struct {
// contains filtered or unexported fields
}
ThemeWatcher keeps the themes in a directory registered while their files change, e.g. so a designer sees a theme file update the running app.
func WatchThemes ¶
func WatchThemes(dir string, interval time.Duration, onChange func(names []string, err error)) (*ThemeWatcher, error)
WatchThemes registers every *.json theme file in dir now, then checks the directory every interval (default one second) for added, changed or removed files. Changes are registered on the next frame, under the frame lock; if the theme in use (CurrentName) changed, it is applied again. onChange, if set, runs then too with the changed theme names, or with the error of a file that failed to parse; the other files still load.
It polls instead of using file system events, so it needs nothing but the standard library and works the same on every platform.
func (*ThemeWatcher) Stop ¶
func (w *ThemeWatcher) Stop()
Stop ends the watching; registered themes stay.