Skip to main content

Layout System

Yazi's plugin UI system lets plugins render custom interface elements using a flexbox-like layout model with constraints and composable widgets.


Geometry Types

Rect

A rectangle with position and size.

FieldTypeDescription
xintegerColumn offset
yintegerRow offset
wintegerWidth in columns
hintegerHeight in rows

Pos

A position (x, y) coordinate.

local pos = ui.Pos { x = 5, y = 10 }

Constraint

Constraints define how space is distributed in a Layout.

ConstructorDescription
Constraint.Ratio(a, b)Proportional space (a out of b total)
Constraint.Length(n)Fixed length of n columns/rows
Constraint.Min(n)At least n columns/rows
Constraint.Max(n)At most n columns/rows
ui.Layout()
:direction(ui.Layout.HORIZONTAL)
:constraints({
ui.Constraint.Ratio(1, 3), -- 1/3 of space
ui.Constraint.Ratio(2, 3), -- 2/3 of space
})

Layout

Arranges child elements according to constraints.

MethodDescription
:direction(dir)Layout.HORIZONTAL or Layout.VERTICAL
:constraints([Constraint])Set distribution constraints
:split(Rect) -> [Rect]Divide a rect into sub-rects

UI Elements

All elements are constructed with a table and rendered via the ui module.

Line

A single row of styled text (inline).

ui.Line { ui.Span("Hello"), ui.Span("World"):bold() }

Text

A multi-line block of text.

ui.Text {
ui.Line { "Line 1" },
ui.Line { "Line 2" },
}

List

A scrollable list of items.

FieldTypeDefaultDescription
items[Line]List items
highlightStyleStyle for the selected item
ui.List {
items = {
ui.Line { "Item A" },
ui.Line { "Item B" },
},
highlight = ui.Style():fg("blue"):bold(),
}

Bar

A horizontal or vertical bar (e.g., scrollbar, progress indicator).

ui.Bar(rect, ui.Bar.VERTICAL)
:symbol(ui.Bar.ASCII)
:style(ui.Style():fg("cyan"))

Border

Wraps content with a border frame.

ui.Border(rect, ui.Border.PLAIN)
StyleDescription
Border.PLAINStraight lines (-, |, +)
Border.ROUNDEDRounded corners
Border.DOUBLEDouble lines
Border.THICKThick lines
Border.EMPTYNo border (invisible)

Gauge

A progress bar.

FieldTypeDescription
percentintegerFill percentage (0–100)
labelstringCenter label text
styleStyleFill style
ui.Gauge {
percent = 65,
label = "65%",
style = ui.Style():fg("green"),
}

Clear

Clears the entire area (erases all content).

ui.Clear(rect)

Table

A table with columns and rows.

ui.Table {
header = { "Name", "Size", "Modified" },
rows = {
{ "foo.txt", "1.2 KB", "2025-01-15" },
{ "bar.md", "4.5 KB", "2025-01-16" },
},
widths = { 20, 10, 15 },
}

Paragraph

A text paragraph with word wrapping.

ui.Paragraph {
text = ui.Line { "Long text that will wrap at the rect boundary..." },
wrap = ui.Paragraph.WORD_WRAP,
}

Sparkline

A mini sparkline chart.

ui.Sparkline {
data = { 1, 4, 2, 8, 5, 7, 3 },
max = 8,
style = ui.Style():fg("yellow"),
}

Rendering Example

local function my_widget(area)
local chunks = ui.Layout()
:direction(ui.Layout.VERTICAL)
:constraints({
ui.Constraint.Length(1),
ui.Constraint.Ratio(1, 1),
ui.Constraint.Length(1),
})
:split(area)

return {
ui.Border(chunks[1], ui.Border.PLAIN),
ui.Text { ui.Line { "Content area" } },
ui.Gauge { percent = 50, label = "progress" },
}
end
tip

All UI elements accept a table constructor and can be styled with method chaining: ui.Span("text"):fg("red"):bold():italic().