Form

termflow.tui.widgets.Form
object Form

Declarative form layout — a vertical column of labelled rows where each row hosts an arbitrary widget that renders itself based on whether it currently owns focus.

Form is presentation-only. Apps own the field state (the current value of each text field, checkbox, button, …) and a FocusManager that tracks which row owns focus. Form lays out the labels + widgets and asks each row's render callback to produce its VNode, passing the focused boolean so the widget renders the appropriate visual.

Validation is also app-side: apps decide on submit (typically when a specific button row is activated) whether the field state is valid and what to do next. The errors parameter just controls per-row error messages drawn beneath each row.

given Theme = Theme.dark
val NameId  = FocusId("name")
val AgreeId = FocusId("agree")
val SaveId  = FocusId("save")

Form.column(
 rows = Vector(
   Form.Row(NameId, "Name:",  focused => widgets.Button(label = nameValue, focused = focused)),
   Form.Row(AgreeId, "Agree:", focused => widgets.CheckBox("I accept", agree, focused)),
   Form.Row(SaveId, "",       focused => widgets.Button("Save", focused))
 ),
 focusManager = model.fm,
 at           = Coord(2.x, 4.y)
)

Value parameters

height

Cell height the row will occupy. Defaults to 1.

id

Stable FocusId for the row — passed to the FocusManager for navigation.

label

Label rendered to the left of the widget. Empty string yields no label cell, just the widget.

widget

Render callback receiving focused: Boolean and returning the row's VNode.

Attributes

Graph
Supertypes
class Object
trait Matchable
class Any
Self type
Form.type

Members list

Type members

Classlikes

final case class Row(id: FocusId, label: String, widget: Boolean => VNode, height: Int)

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Object
trait Matchable
class Any
Show all

Value members

Concrete methods

def column(rows: Vector[Row], focusManager: FocusManager, at: Coord, labelWidth: Int, gap: Int, errors: Map[String, String])(using theme: Theme): List[VNode]

Lay out a column of Rows. Returns one or more VNodes per row (label TextNode + widget VNode), positioned vertically starting at at.

Lay out a column of Rows. Returns one or more VNodes per row (label TextNode + widget VNode), positioned vertically starting at at.

Value parameters

at

Top-left of the first row.

errors

Optional per-row error messages keyed by FocusId.value. Drawn one row below the field in the theme's error slot, padding the row's effective height by 1.

focusManager

Source of "is row N focused?".

gap

Blank rows between fields. Defaults to 0.

labelWidth

Cells reserved for the left-hand label column. Each label is right-padded to this width so the widget column lines up. Set to 0 to omit the label column entirely.

rows

The rows to render.

Attributes

def totalHeight(rows: Vector[Row], gap: Int, errors: Map[String, String]): Int

Total height the form will occupy with the given rows + gap + error annotations. Useful for sizing a containing panel.

Total height the form will occupy with the given rows + gap + error annotations. Useful for sizing a containing panel.

Attributes