Teek API Documentation

The build surface: ui.<widget> methods that APPEND nodes to the Document tree. They never touch Tk - widgets become live only when the realizer runs at realize.

Names are deliberately Tk-free (the litmus test: if decoding a name needs Tk knowledge, the name is wrong) - see the design sketch for the full vocabulary rationale.

Mixed into Session rather than living on a separate accessor, so the DSL reads as ui.button(...), not ui.widgets.button(...).

Included classes must provide @document (a Document), @stack (an Array of Node, current-parent stack seeded with @document.root), @scope_stack (an Array of Scope, current-scope stack seeded with [Scope::TOP_LEVEL] - see #component), @vars (an Array of Var), and @images (an Array of Image) - Session sets all five up in initialize. They must also provide #build_open? (a predicate the tree-mutating methods below check via #raise_if_closed! - true before the initial realize and again for the duration of an #add block, false otherwise).

Instance Methods

[](name)

Look up a named widget declared in the CURRENT scope: at the top level outside any #component, that’s everything built outside one; inside a component’s own block, only that component’s own names - a sibling component’s (or the top level’s) same-named node is never found this way, and vice versa. See #component.

Parameters
  • name Symbol

Returns Handle, nil

box(name nil, **opts, &block)

box is a bare alternate spelling of panel - same node type, so the realizer only ever has to know about :panel.

cell(row:, col:, span: 1)

Position the single widget declared in the block at (row, col) in the enclosing ui.grid. Only valid directly inside a grid’s block.

Parameters
  • row Integer
  • col Integer
  • span Integer — how many columns this cell spans

Returns void

@yield _self

@yieldparam _self Teek::UI::WidgetDSL the object that the method was called on

component(label nil, &block)

Opens a fresh Scope around the block, so names declared inside it (ui.button(:save), …) never collide with the same name used elsewhere - in another component, or at the top level - no matter how many components share the same (or no) label, since Scope identity, not label, is what makes two scopes distinct. Splices its content directly into whatever’s currently open - this is scope isolation only, not an extra layer of nesting, so a component built inside ui.panel(:p) attaches as an ordinary child of `:p`, exactly like any other widget declared right there would. The common 80% case - a plain method that takes `ui` and appends into whatever's already open (`def toolbar(ui) = ui.row `...) - needs none of this; reach for #component only when scope isolation itself is the point (reuse across files, avoiding name collisions).

The returned ComponentHandle is the disciplined way for the caller to reach into the component’s own named widgets afterward (screen.handle(:action)/screen[:action]) - the global ui[] never sees into a component’s scope (see #[]), so a component built in one file and mounted from another stays reachable only through the facade it hands back, not by guessing its internal names.

Parameters
  • label Symbol, String, nil — a human-readable label for error messages/debugging - has no bearing on uniqueness

Returns ComponentHandle

@yieldparam c self build the component's content with the ordinary widget DSL, same as any other block

context_menu(name nil, **opts, &block)

A standalone popup menu - built the same declarative way as a menu_bar’s dropdowns, but not attached to anything automatically. Wire it to a widget with handle.on_right_click(this).

Parameters
  • name Symbol, nil

Returns Handle

@yieldparam m MenuBuilder

current_path

The current build-parent ancestry, as a readable breadcrumb (e.g. "column > row") - derived from @stack, the one thing only the builder (not the Document) knows: which containers are currently open. Useful in a build-time error message ("X added outside a Y; current parent: #current_path") or just to orient yourself while poking around mid-build.

Returns String"(top level)" when nothing is currently open

dialog(name nil, modal: true, resizable: false, **opts, &block)

window with dialog-appropriate defaults - modal and fixed-size, for the common “small modal window” case (confirmations, pickers). Same underlying node type as window, just different defaults for modal:/resizable: - both still overridable.

Returns Handle

image(path, **opts)

Declare an image, loaded from a file. Its Tcl image name is allocated now (no interpreter needed - it’s just a string); the backing Teek::Photo - and the actual file load - only becomes real at realize. Pass it as a widget’s image: option (or a later handle.configure(image: ...)) to display it.

Parameters
  • path String — path to an image file (any format Tk's own `image create photo -file` accepts - PNG, GIF, ...)
  • opts Hash — forwarded to Teek::Photo.new - e.g. width:/height:/format:/palette:/gamma:

Returns Image

menu_bar(name nil, **opts, &block)

A window’s menu bar - the row of top-level dropdowns (File/Edit/…) along its top edge. Valid at the top level of a build or directly inside ui.window - attaches to whichever of those it’s declared in once realized.

Parameters
  • name Symbol, nil

Returns Handle

@raise ArgumentError if declared anywhere other than the top level or directly inside ui.window

@yieldparam mb MenuBuilder

overlay(at:)

Floats the single widget declared in the block on top of the enclosing ui.canvas, positioned at a fixed corner/edge/center anchor via Tk’s place geometry manager - a “use sparingly” escape valve for the one legitimate absolute-position case (a status readout or button bar layered over canvas content), not a general-purpose layout mode. Stays correctly positioned across a canvas resize with nothing to redo by hand - place’s relative coordinates are fractions of the canvas’s current size, recomputed live by Tk on every resize. Only valid directly inside a ui.canvas block.

Parameters

Returns void

@raise ArgumentError if declared anywhere other than directly inside ui.canvas, given an unrecognized at:, or its block builds anything other than exactly one widget

pane(name nil, weight: nil, **opts, &block)

One region of an enclosing ui.split. Only valid directly inside a ui.split block; its own block builds the pane’s content with the ordinary widget DSL, same as any other container.

Parameters
  • name Symbol, nil — for `ui[:name]` lookup, same as any widget
  • weight Integer, nil — how much of the leftover space this pane absorbs when the split is resized, relative to its sibling panes' weights - unset panes get Tk's own default (0, fixed size until dragged). The same plain word `ttk::panedwindow` itself uses for this.

Returns Handle

@raise ArgumentError if declared anywhere other than directly inside ui.split

raw(&block)

The build-time escape hatch. A widget has no Tk path yet during build, so app.command(handle.path, ...) mid-build can’t work - ui.raw defers the block instead, running it at realize with the live app in scope. It’s a closure, so it can still reference sibling widgets by name (ui[:other].path) even if they’re declared later - by the time any raw block runs, the whole tree has already been realized once over (same forward-reference guarantee event target: gets). For anything after realize, a live Handle/session.app is the escape hatch instead - see the README for the full split.

Returns nil

@yieldparam app Teek::App

screens

A push/pop stack for content screens - see Screens. One stack per build, created on first access.

Returns Screens

split(name nil, orientation: :horizontal, **opts, &block)

A draggable split - two or more #pane-declared regions, resizable by dragging the sash between them. Maps to ttk::panedwindow.

Parameters
  • name Symbol, nil — for `ui[:name]` lookup, same as any widget
  • orientation Symbol:horizontal (panes side by side, a vertical sash) or :vertical (panes stacked, a horizontal sash)

Returns Handle

@raise ArgumentError if orientation isn't :horizontal or :vertical

@yieldparam s self build panes with `s.pane ...`

stretch(columns: [], rows: [])

Mark which columns/rows of the enclosing ui.grid absorb leftover space - the named replacement for grid columnconfigure -weight. Only valid directly inside a grid’s block.

Parameters
  • columns Array<Integer>
  • rows Array<Integer>

Returns void

tab(label, name nil, **opts, &block)

One page of an enclosing ui.tabs, labeled label in the tab bar. Only valid directly inside a ui.tabs block; its own block builds the pane’s content with the ordinary widget DSL, same as any other container.

Parameters
  • label String — the tab's title, shown in the tab bar
  • name Symbol, nil — for `ui[:name]` lookup, same as any widget

Returns Handle

@raise ArgumentError if declared anywhere other than directly inside ui.tabs

var(initial)

Declare a reactive variable. Its Tcl variable name is allocated now (no interpreter needed - it’s just a string); the variable itself only becomes real at realize. Bind it to widgets with bind:.

Parameters
  • initial Object — initial value - its class decides how Var#value coerces later (Integer/Float/Boolean typed, else String)

Returns Var

Attributes

modal [R]

A push/pop stack for modal window handles - see ModalStack. nil until assigned; unlike #screens it isn’t created automatically, since its callbacks (on_enter:/on_exit:) are mandatory and app-specific: ui.modal = Teek::UI::ModalStack.new(on_enter:, on_exit:).

Returns ModalStack, nil

Used By
Included by: