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
Import from the root re-export:
Common parameters
Set
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
Prefer Surface Description for new code. Primitives remain the implementation layer and escape hatch.
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

