WillowUI

April 11, 2026 ยท View on GitHub

CI Go Reference Go Report Card License: MIT

A reactive UI toolkit for Go, built on Willow and Ebitengine. WillowUI provides a complete widget library, reactive state management, JSON theming, and XML templating for building desktop and game UIs.

New here? Check out the WillowUI website for guides, examples, and everything you need to start building with WillowUI.

Status: Actively developed. API may change before v1.0.0.

Buttons Text Input

Sortable Tree List Calendar

Features

  • 50+ widgets -- buttons, text inputs, sliders, lists, trees, data tables, menus, color pickers, modals, toasts, and more
  • Reactive state -- Ref, Computed, WatchEffect, reactive Array and Record types that drive automatic UI updates
  • JSON theming -- style every widget property from a single JSON file; ships with 7 built-in themes
  • XML templates -- declare layouts in XML with reactive bindings, conditionals, and event handlers
  • Layout system -- VBox, HBox, Anchor, Flow, and TwoColumn layouts with padding, spacing, and alignment
  • Rich text -- inline markup for bold, italic, color, and size within a single text widget
  • Focus management -- tab navigation, focus rings, and keyboard-driven interaction
  • Screen management -- push, pop, and replace screens with a built-in stage manager
  • Visual test runner -- automated screenshot testing via JSON scripts and input injection

Quick Start

go get github.com/devthicket/willowui
package main

import (
	"github.com/devthicket/willow"
	ui "github.com/devthicket/willowui"
)

func main() {
	font := ui.MustLoadDefaultFont()
	clicks := ui.NewRef(0)

	btn := ui.NewButton("inc", "+1", font, 16)
	btn.SetOnClick(ui.Increment(clicks, 1))

	label := ui.NewLabel("count", "0", font, 36)
	formatted, _ := ui.BindFormatterf(clicks, "Count: %d") // app-lifetime: handle not stopped
	label.BindText(formatted)

	row := ui.NewHBox("row")
	row.Spacing = 16
	row.SetPosition(20, 15)
	row.AddChild(btn)
	row.AddChild(label)

	ui.Setup(ui.StageConfig{
		Title:      "Counter",
		Width:      400,
		Height:     70,
		ClearColor: willow.RGBA(0.08, 0.08, 0.10, 1),
	}, row)
}

Widgets

CategoryWidgets
InputButton, IconButton, TextInput, TextArea, MaskedInput, KeybindInput, SearchBox
SelectionCheckbox, RadioButton, Toggle, OptionRotator, Select
RangeSlider, NumberStepper, ProgressBar, MeterBar, ScrollBar
ListsList, TreeList, TileList, SortableList, SortableTreeList, DataTable, TreeTable
ContainersPanel, Window, ScrollPanel, NavDrawer, Accordion, Popover
NavigationTabBar, ToggleButtonBar, ToolBar, MenuBar
DisplayLabel, RichText, Badge, Tag, TagBar, Tooltip, Toast, Image, AnimatedImage
SpecialtyColorPicker, GradientEditor, ImageCropper, TimePicker, CalendarSelector, StatWeb, DragHandle, InputField
Widget gallery (click to expand)
AccordionCalendar
CheckboxColor Picker
Data TableList
Masked InputMenu Bar
Number StepperOption Rotator
Progress BarRadio
Scroll PanelSelect
SliderSortable List
Sortable Tree ListStat Web
Tab BarTag Bar
Text AreaText Input
Tile ListTime Picker
ToggleToggle Button Bar
TooltipTree List
WindowButton

Theming

Themes are plain JSON. Load one and every widget picks it up:

theme, err := ui.LoadThemeFromFile("themes/dark.json")
ui.SetTheme(theme)

Ships with 7 built-in themes: dark, forest, jrpg, macos, neon, windows, and debug. Create your own -- each widget type has its own section with full control over colors, corners, padding, and more. See the theme docs for the full schema.

XML Templates

Define layouts declaratively and bind reactive state:

<VBox padding="16" spacing="8">
    <Label text="Hello, {{name}}" fontSize="24" />
    <Button text="Click me" on:click="handleClick" />
</VBox>

Templates compile to a binary format for fast startup, and support hot reload during development.

Examples

The examples/ directory has 60+ runnable demos:

go run ./examples/widgets/buttons/
go run ./examples/reactive/counter/
go run ./examples/templating/xml-basic/
go run ./examples/theming/theme-gallery/

Documentation

Built with

  • Go 1.24+
  • Willow -- scene graph rendering engine
  • Ebitengine v2.9+ -- GPU backend

Contributing

Contributions are welcome. Please open an issue first for major changes to discuss the design. For bug fixes and small improvements, open a pull request directly.

go build ./...
go test ./...
go vet ./...

License

MIT