ui

package
v0.0.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package ui is Nimbus Native's component layer: apps describe their screens as Go components, and the runtime keeps real native views (UIKit, Android Views) in step with them.

Everything happens on one goroutine, the UI loop: host events, state updates, rendering, layout and effects. A render reconciles the new element tree against the one on screen, lays it out with the layout package, and sends the differences to the host as one render.Commit.

Index

Constants

View Source
const (
	FitCover   = render.FitCover   // fills the frame, cropping what's over
	FitContain = render.FitContain // fits inside, showing all of it
	FitStretch = render.FitStretch // stretches to the frame
)

How an image fills its frame.

View Source
const (
	Began     = Phase(render.GestureBegan)     // a finger came down and started moving
	Changed   = Phase(render.GestureChanged)   // it moved
	Ended     = Phase(render.GestureEnded)     // it lifted
	Cancelled = Phase(render.GestureCancelled) // the system took it away
)
View Source
const (
	Column = layout.Column
	Row    = layout.Row

	JustifyStart        = layout.JustifyStart
	JustifyCenter       = layout.JustifyCenter
	JustifyEnd          = layout.JustifyEnd
	JustifySpaceBetween = layout.JustifySpaceBetween
	JustifySpaceAround  = layout.JustifySpaceAround
	JustifySpaceEvenly  = layout.JustifySpaceEvenly

	AlignStretch = layout.AlignStretch
	AlignStart   = layout.AlignStart
	AlignCenter  = layout.AlignCenter
	AlignEnd     = layout.AlignEnd
)
View Source
const (
	BlurNone      = render.BlurNone
	BlurUltraThin = render.BlurUltraThin
	BlurThin      = render.BlurThin
	BlurRegular   = render.BlurRegular
	BlurThick     = render.BlurThick
	BlurGlass     = render.BlurGlass // Liquid Glass on iOS 26+; elsewhere a thin blur, tinted
)
View Source
const (
	CornerTopLeft     Corners = render.CornerTopLeft
	CornerTopRight    Corners = render.CornerTopRight
	CornerBottomRight Corners = render.CornerBottomRight
	CornerBottomLeft  Corners = render.CornerBottomLeft

	CornersLeft   = CornerTopLeft | CornerBottomLeft
	CornersRight  = CornerTopRight | CornerBottomRight
	CornersTop    = CornerTopLeft | CornerTopRight
	CornersBottom = CornerBottomLeft | CornerBottomRight
)
View Source
const Forever = -1

Forever repeats an animation until its canvas leaves the screen.

Variables

View Source
var (
	LightTheme = Theme{
		Background: Hex("#f9fafb"), Surface: Hex("#ffffff"), Text: Hex("#111827"), TextMuted: Hex("#6b7280"),
		Border: Hex("#e5e7eb"), Primary: Hex("#2563eb"), OnPrimary: Hex("#ffffff"), Danger: Hex("#dc2626"),
		Bar: Hex("#ffffff"), BarText: Hex("#111827"), Success: Hex("#16a34a"), Warning: Hex("#d97706"),
		Radius: 12, Title: 24, Heading: 17, Body: 15, Caption: 13, SpaceS: 8, SpaceM: 12, SpaceL: 20,
	}
	DarkTheme = Theme{
		Dark:       true,
		Background: Hex("#0b0f17"), Surface: Hex("#151b26"), Text: Hex("#f3f4f6"), TextMuted: Hex("#9ca3af"),
		Border: Hex("#273041"), Primary: Hex("#3b82f6"), OnPrimary: Hex("#ffffff"), Danger: Hex("#f87171"),
		Bar: Hex("#151b26"), BarText: Hex("#f3f4f6"), Success: Hex("#4ade80"), Warning: Hex("#fbbf24"),
		Radius: 12, Title: 24, Heading: 17, Body: 15, Caption: 13, SpaceS: 8, SpaceM: 12, SpaceL: 20,
	}
)

LightTheme and DarkTheme are the built-in themes.

View Source
var HandleURL func(link string) bool

HandleURL, when set, sees every link first; returning true means it was handled and nothing else happens.

View Source
var Once any = once{}

Once as an Effect dependency runs the effect only after the first render.

View Source
var RestoreRoute func(path string) (title string, screen Component, ok bool)

RestoreRoute turns a path back into a screen. router.Register sets it.

View Source
var StaleAfter = 30 * time.Second

StaleAfter is how old cached query data may be before a component that mounts with it fetches again in the background.

Functions

func Effect

func Effect(c *Ctx, fn func(ctx context.Context) func(), deps ...any)

Effect runs fn after a render that changed deps: every render if no deps are given, only the first with ui.Once. fn's context is cancelled — and its returned cleanup called — before it runs again and when the component leaves the screen. Effects run on the UI goroutine; start your own goroutine for slow work and set State from it.

func IconNames added in v0.0.13

func IconNames() []string

IconNames are the built-in icons.

func LinkPath added in v0.0.9

func LinkPath(link string) string

LinkPath is the route path a link points to: a web link's path, or for an app's own scheme the host and path together (myapp://orders/42 is /orders/42).

func Main

func Main()

Main is for the app's main function: func main() { ui.Main() }. On a device the host owns the process and main never runs; under `nimbus native dev` the app runs on the laptop and Main serves the device until it reloads.

func Memo

func Memo[T any](c *Ctx, fn func() T, deps ...any) T

Memo returns fn's result, computing it again only when deps change.

func Mount

func Mount(root Component)

Mount makes root the app's UI. Call it from init; the UI loop starts when the host starts the runtime.

func Reducer

func Reducer[T any](c *Ctx, initial T) (T, func(func(T) T))

Reducer is State for values updated by a function of the old value: update(func(n int) int { return n + 1 }) never loses an increment, even when called many times before the next render.

func Ref

func Ref[T any](c *Ctx, initial T) *T

Ref is a value that survives re-renders without causing them.

func RefetchQuery

func RefetchQuery(c *Ctx, key string)

RefetchQuery fetches the query with this key again (after a change, say), re-rendering every component that shows it.

func SessionValue

func SessionValue(c *Ctx, key any) any

SessionValue is the value the session was started with under key (see SessionOptions.Values), or nil on a device.

func SetTheme

func SetTheme(light, dark Theme)

SetTheme replaces the light and dark themes. Call it from init, next to Mount.

func State

func State[T any](c *Ctx, initial T) (T, func(T))

State is a value that survives re-renders. Calling set — from any goroutine — stores the new value and schedules a render.

Types

type Accordion added in v0.0.13

type Accordion struct {
	Items  []AccordionItem // Each a Title and Content
	Single bool            // Opening one closes the rest
	Open   int             // the one open at the start; 0 for the first, -1 for none
}

Accordion is a list of headings that open in place. With Single, opening one closes the rest.

func (Accordion) Render added in v0.0.13

func (a Accordion) Render(c *Ctx) Component

type AccordionItem added in v0.0.13

type AccordionItem struct {
	Title   string    // Its heading
	Content Component // What opens under it
}

AccordionItem is a heading and what it opens.

type Action

type Action[A, R any] struct {
	Run     func(A) // starts the action (ignored while it runs)
	Running bool
	Err     error // the last run's error
	Result  R     // the last successful run's result
}

Action is a UseAction's state.

func UseAction

func UseAction[A, R any](c *Ctx, do func(ctx context.Context, arg A) (R, error), onDone ...func(R)) Action[A, R]

UseAction runs a write — placing an order, saving a profile — off the UI goroutine and re-renders with its progress. onDone, if given, runs on the UI goroutine after a success (e.g. to RefetchQuery or close a modal).

place := ui.UseAction(c, func(ctx context.Context, o NewOrder) (Order, error) {
	return api.Call(ctx, client, shared.CreateOrder, o)
}, func(Order) { ui.RefetchQuery(c, "orders"); modals.Dismiss() })

type Align

type Align = layout.Align

Layout vocabulary, re-exported so apps only import ui.

type Anim added in v0.0.13

type Anim struct {
	// contains filtered or unexported fields
}

Anim is an animation of a canvas: Range turns it into the numbers it moves through.

func UseAnimation added in v0.0.13

func UseAnimation(c *Ctx, a Animation) Anim

UseAnimation is an animation that starts when a canvas using it first shows, and runs as a says:

spin := ui.UseAnimation(c, ui.Animation{Ms: 1000, Ease: ui.Linear, Repeat: ui.Forever})
ui.Canvas(40, 40, func(p *ui.Painter) {
	p.Motion(ui.Motion{X: ui.Fixed(20), Y: ui.Fixed(20), Rotate: spin.Range(0, 360)})
	p.Arc(0, 0, 16, 0, 270)
	p.Stroke(4, th.Primary)
	p.Restore()
}, ui.Style{})

func (Anim) Play added in v0.0.13

func (a Anim) Play()

Play runs the animation again from the start.

func (Anim) Range added in v0.0.13

func (a Anim) Range(from, to float32) Num

Range is the animation moving from from to to (and back, if it reverses).

type Animation added in v0.0.13

type Animation struct {
	Ms      int     // how long one run takes; 0 means 300
	Delay   int     // milliseconds before the first run
	Ease    Ease    // EaseInOut when unset
	Bounce  float32 // Spring only: 0 settles without overshooting, 0.5 bounces well
	Repeat  int     // more runs after the first; Forever
	Reverse bool    // every other run goes backward
	OnDone  func()  // after the last run (never for Forever)
}

Animation is how a canvas animates a number: the phone runs it, frame by frame, without a render from Go.

type AppBar added in v0.0.13

type AppBar struct {
	Title    string      // The screen's name
	Subtitle string      // Under it
	OnBack   func()      // adds a back arrow
	Leading  Component   // or anything else at the start
	Actions  []Component // at the end
	Large    bool        // the title on its own line, larger
}

AppBar is a screen's top bar when it has no navigation Stack of its own:

ui.AppBar{Title: "Orders", Actions: []ui.Component{ui.IconButton{Icon: "search", Label: "Search"}}}

func (AppBar) Render added in v0.0.13

func (b AppBar) Render(c *Ctx) Component

type Avatar added in v0.0.13

type Avatar struct {
	Name  string  // Gives the initials and the color, and is read aloud
	Image string  // a picture's URL
	Size  float32 // 0 means 40
}

Avatar is a person: their picture, or their initials on a color of their own:

ui.Avatar{Name: "Asha Rao", Size: 44}

func (Avatar) Render added in v0.0.13

func (a Avatar) Render(c *Ctx) Component

type Badge added in v0.0.13

type Badge struct {
	Label string // The words
	Tone  Tone   // Neutral, Accent, Good, Caution or Bad
	Solid bool   // white on the tone's color, for a count on an icon
}

Badge is a small status label:

ui.Badge{Label: "Paid", Tone: ui.Good}

func (Badge) Render added in v0.0.13

func (b Badge) Render(c *Ctx) Component
type Banner struct {
	Title    string // What happened
	Message  string // More about it
	Tone     Tone   // Sets its color and mark
	Action   string // A link's label
	OnAction func() // Called on a tap
	OnClose  func() // Adds a close button
}

Banner is a message in the page that stays until it's dealt with:

ui.Banner{Tone: ui.Caution, Title: "You're offline", Message: "Orders will send when you're back."}

func (Banner) Render added in v0.0.13

func (b Banner) Render(c *Ctx) Component

type BlendMode added in v0.0.13

type BlendMode uint8

BlendMode is how a shape's colors combine with what's under it.

const (
	BlendNormal BlendMode = iota
	BlendMultiply
	BlendScreen
	BlendOverlay
	BlendDarken
	BlendLighten
	BlendColorDodge
	BlendColorBurn
	BlendHardLight
	BlendSoftLight
	BlendDifference
	BlendExclusion
	BlendHue
	BlendSaturation
	BlendColor
	BlendLuminosity
	BlendErase // erases what's under the shape, as much as it's opaque
	BlendAtop  // draws only over what's already drawn
	BlendPlus  // adds the colors
)

type Blur added in v0.0.13

type Blur = render.Blur

Blur is how strongly what is behind a view is blurred (Style.Blur): the platform's materials on iOS, a backdrop blur on Android 12+ and the web. Older Android shows the Background tint alone.

type Button added in v0.0.13

type Button struct {
	Label    string  // The words on it
	Icon     string  // an Icon name, before the label
	OnPress  func()  // Called on a tap
	Variant  Variant // Filled, Tonal, Outlined, Plain or Destructive
	Size     Size    // SizeSmall, SizeMedium or SizeLarge
	Disabled bool    // Dimmed, can't be tapped
	Loading  bool    // A spinner replaces the icon, can't be tapped
	Full     bool    // as wide as its container
}

Button is a tappable action:

ui.Button{Label: "Place order", Icon: "check", OnPress: place}
ui.Button{Label: "Cancel", Variant: ui.Outlined, OnPress: cancel}

While Loading it shows a spinner and can't be tapped.

func (Button) Render added in v0.0.13

func (b Button) Render(c *Ctx) Component

type Cap added in v0.0.13

type Cap uint8

Cap is how a stroke's open ends look.

const (
	CapRound  Cap = iota // a half circle past the end
	CapButt              // square, at the end
	CapSquare            // square, half the width past the end
)
type Carousel struct {
	Pages    []Component // What it shows
	Height   float32     // Its height
	Width    float32     // 0 means the screen's width
	OnChange func(int)   // Called with the new page
}

Carousel shows one page at a time; swipe sideways for the next, with dots to show where you are.

func (Carousel) Render added in v0.0.13

func (r Carousel) Render(c *Ctx) Component

type Checkbox added in v0.0.13

type Checkbox struct {
	Label    string     // Beside the box
	Checked  bool       // Whether it's ticked
	OnChange func(bool) // Called with the new state
	Disabled bool       // Dimmed, can't be changed
}

Checkbox is a tick box with a label:

ui.Checkbox{Label: "Send receipts", Checked: on, OnChange: setOn}

func (Checkbox) Render added in v0.0.13

func (b Checkbox) Render(c *Ctx) Component

type Chip added in v0.0.13

type Chip struct {
	Label    string // The words
	Icon     string // An Icon name
	Selected bool   // Tinted with Primary
	OnPress  func() // Called on a tap
	OnRemove func() // Adds a close button
}

Chip is a compact choice, filter or tag:

ui.Chip{Label: "Vegetarian", Selected: veg, OnPress: toggle}

OnRemove adds a close button.

func (Chip) Render added in v0.0.13

func (p Chip) Render(c *Ctx) Component

type Color

type Color uint32

Color is 0xRRGGBBAA. The zero Color means "unset".

func Hex

func Hex(s string) Color

Hex parses "#rgb", "#rrggbb" or "#rrggbbaa". It panics on bad input, so use it for constants.

func RGB

func RGB(r, g, b uint8) Color

RGB is an opaque color.

type Component

type Component interface {
	Render(c *Ctx) Component
}

Component is a reusable piece of UI. Its fields are its props; Render runs on every render and may call hooks (State, Effect, Memo, Ref) on c.

type Counter struct{ Start int }

func (p Counter) Render(c *ui.Ctx) ui.Component {
	n, setN := ui.State(c, p.Start)
	return ui.Pressable(func() { setN(n + 1) }, ui.Style{},
		ui.Text(fmt.Sprint(n), ui.Style{}))
}

type Corners added in v0.0.13

type Corners uint8

Corners picks the corners Style.Radius rounds.

type Ctx

type Ctx struct {
	// contains filtered or unexported fields
}

Ctx is a component instance's handle for hooks. Hooks must be called in the same order on every render (never inside if or for).

type DateField added in v0.0.13

type DateField struct {
	Label       string          // Above the field
	Placeholder string          // Shown when there's no value
	Value       time.Time       // zero for none
	Mode        dialog.Mode     // dialog.Date, dialog.Time or dialog.DateTime
	Layout      string          // how the value shows; "2 Jan 2006" by default
	OnChange    func(time.Time) // Called with the new value
}

DateField is a field that picks a date or time with the platform's picker:

ui.DateField{Label: "Delivery", Value: at, OnChange: setAt}

func (DateField) Render added in v0.0.13

func (d DateField) Render(c *Ctx) Component

type Direction

type Direction = layout.Direction

Layout vocabulary, re-exported so apps only import ui.

type Divider added in v0.0.13

type Divider struct {
	Inset float32 // space before it, to line up with text in a row
}

Divider is a thin rule between things.

func (Divider) Render added in v0.0.13

func (d Divider) Render(c *Ctx) Component

type Drag added in v0.0.13

type Drag struct {
	Vertical bool    // moves with the finger down, not across
	Min, Max float32 // how far it goes, in the canvas's units
	Handle   string  // the tagged shape (Painter.Tag) it starts on; "" anywhere on the canvas
	// Animation is how it moves to a new value from Go (Repeat and Reverse
	// aside): a snap after OnEnd, say.
	Animation
	// OnEnd gets where it was let go. Give UseDrag that value (or a snapped
	// one) to keep it there; the old value takes it back.
	OnEnd func(float32)
}

Drag is a number the finger moves on the phone, without Go: a thumb on a track, a card pulled across. Across (or down, with Vertical), the finger moves it as far as it moves, in the canvas's units, between Min and Max.

type Ease added in v0.0.13

type Ease uint8

Ease is how an animation speeds up and slows down.

const (
	EaseInOut Ease = iota // starts and ends gently
	Linear                // the same speed throughout
	EaseIn                // starts gently
	EaseOut               // ends gently
	Spring                // like a spring, overshooting by Animation.Bounce
)

type Edges

type Edges = layout.Edges

Layout vocabulary, re-exported so apps only import ui.

func All

func All(v float32) Edges

All is the same length on every side.

func XY

func XY(x, y float32) Edges

XY is horizontal and vertical lengths: XY(16, 8) pads 16 left and right, 8 top and bottom.

type Element

type Element struct {
	// contains filtered or unexported fields
}

Element describes one piece of UI: a native view, or a component that renders to one. Elements are cheap values, rebuilt on every render; the runtime compares them with what is on screen and changes only what differs.

func C

func C(comp Component) *Element

C wraps a component in an Element, for what only an Element has, such as gestures. They reach the view the component renders.

func Canvas added in v0.0.13

func Canvas(w, h float32, paint func(p *Painter), s Style) *Element

Canvas draws shapes that paint describes, in a w×h space fitted to the element's frame (centred, keeping its aspect, like an SVG viewBox):

ui.Canvas(100, 100, func(p *ui.Painter) {
	p.Circle(50, 50, 40)
	p.Fill(ui.Hex("#8DC2CC"))
}, ui.Style{Width: ui.Pt(60), Height: ui.Pt(60)})

paint runs during the render. To animate, give its numbers an animation (UseAnimation, UseTween) through Motion or Trim: the phone runs it, frame by frame. Without a Width and Height in s, the canvas is w×h points.

func Icon added in v0.0.13

func Icon(name string, size float32, color Color) *Element

Icon draws one of the built-in line icons, the same on every platform, in color (the theme's text color when 0):

ui.Icon("search", 22, th.TextMuted)

IconNames lists them. An unknown name draws nothing. For an icon of your own, draw it with Canvas.

func Image

func Image(url string, s Style) *Element

Image shows a picture from a URL. Give it a size: it has none of its own.

func Key added in v0.0.13

func Key(key string, child Component) *Element

Key gives a child its identity among its siblings, so that a list keeps each row's state when rows move:

rows = append(rows, ui.Key(o.ID, OrderRow{o}))

func List

func List(count int, item func(i int) Component, s Style) *Element

List shows count items in a vertical scroll view, but only creates native views for the items on screen and about one screen above and below. Items may differ in height: each is measured once it has been shown.

ui.List(len(orders), func(i int) *ui.Element {
	return ui.C(OrderRow{orders[i]})
}, ui.Flex(1)).ItemKey(func(i int) string { return orders[i].ID })

Scrolling renders no components but the items coming into view.

func Native added in v0.0.13

func Native(kind string, props any, s Style) *Element

Native shows a view written in Swift and Kotlin, inside your screen: a map, a video, a view from another SDK. The host registers a maker for kind (NativeViews.register on both platforms), props reach it as JSON whenever they change, and Style sizes it like any view. Plugins wrap this in a component of their own; see plugins/googlemaps.

func Pressable

func Pressable(onPress func(), s Style, children ...Component) *Element

Pressable is a container that calls onPress when tapped, dimming while pressed.

func Rich added in v0.0.13

func Rich(s Style, spans ...Span) *Element

Rich is a text whose runs look different, wrapping as one paragraph — a name in bold, a figure in color, a dot in a lighter ink:

ui.Rich(ui.Style{FontSize: 14},
	ui.Span{Text: "70 orders"},
	ui.Span{Text: "  ·  ", Style: ui.Style{Color: rule}},
	ui.Span{Text: "₹689 average", Style: ui.Style{FontWeight: 600}})

func SafeArea

func SafeArea(s Style, children ...Component) *Element

SafeArea is a View padded by the screen's safe-area insets — the notch or status bar, the home indicator, rounded corners — on top of any padding in s, so its children stay clear of them. Inside a Stack the navigation bar already covers the top. Inside Tabs the bottom is padded clear of the tab bar instead (iOS tabs run under it); a Stack in a tab already stops above the bar. While the keyboard is up, the bottom pads clear of it.

ui.SafeArea(ui.Style{Padding: ui.All(16)}, ui.Text("Hello", ui.Style{}))

func Scroll

func Scroll(s Style, children ...Component) *Element

Scroll scrolls its children vertically (Horizontal() for sideways). Give it a size, or Grow to fill the space: its content is as long as its children.

func Slider added in v0.0.9

func Slider(value, min, max float32, onChange func(float32), s Style) *Element

Slider picks a number between min and max: UISlider, Android's SeekBar, colored with the theme's Primary (or s.Color). onChange gets each value as the user drags; pass nil to disable it.

volume, setVolume := ui.State(c, float32(0.5))
ui.Slider(volume, 0, 1, setVolume, ui.Style{})

func Spinner

func Spinner(s Style) *Element

Spinner is the platform's activity indicator.

func Stack

func Stack(title string, root Component, s Style) *Element

Stack is a navigation stack: screens shown one at a time under the platform's navigation bar, with its push and pop transitions and back gestures. root is the first screen. Components inside it push and pop screens through Navigation.

ui.Stack("Orders", OrdersScreen{}, ui.Flex(1))

func Switch

func Switch(on bool, onChange func(bool), s Style) *Element

Switch is the platform's on/off toggle, colored with the theme's Primary (or s.Color). onChange gets the new state; pass nil to disable it.

notify, setNotify := ui.State(c, true)
ui.Switch(notify, setNotify, ui.Style{})

func Tabs

func Tabs(s Style, tabs ...Tab) *Element

Tabs is the platform's tab bar with a screen per tab: UITabBarController on iOS, a bottom navigation bar on Android. Every tab stays mounted, so switching keeps each tab's state, scroll position and navigation stack.

ui.Tabs(ui.Flex(1),
	ui.Tab{Title: "Orders", Icon: "list.bullet", Screen: OrdersTab{}},
	ui.Tab{Title: "Account", Icon: "person", Screen: AccountTab{}})

func TestID added in v0.0.13

func TestID(id string, child Component) *Element

TestID names a child for tests.

func Text

func Text(text string, s Style) *Element

Text shows a string.

func TextField

func TextField(f Field, o FieldOptions) *Element

TextField is a labelled input for a form Field, with its error below.

ui.TextField(form.Field("email", func(s *Signup) *string { return &s.Email }),
	ui.FieldOptions{Label: "Email", Keyboard: render.KeyboardEmail})

func TextInput

func TextInput(value string, onChange func(string), s Style) *Element

TextInput is a single-line text field showing value; onChange gets every edit. Keep value in State and set it from onChange.

func View

func View(s Style, children ...Component) *Element

View is a container: a flex column unless its style says otherwise.

func (*Element) AutoFocus added in v0.0.13

func (e *Element) AutoFocus() *Element

AutoFocus focuses a TextInput when it appears, with the keyboard up.

func (*Element) EstimatedItemHeight

func (e *Element) EstimatedItemHeight(h float32) *Element

EstimatedItemHeight is the height a List assumes for items it has not shown yet (default: the average of the items it has shown).

func (*Element) Fit

func (e *Element) Fit(f render.Fit) *Element

Fit sets how an image fills its frame.

func (*Element) Horizontal

func (e *Element) Horizontal() *Element

Horizontal makes a Scroll scroll sideways.

func (*Element) Href

func (e *Element) Href(path string) *Element

Href is where a Pressable leads, for hosts with addresses: the web host makes it a link crawlers and new tabs can follow. Taps still run its handler. router.Link sets it.

func (*Element) ItemKey

func (e *Element) ItemKey(key func(i int) string) *Element

ItemKey names a List's items, so an item keeps its native views and measured height when the data changes order. Without it, items are keyed by index.

func (*Element) Key

func (e *Element) Key(k string) *Element

Key identifies an element among its siblings, so the runtime can keep its native view and state when the list changes order.

func (*Element) Keyboard

func (e *Element) Keyboard(k render.Keyboard) *Element

Keyboard picks a text input's soft keyboard.

func (*Element) Label

func (e *Element) Label(l string) *Element

Label is the accessibility label screen readers speak. On a component, it labels what the component renders.

func (*Element) Multiline

func (e *Element) Multiline() *Element

Multiline lets a TextInput wrap and take new lines; it is three lines tall unless its style sets a height.

func (*Element) OnEvent added in v0.0.13

func (e *Element) OnEvent(f func(name, data string)) *Element

OnEvent gets what a Native view reports: a name, and JSON.

func (*Element) OnLongPress added in v0.0.9

func (e *Element) OnLongPress(f func()) *Element

OnLongPress makes a Pressable report long presses too.

func (*Element) OnPan added in v0.0.13

func (e *Element) OnPan(f func(Pan)) *Element

OnPan reports drags in any direction on this view. Inside a Scroll, use OnPanX or OnPanY so that scrolling still works the other way.

ui.View(ui.Style{Left: ui.Pt(x)}, card).OnPanX(func(p ui.Pan) {
	setX(start + p.X)
})

func (*Element) OnPanX added in v0.0.13

func (e *Element) OnPanX(f func(Pan)) *Element

OnPanX reports sideways drags only; a drag that starts up or down is left to whatever scrolls around this view.

func (*Element) OnPanY added in v0.0.13

func (e *Element) OnPanY(f func(Pan)) *Element

OnPanY reports up and down drags only.

func (*Element) OnPinch added in v0.0.13

func (e *Element) OnPinch(f func(Pinch)) *Element

OnPinch reports two-finger pinches on this view.

func (*Element) OnRefresh

func (e *Element) OnRefresh(refreshing bool, onRefresh func()) *Element

OnRefresh adds pull to refresh to a Scroll or List: pulling calls onRefresh, and the indicator shows while refreshing is true. With a query:

ui.List(n, row, ui.Flex(1)).OnRefresh(q.Loading, q.Refetch)

func (*Element) OnScroll added in v0.0.13

func (e *Element) OnScroll(f func(x, y float32)) *Element

OnScroll calls f as a Scroll or List scrolls, with how far its content has moved (x, y in points; y grows as you scroll down, and goes below 0 while a pull bounces). It runs often: keep it cheap, and set State only when something changes (to tuck a bar away, say).

func (*Element) OnSubmit added in v0.0.13

func (e *Element) OnSubmit(f func()) *Element

OnSubmit makes Return on a TextInput call f (the key says Send), even on a Multiline one: chat boxes send on Return.

func (*Element) OnSwipe added in v0.0.13

func (e *Element) OnSwipe(f func(Swipe)) *Element

OnSwipe reports a quick flick or a long drag that ends in one direction.

func (*Element) OnTap added in v0.0.13

func (e *Element) OnTap(f func(Tap)) *Element

OnTap makes a canvas take taps: f gets the topmost tagged shape under the finger, as the phone drew it that moment, animations included.

func (*Element) Placeholder

func (e *Element) Placeholder(p string) *Element

Placeholder sets a text input's hint.

func (*Element) Render added in v0.0.13

func (e *Element) Render(*Ctx) Component

Render makes an Element a Component, so children can be either:

ui.View(ui.Style{}, ui.Text("Total", ui.Style{}), ui.Badge{Label: "Paid"}, Orders{})

func (*Element) Secure

func (e *Element) Secure() *Element

Secure hides a text input's characters.

func (*Element) StickToEnd added in v0.0.13

func (e *Element) StickToEnd() *Element

StickToEnd keeps a Scroll's end in view as its content grows, as a chat shows its newest message.

func (*Element) TestID

func (e *Element) TestID(id string) *Element

TestID names the element for UI tests (accessibilityIdentifier on iOS, the view tag on Android). On a component, it names what the component renders.

type EmptyState added in v0.0.13

type EmptyState struct {
	Icon     string // An Icon name
	Title    string // What's missing
	Message  string // What to do about it
	Action   string // A button's label
	OnAction func() // Called on a tap
}

EmptyState is what a screen shows when it has nothing yet:

ui.EmptyState{Icon: "cart", Title: "No orders yet", Message: "New orders show up here.",
	Action: "Open POS", OnAction: open}

func (EmptyState) Render added in v0.0.13

func (e EmptyState) Render(c *Ctx) Component

type Field

type Field struct {
	Name     string
	Value    string
	Error    string
	OnChange func(string)
}

Field is one bound text field: its value, the error to show (empty until the user has touched it or tried to submit), and its change handler.

type FieldErrors

type FieldErrors map[string][]string

FieldErrors are validation errors by field name — the shape Nimbus's validation.ValidationErrors has, so server rules can validate app forms.

func FieldErrorsOf

func FieldErrorsOf(err error) FieldErrors

FieldErrorsOf reads field errors out of a validation error — a FieldErrors, Nimbus's validation.ValidationErrors (for example from a server's 422 response), or any error with ToMap() map[string][]string. It is nil when err carries none.

func (FieldErrors) Error

func (e FieldErrors) Error() string

Error lets FieldErrors be returned as an error.

type FieldOptions

type FieldOptions struct {
	Label       string
	Placeholder string
	Keyboard    render.Keyboard
	Secure      bool
	Multiline   bool  // several lines, three tall unless Style sets a height
	Style       Style // for the input box
}

FieldOptions configure a TextField.

type FloatingButton added in v0.0.13

type FloatingButton struct {
	Icon     string // An Icon name
	Label    string // shown beside the icon when Extended, always read aloud
	OnPress  func() // Called on a tap
	Extended bool   // Shows the label beside the icon
}

FloatingButton is a screen's main action, floating over its content at the bottom right. Put it last among the screen's children.

func (FloatingButton) Render added in v0.0.13

func (b FloatingButton) Render(c *Ctx) Component

type Form

type Form[T any] struct {
	// contains filtered or unexported fields
}

Form is a form's state: its value, which fields the user has touched, and the validation errors. Get one with UseForm.

func UseForm

func UseForm[T any](c *Ctx, initial T, validate func(T) error) *Form[T]

UseForm keeps a form's value in state and validates it on every change. validate returns nil when the value is valid; field errors come from a FieldErrors, from Nimbus's validation.ValidationErrors, or from any error with ToMap() map[string][]string. Pass validation.ValidateStruct to share your server's rules:

form := ui.UseForm(c, Signup{}, validation.ValidateStruct)

func (*Form[T]) Errors

func (f *Form[T]) Errors() FieldErrors

Errors are all field errors, touched or not.

func (*Form[T]) Field

func (f *Form[T]) Field(name string, at func(*T) *string) Field

Field binds one text field of the value: name is the validation key (as in the rules, usually the json name) and at points at the field.

func (*Form[T]) FormError

func (f *Form[T]) FormError() error

FormError is the error that belongs to no single field: from validation, or from SetErrors (a server or network failure).

func (*Form[T]) SetErrors

func (f *Form[T]) SetErrors(err error)

SetErrors shows errors a server returned for the value — say, the field errors in a Nimbus 422 — on their fields, until each field changes. nil clears them. Safe from any goroutine, so an action can call it directly.

func (*Form[T]) Submit

func (f *Form[T]) Submit(onValid func(T)) func()

Submit returns a handler for the submit button: when the value is valid it calls onValid with it; otherwise every field shows its error.

func (*Form[T]) Update

func (f *Form[T]) Update(change func(*T))

Update changes the value; it re-renders and re-validates.

func (*Form[T]) Valid

func (f *Form[T]) Valid() bool

Valid reports whether the value passes validation.

func (*Form[T]) Value

func (f *Form[T]) Value() T

Value is the form's current value.

type Gradient added in v0.0.13

type Gradient struct {
	Colors []Color   // the colors, in order
	Stops  []float32 // where each color sits, 0..1; empty spaces them evenly
	Radial bool      // from From outward to the distance to To; else along From → To
	Sweep  bool      // on a Canvas: clockwise around From, starting toward To
	From   Point     // where it starts: a Style's in its box's unit square, a Canvas's in its own units
	To     Point     // where it ends
}

Gradient is a fill that blends between colors (Style.Gradient).

func LinearGradient added in v0.0.13

func LinearGradient(from, to Point, colors ...Color) *Gradient

LinearGradient blends colors along the line from → to:

ui.LinearGradient(ui.Point{0, 0}, ui.Point{0, 1}, top, bottom) // top to bottom

func RadialGradient added in v0.0.13

func RadialGradient(center Point, radius float32, colors ...Color) *Gradient

RadialGradient blends colors outward from center, reaching the last at radius (a share of the view's width).

type Grid added in v0.0.13

type Grid struct {
	Columns int         // 0 means 2
	Gap     float32     // Space between items
	Items   []Component // What goes in it
}

Grid lays its items out in equal columns:

ui.Grid{Columns: 2, Gap: 12, Items: tiles}

func (Grid) Render added in v0.0.13

func (g Grid) Render(c *Ctx) Component

type IconButton added in v0.0.13

type IconButton struct {
	Icon    string  // An Icon name
	Label   string  // What it does, read aloud
	OnPress func()  // Called on a tap
	Variant Variant // Plain by default
	Size    Size    // 34, 44 or 54 points across
	Filled  bool    // solid Primary, not the plain icon
}

IconButton is a button that is only an icon. Label says what it does, for screen readers.

func (IconButton) Render added in v0.0.13

func (b IconButton) Render(c *Ctx) Component

type Join added in v0.0.13

type Join uint8

Join is how a stroke turns a corner.

const (
	JoinRound Join = iota
	JoinMiter
	JoinBevel
)

type Justify

type Justify = layout.Justify

Layout vocabulary, re-exported so apps only import ui.

type ListRow added in v0.0.13

type ListRow struct {
	Title    string    // The main line
	Subtitle string    // Under it, up to two lines
	Icon     string    // an Icon name, in a tinted square
	Leading  Component // anything else at the start: an Avatar, say
	Trailing Component // at the end: a Switch, a Badge, a price
	OnPress  func()    // adds a chevron unless there is a Trailing
}

ListRow is one row of a list or settings screen:

ui.ListRow{Title: "Notifications", Subtitle: "On", Icon: "bell", OnPress: open}

func (ListRow) Render added in v0.0.13

func (r ListRow) Render(c *Ctx) Component
type Menu struct {
	Trigger Component    // What's tapped
	Items   []MenuAction // The choices
	Label   string       // what the trigger does, for screen readers
	Open    bool         // opens by itself when it first appears
}

Menu opens a small list of actions beside whatever is tapped:

ui.Menu{Trigger: ui.Icon("more", 24, 0), Items: []ui.MenuAction{
	{Label: "Edit", Icon: "edit", OnPress: edit},
	{Label: "Delete", Icon: "trash", Destructive: true, OnPress: remove},
}}
func (m Menu) Render(c *Ctx) Component
type MenuAction struct {
	Label       string // A choice's words
	Icon        string // An Icon name
	Destructive bool   // In the theme's Danger color
	OnPress     func() // Called after the sheet closes
}

MenuAction is a choice in an ActionSheet or Menu.

type ModalNav

type ModalNav struct {
	// contains filtered or unexported fields
}

ModalNav presents and dismisses modals: screens shown over everything — a sheet on iOS (swipe down to close), a full-screen layer on Android (back to close). Each modal is its own navigation stack with a title bar, so Navigation works inside it. Safe from any goroutine.

func Modals

func Modals(c *Ctx) *ModalNav

Modals presents and dismisses modals from any component.

func (*ModalNav) Count

func (m *ModalNav) Count() int

Count is how many modals are open.

func (*ModalNav) Dismiss

func (m *ModalNav) Dismiss()

Dismiss closes the modal the component is in, or else the topmost one.

func (*ModalNav) Present

func (m *ModalNav) Present(title string, screen Component)

Present shows screen in a new modal titled title, over everything else.

type Motion added in v0.0.13

type Motion struct {
	X       Num // moves it across
	Y       Num // moves it down
	Rotate  Num // turns it, in degrees, clockwise
	Scale   Num // scales it; 1 is its own size
	Opacity Num // fades it as one picture, 0 to 1
}

Motion moves, turns, scales and fades what's drawn after it, until its Restore, with numbers that can animate. It turns and scales about the point it moves to. Unset fields leave it be. Like Save, it needs a Restore.

type Nav struct {
	// contains filtered or unexported fields
}

Nav pushes and pops the screens of the Stack a component is in. Its methods are safe from any goroutine; changes show on the next render.

func Navigation(c *Ctx) *Nav

Navigation is the Stack the component is shown in, or nil outside one.

func (n *Nav) Depth() int

Depth is how many screens are on the stack.

func (n *Nav) Pop()

Pop goes back one screen. The root screen stays.

func (n *Nav) PopToRoot()

PopToRoot goes back to the first screen.

func (n *Nav) Push(title string, screenComp Component)

Push shows screen on top, titled title, with the platform's transition.

func (n *Nav) PushPath(title, path string, screenComp Component)

PushPath is Push for a screen with a URL path (router.Push uses it), so a dev reload can open the screen again.

type Num added in v0.0.13

type Num struct {
	// contains filtered or unexported fields
}

Num is a number a canvas animates, for Painter.Motion and Painter.Trim. The zero Num is unset; Fixed is a number that doesn't move.

func Fixed added in v0.0.13

func Fixed(v float32) Num

Fixed is a Num that stays v.

func UseDrag added in v0.0.13

func UseDrag(c *Ctx, value float32, d Drag) Num

UseDrag is a number the finger moves, as d says, starting at value; a new value from Go moves it there, animated.

x, setX := ui.State(c, float32(20))
thumb := ui.UseDrag(c, x, ui.Drag{Min: 20, Max: 280, Handle: "thumb", OnEnd: setX})
ui.Canvas(300, 40, func(p *ui.Painter) {
	p.Motion(ui.Motion{X: thumb, Y: ui.Fixed(20)})
	p.Circle(0, 0, 14)
	p.Tag("thumb")
	p.Fill(th.Primary)
	p.Restore()
}, ui.Style{})

func UseTween added in v0.0.13

func UseTween(c *Ctx, target float32, a Animation) Num

UseTween is a number that moves smoothly to target whenever target changes, from wherever it is on screen, as a says (Repeat and Reverse aside). It starts at target.

type OTPInput added in v0.0.13

type OTPInput struct {
	Length   int          // 0 means 6
	Value    string       // The digits so far
	OnChange func(string) // Called as it changes
}

OTPInput takes a short code, a box for each digit:

ui.OTPInput{Length: 6, Value: code, OnChange: setCode}

func (OTPInput) Render added in v0.0.13

func (o OTPInput) Render(c *Ctx) Component

type OverlayNav added in v0.0.13

type OverlayNav struct {
	// contains filtered or unexported fields
}

OverlayNav shows things over the whole app. Safe from any goroutine.

func Overlays added in v0.0.13

func Overlays(c *Ctx) OverlayNav

Overlays shows toasts, sheets and menus from any component.

func (OverlayNav) ActionSheet added in v0.0.13

func (o OverlayNav) ActionSheet(title string, actions ...MenuAction)

ActionSheet asks what to do, from a sheet of choices:

ui.Overlays(c).ActionSheet("Order 1042",
	ui.MenuAction{Label: "Mark ready", Icon: "check", OnPress: ready},
	ui.MenuAction{Label: "Cancel order", Icon: "trash", Destructive: true, OnPress: cancel})

func (OverlayNav) Dismiss added in v0.0.13

func (o OverlayNav) Dismiss()

Dismiss closes every overlay at once.

func (OverlayNav) Sheet added in v0.0.13

func (o OverlayNav) Sheet(s Sheet)

Sheet opens a sheet over the app:

ui.Overlays(c).Sheet(ui.Sheet{Title: "Filters", Content: Filters{}})

func (OverlayNav) Toast added in v0.0.13

func (o OverlayNav) Toast(message string, tone ...Tone)

Toast shows a short message for a moment, without stopping anything:

ui.Overlays(c).Toast("Order placed", ui.Good)

type Painter added in v0.0.13

type Painter struct {
	// contains filtered or unexported fields
}

Painter collects a canvas's shapes: build a path (MoveTo, LineTo, …, Circle, Rect), then Fill or Stroke it, which starts the next one. Save, Translate, Clip, Shadow and the like change what's drawn after them, until the Restore that matches their Save.

func (*Painter) Arc added in v0.0.13

func (p *Painter) Arc(cx, cy, r, start, sweep float32)

Arc adds part of a circle's edge, as a subpath of its own: from start degrees (clockwise from 3 o'clock) through sweep more (negative turns back). A ring that fills up is an Arc from -90, stroked.

func (*Painter) Blend added in v0.0.13

func (p *Painter) Blend(mode BlendMode)

Blend sets how what's drawn after it combines with what's under it. Inside a Layer, BlendErase and BlendAtop only touch the layer's own drawing: a Layer, a picture, then a gradient drawn with BlendErase fades the picture out. Android 9 and older draw BlendColorDodge to BlendLuminosity as BlendNormal.

func (*Painter) Circle added in v0.0.13

func (p *Painter) Circle(cx, cy, r float32)

Circle adds a circle centred on (cx, cy).

func (*Painter) Clip added in v0.0.13

func (p *Painter) Clip()

Clip keeps what's drawn after it inside the path, until Restore, and starts a new path.

func (*Painter) Close added in v0.0.13

func (p *Painter) Close()

Close joins the subpath's end to its start.

func (*Painter) CubicTo added in v0.0.13

func (p *Painter) CubicTo(c1x, c1y, c2x, c2y, x, y float32)

CubicTo draws a cubic curve to (x, y) with control points c1 and c2.

func (*Painter) Dash added in v0.0.13

func (p *Painter) Dash(lengths ...float32)

Dash makes strokes after it dashed: lengths on, off, on, …; none makes them solid again.

func (*Painter) EvenOdd added in v0.0.13

func (p *Painter) EvenOdd()

EvenOdd fills the path by the even-odd rule, so a shape inside another cuts a hole in it (a ring from two circles).

func (*Painter) Fill added in v0.0.13

func (p *Painter) Fill(c Color)

Fill paints the path's inside in c, then starts a new path.

func (*Painter) FillGradient added in v0.0.13

func (p *Painter) FillGradient(g *Gradient)

FillGradient paints the path's inside with g, then starts a new path. Its points are in the canvas's own space (not the unit square a Style's gradient uses); a radial one spreads from From out to the distance to To, and a sweep turns clockwise around From, starting toward To.

func (*Painter) FillShader added in v0.0.13

func (p *Painter) FillShader(sh *Shader, fallback Color, uniforms ...Num)

FillShader fills the path with sh, giving its uniforms these numbers, in the order the shader declares them (a float2 takes two), then starts a new path. Where shaders can't run (Android 12 and older) it fills with fallback.

func (*Painter) Image added in v0.0.13

func (p *Painter) Image(url string, x, y, w, h float32, fit render.Fit)

Image draws the picture at url (as ui.Image takes) in the rectangle, fitted by fit (FitCover, FitContain, FitStretch); nothing until it has loaded.

func (*Painter) Layer added in v0.0.13

func (p *Painter) Layer(opacity float32)

Layer is a Save whose drawing, up to its Restore, is blended in as one picture at opacity: overlapping shapes inside don't show through each other.

func (*Painter) LineStyle added in v0.0.13

func (p *Painter) LineStyle(cap Cap, join Join)

LineStyle sets the ends and corners of strokes after it. Strokes start round.

func (*Painter) LineTo added in v0.0.13

func (p *Painter) LineTo(x, y float32)

LineTo draws a straight line to (x, y).

func (*Painter) Motion added in v0.0.13

func (p *Painter) Motion(m Motion)

Motion starts a group moved as m says; Restore ends it.

func (*Painter) MoveTo added in v0.0.13

func (p *Painter) MoveTo(x, y float32)

MoveTo starts a new subpath at (x, y).

func (*Painter) Oval added in v0.0.13

func (p *Painter) Oval(x, y, w, h float32)

Oval adds an ellipse that fills the rectangle.

func (*Painter) Path added in v0.0.13

func (p *Painter) Path(d string)

Path adds SVG path data ("M10 10 L20 20 …", as an icon's d attribute) to the path: every command, relative and absolute, arcs included. It stops at the first thing it can't read.

func (*Painter) QuadTo added in v0.0.13

func (p *Painter) QuadTo(cx, cy, x, y float32)

QuadTo draws a quadratic curve to (x, y) bending toward (cx, cy).

func (*Painter) Rect added in v0.0.13

func (p *Painter) Rect(x, y, w, h, radius float32)

Rect adds a rectangle, its corners rounded by radius.

func (*Painter) Restore added in v0.0.13

func (p *Painter) Restore()

Restore goes back to the last Save (or Layer, or Motion).

func (*Painter) Rotate added in v0.0.13

func (p *Painter) Rotate(degrees float32)

Rotate turns what's drawn after it clockwise by degrees, around the origin: Translate to the pivot first.

func (*Painter) Save added in v0.0.13

func (p *Painter) Save()

Save remembers the transform, clip, blend, shadow, dashes and line style, for Restore to bring back.

func (*Painter) Scale added in v0.0.13

func (p *Painter) Scale(sx, sy float32)

Scale stretches what's drawn after it, from the origin.

func (*Painter) Shadow added in v0.0.13

func (p *Painter) Shadow(dx, dy, blur float32, c Color)

Shadow gives what's drawn after it a shadow, (dx, dy) away, blurred by blur points (as CSS's box-shadow), in c; 0 for c removes it. Android 8 draws none.

func (*Painter) Stroke added in v0.0.13

func (p *Painter) Stroke(width float32, c Color)

Stroke draws the path's outline width wide in c, then starts a new path.

func (*Painter) StrokeGradient added in v0.0.13

func (p *Painter) StrokeGradient(width float32, g *Gradient)

StrokeGradient draws the path's outline width wide with g, then starts a new path.

func (*Painter) Tag added in v0.0.13

func (p *Painter) Tag(id string)

Tag names the shape the next Fill, Stroke or gradient paints, for OnTap and for a Drag's Handle. Taps go to the topmost tagged shape: the last painted.

func (*Painter) Text added in v0.0.13

func (p *Painter) Text(text string, x, y float32, s Style)

Text writes s with its top left at (x, y), in s's FontSize, FontWeight, FontFamily, Color, TextAlign and Lines. With a Width in points it wraps there, and TextAlign aligns within it. It isn't part of the path.

func (*Painter) Translate added in v0.0.13

func (p *Painter) Translate(x, y float32)

Translate moves what's drawn after it by (x, y).

func (*Painter) Trim added in v0.0.13

func (p *Painter) Trim(start, end Num)

Trim makes the next stroke show only from start to end of the path's length, as fractions (0 to 1): a ring that fills up, a line that draws itself with an Anim's Range. Call it after the path, before Stroke. It replaces Dash for that stroke, and works on a path in one piece.

type Pan added in v0.0.13

type Pan struct {
	Phase  Phase   // Where it is in the gesture
	X, Y   float32 // How far it has come, in points
	VX, VY float32 // How fast it's going, in points a second
}

Pan is a drag: how far it has come from where it began (X, Y) and how fast it's going (VX, VY, per second), in points.

type Phase added in v0.0.13

type Phase uint8

Phase is where a gesture has got to.

type Pinch added in v0.0.13

type Pinch struct {
	Phase Phase   // Where it is in the gesture
	Scale float32 // How far apart the fingers are; 1 is where they began
}

Pinch is a two-finger pinch: Scale is 1 at the start, more as the fingers spread.

type Point added in v0.0.13

type Point struct{ X, Y float32 }

Point is a place in a view's unit square: (0, 0) its top left, (1, 1) its bottom right.

type ProgressBar added in v0.0.13

type ProgressBar struct {
	Value  float64 // 0 to 1
	Busy   bool    // Runs back and forth
	Height float32 // 0 means 6
	Tone   Tone    // Accent when Neutral
}

ProgressBar shows how far something has got. Value is 0..1, and a bar with Busy runs back and forth when you can't tell.

func (ProgressBar) Render added in v0.0.13

func (b ProgressBar) Render(c *Ctx) Component

type Query

type Query[T any] struct {
	Data    T
	Loading bool  // a fetch is running (Data may still hold the last result)
	Loaded  bool  // Data holds a result
	Err     error // the last fetch's error, if it failed
	Refetch func()
}

Query is a UseQuery's state.

func UseQuery

func UseQuery[T any](c *Ctx, key string, fetch func(ctx context.Context) (T, error)) Query[T]

UseQuery loads data off the UI goroutine and re-renders when it arrives. Results are cached by key and shared: components using the same key make one request and see the same data. Cached data shows at once and is fetched again in the background when older than StaleAfter.

q := ui.UseQuery(c, "orders", func(ctx context.Context) ([]Order, error) {
	return api.Call(ctx, client, shared.ListOrders, shared.ListOrdersReq{})
})
if q.Loading && !q.Loaded { return ui.Spinner(ui.Style{}) }

type RadioGroup added in v0.0.13

type RadioGroup struct {
	Options  []string  // The choices
	Selected int       // The index of the chosen one
	OnChange func(int) // Called with the new index
	Disabled bool      // Dimmed, can't be changed
}

RadioGroup picks one of its options:

ui.RadioGroup{Options: []string{"Card", "UPI", "Cash"}, Selected: pay, OnChange: setPay}

func (RadioGroup) Render added in v0.0.13

func (r RadioGroup) Render(c *Ctx) Component
type SearchBar struct {
	Value       string       // What's typed
	Placeholder string       // "Search" when empty
	OnChange    func(string) // Called as it changes
	OnSubmit    func()       // Called on the keyboard's search key
}

SearchBar is a one-line search box with a clear button:

ui.SearchBar{Value: q, OnChange: setQ, OnSubmit: search}

func (SearchBar) Render added in v0.0.13

func (b SearchBar) Render(c *Ctx) Component

type SegmentedControl added in v0.0.13

type SegmentedControl struct {
	Options  []string  // The segments; two to four fit best
	Selected int       // The index of the chosen one
	OnChange func(int) // Called with the new index
}

SegmentedControl picks one of a few views of the same thing, with a thumb that slides to the selection:

ui.SegmentedControl{Options: []string{"Day", "Week", "Month"}, Selected: at, OnChange: setAt}

func (SegmentedControl) Render added in v0.0.13

func (g SegmentedControl) Render(c *Ctx) Component

type Select added in v0.0.13

type Select struct {
	Label       string    // Above the field, and the list's title
	Placeholder string    // Shown when nothing is chosen
	Options     []string  // The choices
	Selected    int       // -1 for none
	OnChange    func(int) // Called with the new index
}

Select is a field that picks one of its options from a list the platform shows:

ui.Select{Label: "City", Options: cities, Selected: city, OnChange: setCity}

func (Select) Render added in v0.0.13

func (p Select) Render(c *Ctx) Component

type Session

type Session struct {
	// contains filtered or unexported fields
}

Session is a UI runtime that is not the device's: the web host runs one per browser tab. It speaks the same render protocol as the phone hosts: Receive takes host messages, and SessionOptions.Send gets commits.

func NewSession

func NewSession(root Component, o SessionOptions) *Session

NewSession starts a runtime for root. It renders once the host sends a render.Viewport.

func (*Session) Close

func (s *Session) Close()

Close stops the session: effects stop, and its loop ends.

func (*Session) Do

func (s *Session) Do(f func())

Do runs f on the session's UI loop and renders what it changed.

func (*Session) Receive

func (s *Session) Receive(msg []byte)

Receive handles an encoded message from the host.

func (*Session) Settle

func (s *Session) Settle(timeout time.Duration) bool

Settle waits, up to timeout, until the UI stops changing: no queued work and no query still loading. Server rendering uses it to send a page with its data, not a spinner. It reports whether the session settled.

type SessionOptions

type SessionOptions struct {
	// Send gets each render.Commit, encoded.
	Send func(commit []byte)
	// Style, when set, leaves layout to the host (a browser's CSS
	// flexbox): no Frame ops are sent, Style gets each view's layout style
	// whenever it changes, and Lists render every item.
	Style func(tag uint32, s layout.Style)
	// Values are what SessionValue returns to components.
	Values map[any]any
}

SessionOptions configure a Session.

type Shader added in v0.0.13

type Shader struct {
	// contains filtered or unexported fields
}

Shader is a small GPU program that colors a shape, pixel by pixel: noise, ripples, glows, grain. Write it once, in AGSL (Android's shading language, close to GLSL); each phone runs it in its own: AGSL on Android 13+, Metal on iOS, WebGL on the web.

func NewShader added in v0.0.13

func NewShader(src string) *Shader

NewShader reads a shader: uniform floats (float, float2, float3, float4 and their half and vec spellings) then functions, one of them

half4 main(float2 p)

which gets the point it colors, in the canvas's units, and returns its color, premultiplied (rgb × a). It panics on a shader it can't read, so make shaders package variables.

type Shadow added in v0.0.13

type Shadow struct {
	Color  Color
	Radius float32
	X, Y   float32
}

Shadow is a shadow under a view (Style.Shadow): its color (with alpha), how far it spreads, and its offset.

type Sheet added in v0.0.13

type Sheet struct {
	Title   string    // At the top of the panel
	Content Component // What's inside
	Height  float32   // a share of the screen; 0 means 0.5
}

Sheet is a panel that rises from the bottom. Drag it down, or tap outside it, to close.

type Size added in v0.0.13

type Size uint8

Size is how large a control is.

const (
	SizeMedium Size = iota // the default
	SizeSmall              // for tight rows
	SizeLarge              // for a screen's one big action
)

type Skeleton added in v0.0.13

type Skeleton struct {
	Width  Value   // Fills the space when unset
	Height float32 // 0 means 16
	Radius float32 // 0 means 6
	Circle bool    // A circle Height across
}

Skeleton is a placeholder that pulses where content will load.

func (Skeleton) Render added in v0.0.13

func (k Skeleton) Render(c *Ctx) Component

type Span added in v0.0.13

type Span struct {
	Text  string
	Style Style
}

Span is a run of a Rich text: its words and how they differ from the text's own style (FontFamily, FontSize, FontWeight, Color, LetterSpacing, TabularDigits; what a span leaves unset it takes from the text).

type Stepper added in v0.0.13

type Stepper struct {
	Value    int       // The number
	Min      int       // The lowest it goes
	Max      int       // The highest it goes; 0 has no limit
	Step     int       // How much each tap changes it; 0 means 1
	OnChange func(int) // Called with the new value
}

Stepper changes a number a step at a time:

ui.Stepper{Value: qty, Min: 1, Max: 9, OnChange: setQty}

func (Stepper) Render added in v0.0.13

func (s Stepper) Render(c *Ctx) Component

type Store

type Store[T any] struct {
	// contains filtered or unexported fields
}

Store is state the whole app shares, such as a cart or the signed-in user: one value per app on a device, and one per browser tab on the web, where every visitor's UI runs in the same server. Declare it once, at package level:

var Cart = ui.NewStore(func() CartState { return CartState{} })

Components read it with Use, which re-renders them when it changes, and change it from handlers, effects and actions with Update:

cart := Cart.Use(c)
ui.Pressable(func() { Cart.Update(c, func(s CartState) CartState { return s.Add(p) }) }, …)

Keep T a value: Update gets the current one and returns the next.

func NewStore

func NewStore[T any](init func() T) *Store[T]

NewStore declares a store; init makes its first value in each app or tab.

func (*Store[T]) Get

func (s *Store[T]) Get(c *Ctx) T

Get is the store's value without subscribing: for handlers, effects and actions (safe from any goroutine).

func (*Store[T]) Update

func (s *Store[T]) Update(c *Ctx, f func(T) T)

Update replaces the value with f(current) and re-renders the components using it. Safe from any goroutine.

func (*Store[T]) Use

func (s *Store[T]) Use(c *Ctx) T

Use is the store's value, and re-renders the component when it changes. Call it while rendering, like any hook.

type Style

type Style struct {
	// Layout
	Direction  Direction
	Justify    Justify
	AlignItems Align
	AlignSelf  Align

	Grow, Shrink float32
	Basis        Value

	Width, Height       Value
	MinWidth, MinHeight Value
	MaxWidth, MaxHeight Value

	Padding Edges
	Margin  Edges
	Gap     float32
	// Wrap moves children that don't fit onto new lines (rows of chips,
	// grids of tags); LineGap spaces the lines, Gap when zero.
	Wrap    bool
	LineGap float32

	// Transition animates this view's changes of position, size, opacity
	// and background over this many milliseconds, instead of jumping.
	Transition int

	Absolute                 bool
	Left, Top, Right, Bottom Value
	Hidden                   bool

	// Box
	Background  Color
	Radius      float32
	BorderWidth float32
	BorderColor Color
	Opacity     float32 // 0 means 1 (fully opaque); use Hidden to hide
	Clip        bool
	Corners     Corners // which corners Radius rounds; 0 means all four
	// Scale (0 means 1) and Rotate (degrees, clockwise) transform the view
	// about its centre, after layout, so nothing around it moves; with
	// Transition they animate.
	Scale, Rotate float32
	Blur          Blur      // what is behind shows through, blurred; Background tints it
	Gradient      *Gradient // painted over Background
	Shadow        *Shadow   // drawn under the view

	// Text and inputs
	FontSize   float32 // 0 means 16
	FontWeight uint16  // 100..900; 0 means 400
	FontFamily string  // a font the app bundles (`nimbus native font add`); "" is the system font
	Color      Color   // text color; 0 means the platform default
	TextAlign  Align   // AlignStart, AlignCenter, AlignEnd
	Lines      uint32  // 0 = unlimited
	// LetterSpacing is extra space between letters, in points; negative
	// tightens a large headline.
	LetterSpacing float32
	// LineHeight is the distance from one line to the next, in points; 0 is
	// the font's own.
	LineHeight float32
	// TabularDigits gives every digit the same width, so figures line up in
	// columns and don't jiggle as they change.
	TabularDigits bool
	// MinScale lets a one-line text (Lines: 1) shrink to fit its width, down
	// to this share of its size (0.6 is 60%); 0 truncates with an ellipsis.
	MinScale float32
}

Style is how an element looks and lays out. The zero Style is an auto-sized column that stretches its children.

func Flex

func Flex(n float32) Style

Flex makes an element take its share of the free space: Flex(1) fills what is left, like grow 1, shrink 1, basis 0.

func (Style) With

func (s Style) With(o Style) Style

With returns s with the non-zero fields of o laid over it, so styles compose: base.With(ui.Style{Background: red}).

type Swipe added in v0.0.13

type Swipe uint8

Swipe is the way a swipe went.

const (
	SwipeLeft  Swipe = iota + 1 // a flick to the left
	SwipeRight                  // a flick to the right
	SwipeUp                     // a flick up
	SwipeDown                   // a flick down
)

type SwipeAction added in v0.0.13

type SwipeAction struct {
	Label   string // What it says
	Icon    string // An Icon name
	Tone    Tone   // Bad for a delete
	OnPress func() // Called on a tap
}

SwipeAction is a button a SwipeRow reveals.

type SwipeRow added in v0.0.13

type SwipeRow struct {
	Content Component     // The row
	Actions []SwipeAction // What it reveals: Label, Icon, Tone, OnPress
}

SwipeRow reveals actions when its content is swiped to the left. It works inside a list: an up or down drag still scrolls.

func (SwipeRow) Render added in v0.0.13

func (r SwipeRow) Render(c *Ctx) Component

type Tab

type Tab struct {
	Title string
	// Icon is an SF Symbol name on iOS ("list.bullet"); on Android, the
	// drawable resource of the same name with dots as underscores
	// (res/drawable/list_bullet.xml). Without that resource Android shows
	// the title alone.
	Icon   string
	Screen Component
}

Tab is one tab of a Tabs bar.

type TabsNav

type TabsNav struct {
	// contains filtered or unexported fields
}

TabsNav switches the Tabs a component is in. Safe from any goroutine.

func TabsOf

func TabsOf(c *Ctx) *TabsNav

TabsOf is the Tabs the component is shown in, or nil outside one.

func (*TabsNav) Select

func (t *TabsNav) Select(i int)

Select shows the tab at index i.

func (*TabsNav) Selected

func (t *TabsNav) Selected() int

Selected is the index of the tab on screen.

type Tap added in v0.0.13

type Tap struct {
	ID string  // the shape's Tag; "" when it hit none
	X  float32 // where, across
	Y  float32 // where, down
}

Tap is a tap on a canvas: the shape it hit (named by Painter.Tag; "" for none) and where, in the canvas's own units.

type Theme

type Theme struct {
	Dark bool

	Background Color // screens
	Surface    Color // cards, rows, inputs
	Text       Color
	TextMuted  Color
	Border     Color
	Primary    Color // buttons, links, selected tabs
	OnPrimary  Color // text on Primary
	Danger     Color // errors
	Success    Color // done, paid, online
	Warning    Color // needs attention
	Bar        Color // navigation and tab bars
	BarText    Color // titles on bars

	Radius float32 // corner radius for cards and buttons

	// Type scale, in points.
	Title, Heading, Body, Caption float32

	// Spacing scale, in points.
	SpaceS, SpaceM, SpaceL float32
}

Theme is an app's design tokens. The runtime picks the light or dark one to match the system, uses it for anything left unstyled (text color, spinners, screen backgrounds) and for what the platform draws (bars, modal backgrounds, the status bar). Components read it with UseTheme.

func UseTheme

func UseTheme(c *Ctx) Theme

UseTheme is the theme in effect: the dark one while the system is in dark mode. Components re-render when it switches.

type Tone added in v0.0.13

type Tone uint8

Tone is what a Badge or Banner means.

const (
	Neutral Tone = iota // gray: nothing special
	Accent              // the theme's Primary
	Good                // it worked
	Caution             // take care
	Bad                 // it went wrong
)

type Tooltip added in v0.0.13

type Tooltip struct {
	Text  string    // The note
	Child Component // What's tapped
	Open  bool      // shows by itself when it first appears, to point something out
}

Tooltip explains what its child is: tap it for a short note above it.

func (Tooltip) Render added in v0.0.13

func (t Tooltip) Render(c *Ctx) Component

type Value

type Value = layout.Value

Layout vocabulary, re-exported so apps only import ui.

func Pct

func Pct(v float32) Value

Pct is a percentage of the parent's inner size.

func Pt

func Pt(v float32) Value

Pt is a length in points (dp on Android).

type Variant added in v0.0.13

type Variant uint8

Variant is how much a button stands out.

const (
	Filled      Variant = iota // the main action: solid Primary
	Tonal                      // a tint of Primary
	Outlined                   // a border
	Plain                      // text alone
	Destructive                // solid Danger, for what can't be undone
)

type ViewportInfo

type ViewportInfo struct {
	W, H                                     float32
	Scale                                    float32
	SafeTop, SafeBottom, SafeLeft, SafeRight float32
	Platform                                 string // "ios" | "android"
	Dark                                     bool
	Keyboard                                 float32 // how far the keyboard covers the root's bottom
}

ViewportInfo describes the screen.

func Viewport

func Viewport(c *Ctx) ViewportInfo

Viewport is the screen the root fills: size, safe-area insets, platform.

Directories

Path Synopsis
Package render is the wire protocol between the ui runtime (Go) and a host's native renderer.
Package render is the wire protocol between the ui runtime (Go) and a host's native renderer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL