Skip to content

Widgets

Widgets come in two shapes. The functions in widgets and widgets/chart are stateless: each takes its data (and usually a theme.Theme) and returns a styled string to place in a view. Anything with state, such as a cursor, a scroll offset or an open/closed flag, is a component in its own top-level package, with a value-typed Model, a New constructor, and Update and View methods.

fmt.Println(ansi.StripANSI(widgets.Box("Status", "all good", theme.DarkTheme(), 20)))
// Output:
// ┌──────────────────┐
// │ │
// │ Status │
// │ all good │
// │ │
// └──────────────────┘

From ExampleBox in widgets/example_test.go.

A component is embedded in your own model. You hold its Model in a field, pass messages to its Update, keep the Model it returns, and draw its View or LayoutNode. It has no Init. The root package names these shapes, and packages assert them at compile time with lines such as var _ tui.Component[Model] = Model{}:

Contract Shape Asserted by
tui.Component[T] Update(tui.Msg) (T, tui.Cmd), View() string accordion, appshell, autocomplete, clipboard, clockview, colorpicker, commandpalette, confirm, datatable, datepicker, emailinput, errorretry, faces, filepicker, form, loadingbar, logview, maskedinput, menu, multiselect, numberinput, passwordinput, picker, skeleton, spinner, streamtext, tabs, taginput, textarea, textinput, toolapproval, treeview, viewport, virtuallist
tui.Overlay[T] Open() bool, Update, Render(base string) string. It composites onto a drawn frame. Show and Hide are pointer methods outside the interface contextmenu, dialog, drawer, helpscreen, menubar, popover, toast
tui.ThemeSetter[T] SetTheme(theme.Theme) T every component except clockview, logview, markdown, viewport and wizard; see Theming
tui.Linearizer Linearize() string, plain text for accessible output every component has the method; most assert it. See Accessibility
tui.CursorProvider CursorCell() (x, y int, ok bool) textarea, textinput

Every component Model also has LayoutNode(), a test enforces it, and most have Tokens() and WithTokens(). Some packages implement a contract’s methods without the assertion: scrollbar and splitpane have Update/View, and notificationcenter has Render(base string) with no Update. wizard.Model and markdown.Model take the theme as an argument to View and LayoutNode. For layout see Layout. For keys, focus and the KeyMap convention see Input.

“Keys” marks packages with a KeyMap field, DefaultKeyMap() and Bindings(). “Experimental” packages say so in their package comment, and their API may change in any minor release. The example column names a program in examples/ that imports the package.

Package Purpose (from the package comment) Keys Example program
accordion A list of collapsible sections yes examples/settings
appshell Header, full-width input, scrollable content and optional key-hints footer, composed from existing widgets. Experimental
autocomplete A text input with a filtered suggestion dropdown yes examples/form
clipboard A “copy to clipboard” button that writes OSC 52. Experimental
clockview A wall-clock, stopwatch or countdown timer
colorpicker A palette-swatch and hex-input colour picker yes
commandpalette A text input with a fuzzy-filtered dropdown of Commands (“Ctrl+K” style). Experimental yes
confirm A yes/no prompt yes examples/form
contextmenu A popup menu opened at an anchor point yes
datatable widgets.Table plus row navigation yes examples/table, examples/inspector
datepicker A keyboard-navigable calendar on time.Time yes
dialog A modal box with title and message, composited over the screen, dismissed with Enter/Esc yes examples/dashboard
drawer An overlay anchored to an edge of the base view yes
emailinput A textinput.Model wrapper that rejects whitespace
errorretry An error with retry (Enter or r, up to MaxRetries) and dismiss (Esc). Experimental yes
faces A catalog of 50 animated Braille characters and a widget that plays them. Experimental examples/faces
filepicker A filesystem browser, one directory at a time yes
form A validating column of labelled fields with Submit yes examples/login, examples/signup
helpscreen A full-screen key-binding help overlay
imageview A PNG drawn with the kitty graphics protocol or Sixel, or a text placeholder. Experimental
loadingbar An indeterminate progress animation examples/dashboard
logview An append-only scrolling log examples/procstream
markdown A CommonMark subset rendered as styled, width-aware text examples/chat, examples/agentshell
maskedinput A textinput.Model wrapper that masks each character with a configurable rune
menu Nested-navigation list on top of picker.Model yes
menubar A horizontal bar of titled dropdown menus yes
multiselect A multi-choice list: Space toggles, Enter confirms yes examples/list
notificationcenter A panel showing every queued notification at once. Experimental
numberinput A textinput.Model wrapper that accepts digits and one leading -
passwordinput A textinput.Model wrapper that masks the value examples/focus
picker A single-choice list (InkUI’s “Select”) yes examples/loginflow, examples/router, examples/setupflow
popover An overlay anchored near a point yes
scrollbar A track and thumb showing how much content is visible and where yes
skeleton A loading placeholder block
spinner An animated loading indicator examples/asyncload, examples/buildlog, examples/inlinespinners
splitpane Two layout.Nodes with a divider moved by keyboard or mouse yes
streamtext Text revealed a few characters at a time (New streams, NewTypewriter types). Experimental examples/chat, examples/agentshell
tabs A horizontal tab bar yes examples/settings, examples/inspector
taginput A text input plus a list of committed tags drawn as widgets.Tag chips yes
textarea A multi-line text input yes examples/focus, examples/agentshell
textinput A single-line text input yes examples/focus, examples/cursorfield, examples/form
toast A transient notification in a screen corner that closes after Duration examples/dashboard
toolapproval A gate-before-execution prompt for an agent tool call. Experimental yes examples/agentshell
treeview A hierarchical expandable tree yes examples/inspector
viewport A scrollable window onto content taller than it yes examples/pager
virtuallist A scrolling window onto a large uniform-height list that never builds off-screen rows yes
wizard Step navigation for multi-step flows, drawn with widgets.Stepper examples/form

Every package listed has an Example in its example_test.go (TestEveryPackageHasExample in exampleevery_test.go requires one per package).

Everything in widgets is a pure function of its arguments that returns a string. It needs no Msg handling and never imports tui or a component package: it sits below the components. Use layout.Block(s) (or widgets.Node(s), the same adapter) to place the result in a layout.

Kind Functions
Containers and labels Alert, Badge, Banner, Box, Card, InfoBox, Panel, Tag, Tooltip, TooltipOverlay, Center, Spacer
Separators and headings Divider, DividerLabel, DividerWith, DividerLabelWith, Header, HeaderWithAccessory, Breadcrumb
Progress and status ProgressBar, ProgressCircle, MultiProgress, StatusIndicator, Stepper, Pagination, PaginationDots
Controls drawn as text Checkbox, Toggle, FormField, Form
Lists and tables List, ListWith, KeyValue, Table, TableRows, TableRowsWith
Key hints KeyHint, KeyHints, HintsFromKeymap
Text formatting CodeBlock, CodeBlockLang, DiffView, Gradient, BigText, BigTextGradient, Link
Chat and agent helpers ChatMessage, ChatMessageRaw, TokenCounter, UsageMonitor, CompactCount
Error isolation ErrorBoundary renders a fallback if the render function panics

widgets/chart holds the data plots: Sparkline, SparklineWith, BarChart, LineChart, HeatMap and Gauge, each with a Linearize... function for accessible output. The functions of the same names in widgets are deprecated wrappers for the chart versions. examples/chat and examples/dashboard use widgets/chart.

examples/welcomescreen, examples/splashscreen, examples/loginflow and examples/setupflow build whole screens from widgets functions and a layout.Row.