Skip to content
Subha Sundar Das edited this page Jul 14, 2026 · 6 revisions

New to RetUI? You're in the right place.

There are only 8 ideas to learn. Once they click, everything else in RetUI will make sense. Let's go through them one at a time, with real, working code.


1. Everything is a Component

Think of a component as a little Lego brick. You snap bricks together to build bigger things.

In code, a component is just a Go function that returns a retui.Element. That's it.

func Greeting() retui.Element {
    return retui.Text("Hello, World!", retui.NewStyle())
}

Want to use it? Just call it:

func App() retui.Element {
    return Greeting()
}

Takeaway: If a function returns retui.Element, it's a component. You'll write dozens of these.


2. Components Nest Inside Each Other

Here's the part that makes RetUI powerful: components can contain other components.

The main container you'll use is Box. Think of Box as an invisible wrapper that arranges whatever you put inside it.

func App() retui.Element {
    return retui.Box(
        retui.Props{Direction: retui.Column},
        retui.NewStyle(),
        retui.Text("Welcome", retui.NewStyle().Bold(true)),
        retui.Text("Hello RetUI!", retui.NewStyle()),
    )
}

That creates a Box holding two pieces of text, stacked vertically:

Welcome
Hello RetUI!

You can keep nesting boxes inside boxes, as deep as you need:

Box
├── Box
│   ├── Text
│   └── Text
└── Text

Takeaway: Box is your primary layout container. Most screens start with one.


3. Don't Worry About Redrawing — RetUI Does It For You

One of the nicest things about RetUI is that you never manually clear or redraw the terminal.

When your application's data changes, RetUI automatically updates only the parts of the screen that actually changed.

Before: Counter: 5
After:  Counter: 6

Only the 6 is updated. The rest of the screen stays untouched, making your application feel smooth and flicker-free.

Takeaway: Change your data. RetUI updates the screen automatically.


4. State = Data That Can Change

"State" is simply data that your component remembers between renders.

Without state, values never change:

retui.Text("Counter: 0", retui.NewStyle())

With state:

count, setCount := retui.UseState(0)

retui.Text(
    fmt.Sprintf("Counter: %d", count),
    retui.NewStyle(),
)
  • count → current value
  • setCount → function used to update it
setCount(count + 1)

As soon as you call setCount, RetUI re-renders the component automatically.

Example: A Simple Counter

import (
    "fmt"

    "github.com/subhasundardass/retui/retui"
)

func Counter() retui.Element {
    count, setCount := retui.UseState(0)

    // Give this component a focus slot so it can receive key presses
    retui.SetFocusOrder([]string{"counter"})
    if retui.CurrentFocus() == "" {
        retui.SetFocus("counter")
    }

    if retui.IsFocused("counter") {
        switch retui.CurrentKey.Code {
        case retui.KeyUp, retui.KeyEnter, retui.KeySpace:
            setCount(count + 1)
        case retui.KeyDown:
            setCount(count - 1)
        }
    }

    return retui.Box(
        retui.Props{Direction: retui.Column, Gap: 1},
        retui.NewStyle(),
        retui.Text(fmt.Sprintf("Counter: %d", count), retui.NewStyle()),
        retui.Text("↑ / Space / Enter: +1    ↓: -1", retui.NewStyle().Foreground(retui.Hex("#888888"))),
    )
}

Run this example and click the button—the counter increases automatically.

Takeaway: UseState gives you a value and a setter. RetUI takes care of updating the UI.


5. Hooks: How Components Remember Things

Hooks are simply helper functions that let components keep information between renders.

The most commonly used hook is UseState.

RetUI currently provides four hooks:

Hook Purpose Think of it as...
UseState Store a changing value A sticky note
UseStateKeyed Store state for dynamic items like trees and lists A labeled sticky note
UseEffect Run code when something changes "When this changes, do that."
UseContext Share data across many components A shared notice board

You don't need to master all of them immediately.

Most applications use UseState far more than anything else.

Takeaway: Learn UseState first. The others will feel natural later.


6. Layout: Row or Column?

RetUI doesn't use pixel coordinates.

Instead, you describe how elements should be arranged.

Horizontal Layout (retui.Row)

retui.Box(
    retui.Props{
        Direction: retui.Row,
        Gap:       2,
    },
    retui.NewStyle(),

    retui.Text("Left", retui.NewStyle()),
    retui.Text("Right", retui.NewStyle()),
)

Output:

Left  Right

Vertical Layout (retui.Column)

retui.Box(
    retui.Props{
        Direction: retui.Column,
    },
    retui.NewStyle(),

    retui.Text("One", retui.NewStyle()),
    retui.Text("Two", retui.NewStyle()),
    retui.Text("Three", retui.NewStyle()),
)

Output:

One
Two
Three

You can combine rows and columns to build almost any layout.

Row
├── Column
│   ├── Header
│   └── Content
└── Sidebar

Takeaway: Row places items side by side. Column stacks them vertically.


7. Keyboard Focus

Terminal applications are keyboard-first.

RetUI always knows which interactive component currently has focus.

Name:  [Subha      ]  ← Focused
Email: [            ]

Press Tab:

Name:  [Subha      ]
Email: [user@mail.com]  ← Focused

RetUI provides focus management utilities such as:

  • SetFocus()
  • CurrentFocus()
  • IsFocused()
  • SetFocusOrder()

You define the focus order once, and RetUI handles keyboard navigation.

Takeaway: You don't manually manage which control is active.


8. Build Once, Reuse Everywhere

Whenever you notice yourself copying the same UI more than once, convert it into a reusable component.

Instead of repeating:

retui.Box(
    retui.Props{
        Direction: retui.Column,
    },
    retui.NewStyle(),

    retui.Text(
        "User",
        retui.NewStyle().Bold(true),
    ),
)

Create a component:

func UserPanel() retui.Element {
    return retui.Box(
        retui.Props{
            Direction: retui.Column,
        },
        retui.NewStyle(),

        retui.Text(
            "User",
            retui.NewStyle().Bold(true),
        ),
    )
}

Now reuse it anywhere:

func App() retui.Element {
    return retui.Box(
        retui.Props{
            Direction: retui.Column,
            Gap:       1,
        },
        retui.NewStyle(),

        UserPanel(),
        UserPanel(),
    )
}

Takeaway: If you copy the same UI twice, it's probably time to make a component.


Quick Recap

Concept Summary
Component A function that returns retui.Element
Nesting Components can contain other components
Auto Update Change state and RetUI updates the screen automatically
State UseState gives you a value and a setter
Hooks UseState, UseStateKeyed, UseEffect, UseContext
Layout Row arranges horizontally, Column arranges vertically
Focus RetUI tracks the active component automatically
Reuse Wrap repeated UI into reusable components

What's Next?

Now that you understand the core ideas, you're ready to learn how to build real applications with RetUI.

The next recommended guides are:

  1. Layout System
  2. Styling
  3. Components
  4. State Management
  5. Keyboard Events
  6. Navigation
  7. Overlays & Dialogs
  8. Building Your First App

These eight concepts are the foundation of everything you'll build in RetUI.

Clone this wiki locally