tamboui/tamboui

[Windows] Toolkit-DSL: Components not rendering

Open

#258 opened on Feb 23, 2026

View on GitHub
 (4 comments) (0 reactions) (0 assignees)Java (44 forks)github user discovery
help wanted

Repository metrics

Stars
 (522 stars)
PR merge metrics
 (Avg merge 16d 12h) (1 merged PR in 30d)

Description

Hi

I'm relatively tempted in trying to create a "bigger" CLI application using TamboUI. But There are a couple of steps I'm either missing or that are not working as I'd expected them to do.

Simple app:

fun main() {
    TestApp().run()
}

// extended example with custom components and config
class TestApp : ToolkitApp() {

    override fun configure(): TuiConfig? {
        return TuiConfig.builder()
            // .mouseCapture(true)
            // .hideCursor(true)
            .fpsOverlay(true)
            .tickRate(50.milliseconds.toJavaDuration()) // 16 for 60 FPS, 33 for 30 FPS, 50 for 20 FPS
            .build()
    }

    override fun render(): Element? {
        return panel(
            "Hello",
            text("Welcome to TamboUI DSL!").bold().cyan(),
            object : Component<Nothing>() {
                override fun render(): Element? {
                    return text("This is a placeholder component").bold().cyan()
                }
            }.id("placeholder-component"),
            column(
                Button("Click me!").id("button-1"),
                CounterComponent().id("counter-1")
            ),
            spacer(),
            text("Press 'q' to quit").dim()
        ).rounded()
    }
}

// my own attempts
class Button(
    private val title: String,
    private val handleKeyEvent: KeyEvent.() -> EventResult = { EventResult.UNHANDLED }
) : Component<Button>() {
    override fun preferredSize(): Size? {
        return Size.heightOnly(3)
    }

    override fun render(): Element =
        panel(text(title))
            .rounded()
    // .borderColor(if (isFocused) Color.GREEN else Color.GRAY)
    // .focusable(true)
    // .onKeyEvent { if (isFocused) it.handleKeyEvent() else EventResult.UNHANDLED }

    override fun handleKeyEvent(event: KeyEvent, focused: Boolean): EventResult? {
        if (isFocused && EventResult.HANDLED == event.handleKeyEvent()) {
            return EventResult.HANDLED
        }
        return super.handleKeyEvent(event, focused)
    }
}

// from the examples
class CounterComponent : Component<CounterComponent>() {
    var count = 0

    @OnAction(Actions.MOVE_UP)
    fun increment(event: Event) {
        count++
    }

    override fun render(): Element {
        return text("Count: " + count)
    }
}

Regardless whether I use the default config, Java 21 and JLine- or 25 and Panama-backend, the components are never displayed. I tried a more complex UI (without custom components) where on the other hand I falied to properly attach Key handlers.

So basically it's working 50% or more but never to the extend I hoped.

Do you see anything wrong the little app or do you have some general suggestions what I should change?

Kind regards Daniel

Contributor guide