Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

227 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, dashboard/data widgets, charts and desktop-shell pieces — around 30 kLoC of widget code with roughly 40 kLoC of tests.

Status

v0.109.0 — broad GTK 4 / DaisyUI / desktop-shell coverage. The widget set has grown well past the early parity passes into a full application toolkit: ~150 widget types across inputs, containers, overlays, structural rows, semantic banners, a dashboard/data suite, a chart family, desktop-shell pieces (status area, wallpaper, command palette), and a loading-screen Skeleton family. A declarative Container + swappable Layout model (FitLayout, BoxLayout, BorderLayout, CardLayout, FlowLayout) sits under the convenience containers (HBox/VBox/Grid/Frame/Dock/ Border).

~150 widget types + 10 stock icons, ~30 kLoC 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, Accessible/A11yInfo, Focusable, Measurer
Text bitmap 5x7 + anti-aliased NewTrueTypeFont, one-call AA default UseOpenTypeText, global SetFont + per-widget Base.Font, DrawText, TextWidth, Label
Action Button, ToggleButton, CheckButton, RadioButton + RadioGroup, Switch, SplitButton, IconButton, CycleButton, Chip, SegmentedBar
Input Entry, TextView + Selection + IME preview + optional Highlighter (syntax spans) + ShowLineNumbers gutter, SpinButton, Scale, RangeSlider, SearchEntry, TagField, ComboBox, FormField, Validate/Rule
Terminal TerminalView (Cols×Rows TermCell grid, block cursor, wrap/scroll, per-cell FG/BG)
Selection ListBox, TreeView, DropDown
Containers Container + swappable Layout (FitLayout, BoxLayout, BorderLayout, CardLayout, FlowLayout); convenience wrappers HBox, VBox, Grid, Frame, Dock, Border, Stack, Overlay, Paned, Expander, Accordion; declarative Node builder + ViewController (LookupAs)
Tabs Notebook, ViewSwitcher, Carousel
Scroll ScrollView, Scrollbar
Feedback ProgressBar, ProgressCircle, LevelBar, Spinner, Image, Tooltip, Notification, Toast, Banner, Alert, Badge, LoadMask, Backdrop, FocusRing
Loading Skeleton (Text/Rect/Circle/Avatar/Block kinds, shimmer via SetPhase), SkeletonGroup, NewSkeletonCard, NewPageSkeleton
Structure Card, HeaderBar, ActionRow, Breadcrumbs, Steps, Avatar, Rating, Stat, Kbd, ChatBubble, Diff, Pagination, DropZone
Navigation Menu + MenuItem.Shortcut, MenuBar + Alt+letter, ContextMenu, Popover, CommandPalette, Dialog, MessageDialog, Wizard
Window Window, WindowDecoration, DecoButton (client-side decorations)
Bars Toolbar, PagingToolbar, Statusbar, 10 stock DrawIcon* helpers
Composite FileChooser, ColorChooser, ColorPicker, FontChooser, Calendar, DatePicker, DateRangePicker, TimePicker, MarkdownView, MarkdownEditor
Data suite Table (cell edit, frozen columns, group rows, aggregates, row-expanders), TreeTable, PropertyGrid, Kanban (drag cards), Gantt (drag/resize bars), Agenda/AgendaCalendar event calendar (week/month/quarter/year, colour-coded calendars, sidebar, inline editor)
Charts LineChart, BarChart, PieChart, AreaChart, ScatterChart, RadarChart, Gauge, Sparkline
Shell StatusIcon, StatusArea, Wallpaper, Thumbnail
Motion Easing/Tween (Linear, EaseIn*/Out*/InOut*), GestureRecognizer
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).
  • Skeleton (loading placeholders) — shape kinds Text (rounded bars, tunable LineH/LineGap/LastFrac/Radius), Rect (rounded media block), Circle (avatar), plus the original Avatar/Block swap-parity kinds. Optional diagonal shimmer band (a lighter tint over Theme.SurfaceAlt, working in light + dark) driven by SetPhase(t) advanced per frame. SkeletonGroup composes primitives; presets NewSkeletonCard(bounds) (avatar + 2-line header + media block) and NewPageSkeleton(bounds) (top bar + paragraph groups + image blocks, the webengine browser client's loading screen).
  • 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. Extended since with anti-aliased vector text (NewTrueTypeFont(ttf, px)) and, from v0.34, a per-widget font: set widget.Font (the exported Base.Font field) to give one widget its own face/size — e.g. a 10px badge next to a 22px title — while every other widget keeps the global SetFont font. A widget with no Font set (the default, nil) renders exactly as before. Since v0.77, UseOpenTypeText() turns on anti-aliased, shaped text for the whole UI in one call — it installs the bundled Atkinson Hyperlegible face (from github.com/go-opentype/fonts, no extra imports, js/wasm-safe) as the active font, so consumers get crisp AA/multi-script glyphs without sourcing a face of their own. Use UseOpenTypeTextSize(px) for a specific size, or DefaultOpenTypeFont(px) to compose the default face into a NewFallbackFont chain (add a CJK/Arabic face) before SetFont. The 5x7 bitmap stays the compiled-in default (so existing pixel/metric tests keep their geometry); AA is an explicit opt-in, and SetFont(nil) restores the bitmap.
  • 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

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages