Skip to content

Widgets

Tachikoma includes dozens of widgets covering text display, input controls, data visualization, navigation, and containers. All widgets follow the render protocol: render(widget, area::Rect, buf::Buffer).

Value Protocol

Many widgets support a unified value interface:

julia
value(widget)            # get the widget's current value
set_value!(widget, v)    # set the widget's value
valid(widget)            # check if the current value is valid (default: true)

Text Display

Block

Bordered panel with optional title. The workhorse container widget:

julia
block = Block(; title="Panel", border_style=tstyle(:border),
               title_style=tstyle(:title, bold=true), box=BOX_ROUNDED)
inner = render(block, area, buf)   # returns inner Rect after drawing borders
block_basic example

Box styles: BOX_ROUNDED, BOX_HEAVY, BOX_DOUBLE, BOX_PLAIN.

Paragraph

Styled text with wrapping and alignment:

julia
para = Paragraph([
    Span("Bold text ", tstyle(:text, bold=true)),
    Span("and dim text", tstyle(:text_dim)),
]; wrap=word_wrap, alignment=align_center)

render(para, area, buf)
paragraph_basic example
julia
para = Paragraph([Span("Hello ", tstyle(:text)), Span("world", tstyle(:accent))])
paragraph_line_count(para, 40)   # count wrapped lines for a given width

Wrap modes: no_wrap, word_wrap, char_wrap. Alignment: align_left, align_center, align_right.

Span

Inline styled text fragment, used inside Paragraph and StatusBar:

julia
Span("text", tstyle(:primary, bold=true))
span_demo example

BigText

Large block-character text (5 rows tall):

julia
bt = BigText("12:34"; style=tstyle(:primary, bold=true))
render(bt, area, buf)
bigtext_basic example
julia
intrinsic_size(BigText("12:34"))   # (width, height) in terminal cells

StatusBar

Full-width bar with left and right aligned spans:

julia
render(StatusBar(
    left=[Span("  Status: OK ", tstyle(:success))],
    right=[Span("[q] quit ", tstyle(:text_dim))],
), area, buf)
statusbar_basic example

Separator

Visual divider line:

julia
render(Separator(), area, buf)
separator_basic example

Input Widgets

TextInput

Single-line text editor with optional validation:

julia
input = TextInput(; text="initial", label="Name:", focused=true,
                   validator=s -> length(s) < 2 ? "Min 2 chars" : nothing)
textinput_demo example
julia
handle_key!(input, evt)   # returns true if consumed
text(input)                # get current text
set_text!(input, "new")    # set text
value(input)               # same as text()
valid(input)               # true if validator returns nothing

The validator function receives the current text and returns nothing (valid) or an error message string.

TextArea

Multi-line text editor:

julia
area = TextArea(; text="", label="Bio:", focused=true)
textarea_demo example
julia
handle_key!(area, evt)
handle_mouse!(area, evt, rect)
text(area)
set_text!(area, "multi\nline")

CodeEditor

Syntax-highlighted code editor:

julia
CodeEditor(; text="function greet(name)\n    println(\"Hello, \$name!\")\nend",
    focused=true, block=Block(title="editor.jl", border_style=tstyle(:border),
    title_style=tstyle(:title)))
codeeditor_demo example
julia
handle_key!(editor, evt)
editor_mode(editor)        # current mode symbol

Supports Julia syntax highlighting with token types: token_keyword, token_string, token_comment, token_number, token_plain.

Checkbox

Boolean toggle:

julia
cb = Checkbox("Enable notifications"; focused=false)
checkbox_demo example
julia
handle_key!(cb, evt)       # space toggles
value(cb)                  # true/false
set_value!(cb, true)

RadioGroup

Mutually exclusive selection:

julia
rg = RadioGroup(["Admin", "Editor", "Viewer"])
radiogroup_demo example
julia
handle_key!(rg, evt)       # up/down + space/enter to select
value(rg)                  # selected index (Int)
set_value!(rg, 2)

Select from a dropdown list:

julia
dd = DropDown(["Tokyo", "Berlin", "NYC", "London"])
dropdown_demo example
julia
handle_key!(dd, evt)       # enter opens, up/down navigates, enter selects
value(dd)                  # selected index (Int)

Calendar

Date picker widget:

julia
cal = Calendar(2026, 2; today=19)
render(cal, area, buf)
calendar_basic example

Selection & Navigation

SelectableList

Keyboard and mouse navigable list:

julia
list = SelectableList(["Alpha", "Beta", "Gamma", "Delta", "Epsilon"];
                      selected=1, focused=true,
                      block=Block(title="Items"),
                      highlight_style=tstyle(:accent, bold=true),
                      marker=MARKER)
selectablelist_demo example
julia
handle_key!(list, evt)
value(list)                # selected index
set_value!(list, 2)
list_hit(list, x, y, area)    # hit test → index or nothing
list_scroll(list, lines)       # scroll by n lines

With styled items:

julia
items = [ListItem("Item 1", tstyle(:text)),
         ListItem("Item 2", tstyle(:warning))]
list = SelectableList(items; selected=1)

TreeView / TreeNode

Hierarchical tree display:

julia
root = TreeNode("Root", [
    TreeNode("Child 1", [
        TreeNode("Leaf A"),
        TreeNode("Leaf B"),
    ]),
    TreeNode("Child 2"),
])

tree = TreeView(root; block=Block(title="Tree"))
render(tree, area, buf)
treeview_basic example
julia
handle_key!(tree, evt)     # up/down navigate, enter expand/collapse

TabBar

Tab switching:

julia
tabs = TabBar(["Overview", "Details", "Settings"]; active=2)
render(tabs, area, buf)
tabbar_basic example
julia
handle_key!(tabs, evt)     # left/right to switch
value(tabs)                # selected tab index

Confirmation dialog:

julia
modal = Modal(; title="Delete?", message="This cannot be undone.",
               confirm_label="Delete", cancel_label="Cancel",
               selected=:cancel)
render(modal, area, buf)
modal_basic example

Data Visualization

Sparkline

Mini line chart from a data vector:

julia
Sparkline(data; style=tstyle(:accent))
sparkline_demo example

Gauge

Progress bar (0.0 to 1.0):

julia
Gauge(progress;
    filled_style=tstyle(:primary),
    empty_style=tstyle(:text_dim, dim=true),
    tick=tick)
gauge_demo example

BarChart

Bar chart with labeled entries:

julia
entries = [BarEntry("CPU", 65.0), BarEntry("MEM", 42.0), BarEntry("DSK", 78.0)]
render(BarChart(entries; block=Block(title="Usage")), area, buf)
barchart_basic example

Chart

Line and scatter plots with multiple data series:

julia
cpu_data = Float64[0.3 + 0.2 * sin(i * 0.3) for i in 1:30]
mem_data = Float64[0.5 + 0.1 * cos(i * 0.2) for i in 1:30]
series = [
    DataSeries(cpu_data; label="CPU", style=tstyle(:primary)),
    DataSeries(mem_data; label="Mem", style=tstyle(:secondary)),
]
render(Chart(series; block=Block(title="System")), area, buf)
chart_basic example

Chart types: chart_line, chart_scatter.

Table

Simple row/column table:

julia
headers = ["Name", "Status", "CPU"]
rows = [["nginx", "running", "12%"],
        ["postgres", "running", "8%"]]

render(Table(headers, rows;
    block=Block(title="Processes"),
    header_style=tstyle(:title, bold=true),
    row_style=tstyle(:text),
    alt_row_style=tstyle(:text_dim)), area, buf)
table_basic example

DataTable

Sortable, filterable data table with pagination:

julia
dt = DataTable([
    DataColumn("Name",  ["Alice", "Bob", "Carol"]),
    DataColumn("Score", [95, 82, 91]; align=col_right),
    DataColumn("Grade", ["A", "B", "A"]; align=col_center),
]; selected=1)
render(dt, area, buf)
datatable_basic example

Sort directions: sort_none, sort_asc, sort_desc. Column alignment: col_left, col_right, col_center.

With the Tables.jl extension, DataTable accepts any Tables.jl source:

julia
using Tables
dt = DataTable(my_dataframe)

Containers & Control

Form / FormField

Multi-field form with focus navigation and validation:

julia
form = Form([
    FormField("Name", TextInput(; validator=s -> isempty(s) ? "Required" : nothing);
              required=true),
    FormField("Bio", TextArea()),
    FormField("Notify", Checkbox("Enable notifications")),
    FormField("Role", RadioGroup(["Admin", "Editor", "Viewer"])),
    FormField("City", DropDown(["Tokyo", "Berlin", "NYC"])),
]; submit_label="Submit",
   block=Block(title="Registration"))
render(form, area, buf)
form_basic example
julia
handle_key!(form, evt)     # Tab/Shift-Tab navigation, widget key handling
value(form)                # Dict{String, Any} of field label → value
valid(form)                # true if all required fields are valid

Button

Clickable button:

julia
btn = Button("Submit"; style=tstyle(:primary), focused=true)
render(btn, area, buf)
button_basic example
julia
handle_key!(btn, evt)      # enter/space triggers

ScrollPane

Scrollable container for content:

julia
sp = ScrollPane(["Line 1", "Line 2", "Line 3"]; following=true)
push_line!(sp, "new line")           # append content
render(sp, area, buf)
scrollpane_basic example
julia
handle_mouse!(sp, evt, area)         # scrollbar drag + scroll wheel

Scrollbar

Standalone scrollbar indicator:

julia
sb = Scrollbar(100, 20, 0)
render(sb, area, buf)
scrollbar_basic example

ProgressList / ProgressItem

Task status list with status icons:

julia
items = [
    ProgressItem("Build"; status=task_done),
    ProgressItem("Test"; status=task_running),
    ProgressItem("Deploy"; status=task_pending),
]
render(ProgressList(items; tick=tick), area, buf)
progresslist_basic example

Task statuses: task_pending, task_running, task_done, task_error, task_skipped.

FocusRing

Tab/Shift-Tab navigation manager — cycles focus between panes or widgets (see Input & Events for the full example):

julia
ring = FocusRing([widget1, widget2, widget3])
handle_key!(ring, evt)
current(ring)
next!(ring)
prev!(ring)
focusring_widget_demo example

Container

Group widgets with automatic layout:

julia
container = Container(
    [widget1, widget2, widget3],
    Layout(Vertical, [Fixed(3), Fill(), Fixed(1)]),
    Block(title="Metrics")
)
container_basic example

MarkdownPane

Scrollable CommonMark viewer with styled headings, bold/italic, inline code, code blocks with syntax highlighting, lists, block quotes, and horizontal rules. Requires the markdown extension (enable_markdown() or using CommonMark).

julia
enable_markdown()
pane = MarkdownPane("# Hello\n\n**Bold**, *italic*, `code`.\n\n- Item 1\n- Item 2";
    block=Block(title="Docs"))
render(pane, area, buf)
markdownpane_basic example

Update content dynamically with set_markdown!:

julia
set_markdown!(pane, "# Updated\n\nNew content here.")

Supports keyboard scrolling (//Page Up/Page Down) and mouse wheel. Automatically reflows text when the render width changes.