Teaches coding agents how to build TUIs with TamboUI correctly: API-level selection, render-thread discipline, display-width safety, CSS-aware element authoring, and JFR conventions.
87
90%
Does it follow best practices?
Impact
84%
1.44xAverage score across 5 eval scenarios
Passed
No known issues
textInput(state).onSubmit(...) takes a Runnable, not a Consumer<String>. The submitted text is read out of the bound TextInputState, not passed as a callback argument. Why: most TUI libraries pass the submitted line into the handler; TamboUI does not, and writing the more familiar onSubmit { line -> ... } produces either a compile error or a handler that runs but never sees the text — both look like "submit doesn't work."
val state = textInputState()
textInput(state).onSubmit(Runnable {
val line = state.text()
if (line.isNotBlank()) {
send(line)
}
state.clear()
})Java equivalent:
TextInputState state = textInputState();
textInput(state).onSubmit(() -> {
String line = state.text();
if (!line.isEmpty()) {
send(line);
}
state.clear();
});TextInputState is the source of truth for the buffer and cursor — reading from there is the same source the next render usesstate.clear() to reset for the next line — two operations where one sufficesstate.clear() is mandatory at the end of the handler unless you want the previous line to persist visibly in the input boxprivate val state: TextInputState (see [[persistent-stateful-elements]]), the handler can safely reference it directly.onSubmit { line -> ... } (lambda taking a String) — compile error: Runnable is zero-arg.onSubmit(Consumer<String> { ... }) — compile error: wrong typestate.clear() — input keeps accumulating across submitstextInput(textInputState()) inline in render() — the state object is discarded every frame, see [[persistent-stateful-elements]]evals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
rules
skills