ui.drawing is stateless draw helpers that append to a DefaultCommandList. Surface Description calls them internally. Reach for them when you need drawing outside the node tree:
- Building custom nodes before upstream helpers exist
- Drawing in legacy widget
drawmethods (otter-bar) - Composing one-off chrome (
monitor.zig,auth_surface.zig)
drawing.zig does not look up theme globals. Pass colors from your loaded Theme.
Module map
| Submodule | Exports |
|---|---|
drawing.core | panel, border, control, listRow, wrappedText |
drawing.frame | roundedFill, surfacePanel, controlFrame, textBaselineY |
drawing.controls | button, toggle, checkbox, tabBar, scrollbar, formRow, numberInput, progressBar, colorSwatch, dropdown |
drawing.input | inputBox, wrappingInputBox, passwordInputBox |
drawing.text | truncateText, textTruncated |
drawing.select | Select trigger rendering |
drawing.dropdown | dropdownOverlay, hit tests for menu rows |
drawing.color_picker | colorPickerPopup, HSV, hit tests |
Common parameters
| Parameter | Type | Notes |
|---|---|---|
cmds | *DefaultCommandList | Collects draw commands |
rect | geo.Rect | Destination in logical pixels |
font | *render.Font | Required for text primitives |
style | per-function struct | Colors, padding, radius |
theme | passed by caller | Not stored inside drawing |
cmds.scale from the Wayland surface scale before drawing (Surface Description does this in begin()).
Controls (drawing.controls)
button
ButtonStyle: background, hover_background, pressed_background, text_color, border_color, radius, padding, font_size, disabled.
toggle
Pill switch. ToggleStyle: on_color, off_color, thumb_color, disabled_color.
checkbox
Box + optional label. CheckboxStyle: box_color, check_color, text_color, font_size.
iconButton
Icon over label stack (logout menu pattern). IconButtonStyle: border, hover, icon_size, padding.
dropdown / dropdownOverlay
Trigger row and floating option list. Pair with dropdownOverlayHitTest for manual hit routing outside Surface Description.
tabBar
Horizontal tabs. TabBarStyle mirrors TabsSpec colors.
scrollbar / roundedScrollbar
Track + thumb from ui.ScrollState. ScrollbarStyle: track/thumb colors, width, radius.
formRow / sectionHeader
Settings rows: fixed label column + value text.
numberInput
Decrement, value field, increment. Returns NumberInputResult with sub-rects. Use numberInputHitTest for three-zone clicks.
progressBar
Track + fill by value_0_100 (0..100 byte percent).
colorSwatch
Small filled square with optional checkerboard for alpha.
Text input (drawing.input)
inputBox
Single-line field with cursor, selection, placeholder, IME preedit underline.
InputBoxStyle: background, text_color, placeholder_color, cursor_color, selection_color, border_color, font_size, padding, border_width, radius.
Helpers:
inputBoxCursorFromClick/wrappingInputBoxCursorFromClickwrappingInputBox+wrappingInputBoxHeightfor multilinepasswordInputBox+maskUtf8for masked fields
Text (drawing.text)
truncateText/textTruncated: ellipsis overflow for narrow rectswrappedText/wrappedTextHeight: multiline word wrap
text_system through cmds when drawing RTL or CJK (same as Surface Description).
Panels and frames (drawing.frame, drawing.core)
surfacePanel: raised card with shadow (settings panels)controlFrame: inset background inside a border (inputs, buttons)roundedFill/roundedBorder: low-level rounded rectspanel,border,control: composable building blockslistRow: selectable row with optional icon (launcher results)
Color picker (drawing.color_picker)
colorPickerHitTest returns which sub-region (SV, hue, alpha) was clicked. colorPickerUpdate maps drag position to new color.
When to use primitives vs nodes
Use SurfaceNode | Use drawing.* directly |
|---|---|
| App windows and forms | Bar widget draw specs |
Anything needing hitTest / dispatch | Fully custom render loops |
| Settings, monitor, lock UI | monitor.zig graph/table helpers |
Related modules
ui.table: sortable tables for monitor-style UIs (usesdrawing+ directcmds)ui.monitor: sidebar, graphs, search box built on primitivesui.auth_surface: lock/greeter shared auth layoutui.overlay_chrome: loupe/crosshair for screenshot tools
Next
- Nodes and controls: Surface Description wrappers around these primitives
- Bar widgets: daemon widget draw path

