smidr.widgets

..
UIAccordion

A collapsible section header: chevron, all-caps title, underline and an optional right-aligned hint. The owner toggles its section's content visibility from onToggle(expanded) and re-flows the layout.

UIBadge

A small count/status bubble: a rounded pill sized to its text, meant to overlay a button or icon (position it yourself at the corner). A zero count hides it unless showZero; counts past maxCount show as N+. Set text for a non-numeric label (e.g. "NEW"). Non-interactive.

UIBalloon

A callout / popover: a rounded panel with a directional tail pointing at an anchor point, shown on UIRoot.popupLayer. Add content to body (below the optional title). It prefers to sit below the anchor with the tail pointing up, flips above when it would clip the viewport bottom, and clamps horizontally while keeping the tail aimed at the anchor.

UIBreadcrumb

A path/navigation trail: clickable segments separated by chevrons, with the last segment shown as the current (brighter) location. Clicking a segment fires onSelect(index). Set the trail with setPath; the row hit-tests segment x-ranges rather than nesting child widgets.

UIButton

A clickable button. Variants: default (panel surface), accent (primary action) and danger (destructive). Hover lightens, press dips; the click fires on press-started release (see UIComponent).

UICheckbox

A labelled checkbox row: label on the left, accent check square on the right (or standalone square when the label is empty). Clicking anywhere on the row toggles; onToggle(checked) fires after the flip.

UIChip

A compact pill chip. With hasDot = true it's a stateful toggle showing a status dot (on flips on click, then onToggle(on) fires); without a dot it's a value chip whose text the owner updates and whose onClick typically cycles the value. Auto-sizes to its label.

UIColorPicker

An inline HSV colour picker: a saturation/value square, a vertical hue strip, a live swatch + hex readout, and a row of preset swatches. Dragging the square sets saturation (x) and value (y); dragging the strip sets hue; clicking a preset jumps to it. onChange fires continuously while dragging with the opaque 0xFFRRGGBB colour.

UIDataColumn

One column of a UIDataGrid: a title, a base (unscaled) width, cell alignment, and whether the header sorts by it (numerically when numeric).

UIDataGrid

A virtualized data table: a fixed header of columns above a UIList of rows, where each row draws one text cell per column. Only on-screen rows exist as display objects (inherited from UIList), so a table of any height stays cheap.

UIDateTimePicker

A labelled date (and optional time) field: label left, value box right. Clicking the box opens a calendar popup on UIRoot.popupLayer behind a click-blocking backdrop (Escape or an outside click closes it). Navigate months with the header arrows and click a day to pick it; with showTime the popup adds hour/minute steppers and a Set button, otherwise a day click commits immediately.

UIDockGroup

A leaf of a UIDockHost: a tabbed group of UIDockPanels, one visible at a time. Clicking a tab activates its panel; dragging a tab hands off to the host to re-dock (split, tab into another group, or move). The host sizes and positions the group; do not use it standalone.

UIDockHost

An editor-style docking region: a tree of resizable splits with tabbed UIDockGroups at the leaves. Add panels with addPanel (a new tab in the primary group) or dock(panel, target, zone) (split a target). Dragging a panel's tab re-docks it live — a drop-zone overlay shows where it will land (CENTER tabs into a group, the edges split it), and emptied groups collapse so the tree stays tidy. Split dividers drag to reproportion.

UIDockPanel

One dockable panel: a titled content surface shown in a UIDockGroup tab. Add the panel's widgets to content (origin at the panel's top-left); the hosting group sizes and positions it. The title labels its tab.

UIDrawer

A persistent slide-out panel docked to the left or right viewport edge, for mobile layouts where desktop side panels don't fit. Add widgets to content; the drawer lives on UIRoot.popupLayer above a tap-to-close scrim while open.

UIDrawerSide

Which viewport edge a UIDrawer docks to.

UIDropdown

A labelled dropdown row: label left, value box right. Clicking the box opens a scrollable popup list on UIRoot.popupLayer behind a click-blocking backdrop, so nothing underneath can be interacted with while it is open (Escape or an outside click closes it). display entries override row labels while items holds the raw values delivered to onSelect.

UIExpander

A single collapsible section: a clickable header with a rotating chevron over a body you fill via content. Unlike UIAccordion (which only toggles an external body's visibility), the expander owns its body and its own height grows/shrinks with the state, so h reflects headerHeight plus contentHeight while open. onToggle(open) lets a host relayout.

UIIcon

A themed icon that can be dropped into any widget or layout. Sources:

UIIconRail

A vertical icon rail (Blender/VSCode-style activity bar): fixed-width column of tabs, one active at a time with an accent indicator. onSelect(index) fires on change.

UIKeybind

A key-binding row: label left, binding box right showing the current key. Clicking the box enters listening mode (UIFocus.typing gates the host's keybinds automatically); the next key pressed becomes the binding and fires onChange(keyCode). Escape cancels; with allowClear on, Backspace/Delete clears the binding (fires onChange(-1)) — disable allowClear to make those keys bindable. Works on mobile only with a hardware keyboard attached; desktop-oriented.

UILabel

A themed, non-interactive text label. tone picks the theme text ramp (PRIMARY/SECONDARY/ TERTIARY) so theme swaps restyle it; colorOverride pins an explicit ARGB color instead. Set key (+ fallback) for localized text, or assign text directly.

UIList

A virtualized, selectable list. Only the visible rows (+2) exist as display objects; they are recycled by modulo slot mapping, so scrolling by one row rebinds exactly one row and a 100k-entry list costs the same as a 20-entry one. Rows are fixed-height (the constraint that keeps the window math O(1)).

UIListRow

One recyclable list row. The default implementation renders a single label via UIList.labelOf; subclass and override bind()/render() for custom content, supplying instances through UIList.rowFactory. Never construct rows yourself outside a factory — the list owns the pool.

UIMenuBar

A desktop menu bar. Clicking a title opens its dropdown (UIContextMenu); while one is open, hovering another title switches to it. An optional brand label renders before the menus and arbitrary widgets can be laid over the right side by the owner.

UIMenuDef

One top-level menu: a title plus an item factory (evaluated on open, so checkmarks and shortcut labels are always current).

UIModal

A modal dialog panel centered over a dimmed, click-blocking backdrop on UIRoot.popupLayer. Add content to body (coordinates relative to the panel, below the title). Escape or the backdrop click closes it (unless dismissable = false). Opens/closes with a short fade+scale.

UIPanel

A filled surface: chrome bands, cards, placeholders. Non-interactive but blocking by default (children stay interactive, pointer hits never fall through). corner rounds the fill; the four border* flags draw 1px themed edges and outline draws a full 1px frame.

UIPieMenu

A radial (pie) menu: entries laid out as donut sectors around the open point on UIRoot.popupLayer, behind a click-blocking backdrop. Moving the pointer highlights the sector under it; clicking a sector runs its onSelect and closes. Escape or an outside click closes with no selection. Reuses UIMenuItem (label/key/onSelect/disabled; separators and shortcuts are ignored here).

UIProgressBar

A progress bar for any long-running operation (downloads, uploads, decompression, loading).

UIRadioGroup

An exclusive-choice list of radio options (the vertical counterpart to UISegmentedControl): a stacked column of rows, each a dot on the left and a label on the right, with exactly one selected. Clicking a row selects it and fires onSelect(index); picking another clears the previous one.

UIRating

A star rating: a row of max stars, filled up to rating. Clicking or dragging sets the rating (with a live hover preview), unless readOnly. onChange fires with the new 1-based rating (0 when cleared by clicking the current single star). Uses the built-in STAR glyph.

UIScrollPane

A fixed-size, vertically scrollable container. Add children to content; call refreshContent() after (re)filling it. Scrolls by mouse wheel and by dragging the slim scrollbar thumb; on mobile (touchScroll) dragging anywhere scrolls with fling momentum — a drag past the threshold steals the press so no child widget clicks. Clipping uses scrollRect (GPU clip — scrolling never repaints children).

UISegmentedControl

An exclusive-choice segmented control (radio group): label left, equal-width segments in a box on the right. Exactly one segment is selected; picking another slides the accent pill over and fires onSelect(index). Taller by default on mobile for touch.

UISeparator

A 1px themed divider line (horizontal by default).

UISlider

A labelled horizontal slider: label left, track + knob right, current value drawn beside the knob. Dragging anywhere on the track seeks; onChange(value) fires while dragging.

UISpinner

An indeterminate busy spinner: a faint full ring with a brighter sweeping arc that rotates while spinning. It steps a UIRoot ticker (only while spinning) and repaints the arc each frame, so an idle spinner costs nothing. Pair it with UIProgressBar for determinate work.

UISplitter

Two resizable panes with a draggable divider: side by side (vertical = false) or stacked (vertical = true). Add each pane's content to first / second (origin at the pane's top-left); the panes are clipped to their region, so overflow is hidden and only in-region content takes the pointer. Dragging the divider moves the split, honouring minFirst / minSecond.

UIStack

A flow-layout container: stacks its children in a row (vertical = false) or column (vertical = true), spaced by gap with padding around the group. stretch sizes each UIComponent child to fill the cross axis; otherwise align places them (START/CENTER/END). The main axis auto-grows to fit — a vertical stack keeps its given width and computes its height, a horizontal stack keeps its height and computes its width.

UIStatusBar

A bottom status bar: a themed strip of text cells, left-packed by default with a rightAlign flag to pack from the right (line/column, encoding, clock). Thin separators divide adjacent cells on the same side. Passive but blocking, so it never leaks pointer hits to content behind it; span it across the window and update cells in place with setText.

UIStatusCell

One UIStatusBar cell. width fixes the cell width (0/omitted auto-sizes to the text); rightAlign packs it from the right edge instead of the left.

UIStepper

A labelled numeric - value + row: label left, stepper box right. Clicking -/+ changes by step, clamped to [min, max]; holding repeats after a delay with acceleration. Clicking the value itself types a number directly (Enter/blur commits, Escape cancels). onChange(value) fires on every change; decimals controls display rounding.

UISwitch

A labelled toggle switch row: label left, animated track + knob right. Clicking anywhere on the row flips the state and fires onToggle(on). The track colour and knob position tween between states. Larger track and row height on mobile for touch.

UITabDef

One UITabs tab definition.

UITabs

A horizontal tab strip (the horizontal counterpart to UIIconRail): content-width cells, one active at a time with an accent underline that slides between tabs. The owner switches panel content from onSelect(index). Taller by default on mobile for touch.

UITextArea

A multi-line, scrollable text editor — the note-taking / code surface the single-line UITextInput is not. It owns text editing (caret, selection, scrolling, clipboard, variable line heights) but is deliberately style-agnostic: it carries one opaque Int style word per character and defers all meaning to an optional installed styler (smidr.text.UITextStyler).

UITextInput

A labelled single-line text field: label left, input box right. Click to focus; while focused it captures the keyboard (UIFocus.typing) — caret, Shift+arrow selection, Home/End, Ctrl+A/C/X/V, Backspace/Delete word-aware basics, Enter commits (onEnter), Escape blurs. onChange(text) fires on every edit.

UITile

One recyclable tile. The default draws an optional glyph over a centered label; subclass and override bind()/render() for custom content, supplying instances through UITileGrid.tileFactory. Never construct tiles yourself outside a factory.

UITileGrid

A virtualized icon/tile grid: fixed-size tiles that reflow into as many columns as the width allows, scrolled vertically. Like UIList only the on-screen tiles (+ two rows) exist as display objects and are recycled by slot mapping, so a grid of any size is cheap.

UIToolbar

A horizontal button strip: add text or icon buttons, separators, and flexible spacers. The toolbar draws a themed bar (background + bottom border + separator ticks) and lays its items out left to right; spacers absorb the leftover width, so items after a spacer are pushed to the right edge. Buttons are ordinary UIButtons returned for further tweaking (accent, etc.).

UITreeNode

One node in a UITreeView model: a label, an ordered list of children, and an expanded flag. depth is derived by the tree during flattening; treat it as read-only.

UITreeView

A hierarchical, expandable tree. It reuses UIList's virtualization: the tree keeps a mutable node model and flattens the currently-visible nodes (collapsed subtrees excluded) into a flat array, which feeds the list as its provider. So a 100k-node tree still only instantiates the handful of rows on screen, exactly like UIList.

UIWindow

A draggable, titled window and the supported way to build movable tool panels. Parent the window's widgets into content (its origin sits just below the title bar) and they move with the window for free: they are plain display-list children, so layouts are written once in window-local coordinates and never touched again on drag.