Skip to content

go-widgets/toolkit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

go-widgets/toolkit

CI release pkg.go.dev coverage go license

Pure-Go widget toolkit that renders into an RGBA byte buffer. Zero JS / DOM / canvas dependency — every widget composes pixels into a caller-supplied []byte, so the toolkit runs identically in GOOS=js GOARCH=wasm (browser SharedArrayBuffer clients), on any native target Go ships (native canvas backends, image files), or in headless tests (screenshot-hash regressions).

Goals

  • One toolkit per app: consumers stop reinventing buttons, scrollbars, text fields. They import github.com/go-widgets/toolkit and compose.
  • Coherent theming: a single Theme value cascades through every widget — change a colour at the top, see it everywhere. LoadGTKTheme(css) parses libadwaita / GTK3 @define-color declarations into a Theme, so any GTK-desktop palette (Adwaita, Juno, WhiteSur, Solarized …) drives the widget ink colours.
  • Pure Go + CGO=0: no C toolchain, no shared libraries. Builds for every Go target including GOOS=js GOARCH=wasm.
  • A11y bridge: core widgets implement an opt-in Accessible interface (A11y() A11yInfo) so a host can CollectA11y and publish them to screen readers without rewriting every widget.

Non-goals

  • Not a CodeMirror replacement. Complex web-grade editors are best embedded via an iframe overlay at the host level.
  • Not GTK. No CSS engine, no SVG renderer, no full BiDi/IME. A broad primitive set — buttons, inputs, containers, feedback, overlays, structural rows, semantic banners, data displays — around 8 kLoC of widget code with double that in tests.

Status

v0.9 — GTK 4 / DaisyUI parity pass. Three additive waves closed the coverage gap versus libadwaita and DaisyUI 4: v0.7 shipped 9 core widgets (Switch, Badge, Kbd, Alert, Card, Breadcrumbs, Steps, HeaderBar, Table), v0.8 shipped 12 overlays and structural rows (Avatar, Skeleton, Rating, Toast, Banner, Popover, ActionRow, ViewSwitcher, ChatBubble, SearchEntry, Diff, Pagination), v0.9 shipped 8 finishing widgets (SplitButton, IconButton, Stat, Timeline, DropZone, Chip, FormField, ProgressCircle).

62 widgets + 10 stock icons, ~8k LoC of widget code, 100% statement coverage. Pure Go, no CGO, stdlib only. Builds for GOOS=js GOARCH=wasm and every native target Go ships.

Family Widgets
Base Widget, Base, Rect, Event (+ IME composition), Theme, RGBA
Text bitmap 5x7 font (60+ glyphs), DrawText, TextWidth, Label
Action Button, ToggleButton, CheckButton, RadioButton + Group
Input Entry, TextView + Selection + IME preview, SpinButton, Scale, RangeSlider
Selection ListBox, TreeView, DropDown
Layout HBox, VBox, Grid, Frame, Stack, Overlay, Paned, Expander
Tabs Notebook
Scroll ScrollView
Feedback ProgressBar, LevelBar, Spinner, Image, Tooltip, Notification
Navigation Menu + MenuItem.Shortcut, MenuBar + Alt+letter, ContextMenu, Dialog, MessageDialog
Bars Toolbar, Statusbar, 10 stock DrawIcon* helpers
Composite FileChooser, ColorChooser, FontChooser, Calendar, DatePicker, MarkdownView
Charts LineChart, BarChart, PieChart
Theming LoadGTKTheme(css) (GTK3 + libadwaita @define-color → Theme)

v0.6 breaking change

Widget.Draw signature moved from

Draw(surface []byte, surfaceW int, theme *Theme)

to

Draw(p painter.Painter, theme *Theme)

where painter.Painter is a 5-primitive interface (FillRect, StrokeRect, PutPixel, Text, Size). Existing callers that had a []byte + width migrate one line:

// before v0.6:
wg.Draw(surface, w, theme)

// v0.6+:
p := painter.NewPixelPainter(surface, w, h)
wg.Draw(p, theme)

The []byte is still writable + owned by the caller — the PixelPainter just wraps it so the primitives translate to writes. All other widget APIs (Bounds, SetBounds, HitTest, OnEvent, NewButton, …) are unchanged.

toolkit.Rect + toolkit.RGBA became type aliases of painter.Rect + painter.RGBA, so cross-package assignments work transparently.

The 10 DrawIcon* helpers also lost their (surface, surfaceW) prefix; new signature is DrawIconX(p painter.Painter, r Rect, ink RGBA).

Earlier releases

  • v0.9 — 8 widgets: SplitButton (button + attached dropdown arrow), IconButton (toolbar-icon variant), Stat (KPI card with trend indicator), Timeline (vertical event log), DropZone (dashed file drop target), Chip (removable tag), FormField (Label + Child + Help/Error), ProgressCircle (approximated circular progress).
  • v0.8 — 12 widgets: Avatar, Skeleton (Text/Avatar/Block kinds), Rating, Toast (transient bottom-of-screen), Banner (persistent full-width), Popover (Visible container for a Child), ActionRow (libadwaita Title/Subtitle/Prefix/Suffix), ViewSwitcher (segmented tab picker), ChatBubble (User/Other bubble), SearchEntry (Entry with prefix + clear), Diff (Context/Added/Removed colored lines), Pagination (prev/numbers/next with disabled ink).
  • v0.7 — 9 widgets: Switch (iOS-style toggle distinct from ToggleButton), Badge (auto-sizing pill), Kbd (keyboard-shortcut chip), Alert (Info/Success/Warning/Error semantic banner), Card (Title/Body/Footer three-zone), Breadcrumbs (chevron path), Steps (numbered indicator with connector), HeaderBar (Start/Title/ Subtitle/End GTK CSD), Table (Columns/Rows/Selected data grid).
  • v0.6 — Painter back-end abstraction. Every widget's Draw now takes a painter.Painter instead of a fixed []byte + stride pair, so the same widget code renders into a pixel buffer (WUI browser canvas, GUI native window, image file), a terminal cell grid (TUI), or an SVG stream.
  • v0.5 — Toolbar / Statusbar / FileChooser / ColorChooser / Calendar, Selection on TextView, LoadGTKTheme(css), 10 stock icon helpers.
  • v0.4 — 34 widgets. Toolbar / Statusbar, FileChooser / ColorChooser / Calendar, Selection model on TextView, LoadGTKTheme(css).
  • v0.3 — 28 widgets. TextView (multi-line editor), Menu/MenuBar, Dialog/MessageDialog, Tooltip, DropDown, TreeView.
  • v0.2 — 22 widgets. Layout containers (HBox/VBox/Grid/Frame), scroll (ScrollView/ListBox), input (Entry/Check/Radio/Toggle), structural (Stack/Notebook/Paned/Expander), feedback (ProgressBar/LevelBar/Scale/SpinButton/Image/Spinner), bitmap font.
  • v0.1 — scaffolding. Widget interface, Theme value, Button + Label, primitive event dispatch.

Next (v1.0 sketch)

Widget coverage is now materially complete versus GTK 4 + DaisyUI 4. The remaining pre-1.0 work is around the edges of the widget model, not the widget catalogue:

  • Font family plumbingdone (v0.20): a Font interface (Advance, Height, Draw) + a scalable built-in bitmap font. SetFont(NewBitmapFont(2)) doubles all text ("retina"), and every widget re-lays-out because metrics are now read at draw time. Breaking: GlyphHeight / GlyphAdvance and the metric-derived dimensions (CardHeaderH, DatePickerFieldH, DiffLineH, FormFieldLabelH, TimelineEventH, CardFooterH) are now functions — append () at call sites when upgrading.
  • First-class drag-and-drop event kindsdone (v0.16): EventDragStart / EventDragMove / EventDragLeave / EventDrop, plus a DragSource / DropTarget interface pair and SplitDropPayload / JoinDropPayload for multi-item payloads. DropZone dropped its synthetic-EventChar seam and now drives its hover cue + OnDrop from the formal lifecycle as a DropTarget.
  • Context menu helperdone (v0.17): ContextMenu wraps a Menu as a right-click popup — Popup(x, y) shows it at the cursor, it auto-sizes to its items, clamps itself inside the surface, and dismisses on outside-click.
  • Overlay layout containerdone (v0.18): Overlay stacks z-ordered Layers above a primary Content child, so Popover / Toast / Notification / Tooltip / ContextMenu float without hosts arranging z-order. Events route top-down; Modal makes a miss swallow (backdrop) instead of falling through.
  • A11y bridgedone (v0.19): an opt-in Accessible interface (A11y() A11yInfo — role + name + value) implemented by the core widgets (Button/Label/Entry/CheckButton/RadioButton/ Switch/Scale), plus CollectA11y([]Widget) so a host republishes them to the platform layer (WAI-ARIA on wasm, TTY metadata on tui).

Architecture

+----------------------+
| Theme                |  Palette + metrics + font ref
+----------------------+
           |
+----------------------+    +-------------------+
| Widget interface     |    | Event             |
|   Draw(rgba, theme)  |<---|   Kind: click/key |
|   HitTest(x, y)      |    |   X,Y / Code      |
|   OnEvent(ev)        |    +-------------------+
+----------------------+
           |
   +-------+-------+-------+-------+
   |               |       |       |
+--+---+        +--+--+  +-+--+  +-+--+
|Button|        |Label|  |HBox|  | ...|
+------+        +-----+  +----+  +----+

License

BSD 3-Clause. See LICENSE.

About

Pure-Go widget toolkit for wasmdesk native apps (RGBA-buffer renderer, themed, no JS/DOM)

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors