Skip to main content

Widget reference

Tetra widgets describe what appears on the display and how each element is arranged. Import the render module before creating a widget tree:

load("render.star", "render")

Every rendered app returns a render.Root. Nest layout, text, image, shape, chart, and animation widgets below it to build the final 64 × 32 frame.

Shared behavior

Colors accept CSS-style hexadecimal values: #rgb, #rrggbb, #rgba, and #rrggbbaa.

Widgets expose two useful methods:

  • size() returns the rendered width and height. It is especially useful for widgets whose dimensions depend on their content, such as Text.
  • frame_count() returns the number of frames produced by an animated widget, such as Marquee.

Animation

Animation turns its child list into frames. Frame 0 uses the first child, frame 1 uses the second, and so on.

ParameterTypeRequiredPurpose
children[Widget]NoWidgets to render as consecutive frames.
render.Animation(
children=[
render.Circle(diameter=8, color="#4f46e5"),
render.Circle(diameter=12, color="#7c3aed"),
render.Circle(diameter=16, color="#a855f7"),
],
)
Rendered Animation widget example

Box

Box creates a rectangular region. Without color, its background is transparent. It uses all available space unless you set width or height, and centers its child within the resulting area.

ParameterTypeRequiredPurpose
childWidgetNoWidget centered inside the box.
widthintNoMaximum box width in pixels.
heightintNoMaximum box height in pixels.
paddingintNoSpace between the child and the box edges.
colorcolorNoBackground fill.
render.Box(
width=64,
height=32,
color="#111827",
child=render.Text("Hello", color="#f9fafb"),
)
Rendered Box widget example

Circle

Circle draws a filled circle. An optional child is centered inside it.

ParameterTypeRequiredPurpose
colorcolorYesCircle fill.
diameterintYesDiameter in pixels.
childWidgetNoWidget centered in the circle.
render.Circle(
diameter=30,
color="#312e81",
child=render.Circle(diameter=10, color="#22d3ee"),
)
Rendered Circle widget example

Column

Column places children from top to bottom. Its natural height is the combined height of its children, and its width matches the widest child. Set expanded to occupy all available vertical space.

main_align controls vertical distribution:

  • "start", "center", or "end"
  • "space_between", "space_evenly", or "space_around"

cross_align controls horizontal placement with "start", "center", or "end".

ParameterTypeRequiredPurpose
children[Widget]YesWidgets arranged vertically.
main_alignstrNoDistribution along the vertical axis.
cross_alignstrNoAlignment along the horizontal axis.
expandedboolNoFill the available height.
render.Column(
children=[
render.Box(width=12, height=5, color="#22d3ee"),
render.Box(width=22, height=7, color="#fbbf24"),
render.Box(width=32, height=4, color="#a855f7"),
],
)
Column widgets packed vertically using their natural size

With expanded=True, the same children can use the available height and space_around distribution:

render.Column(
expanded=True,
main_align="space_around",
cross_align="center",
children=[
render.Box(width=12, height=5, color="#22d3ee"),
render.Box(width=22, height=7, color="#fbbf24"),
render.Box(width=32, height=4, color="#a855f7"),
],
)
Column widgets distributed vertically with space around them

Image

Image decodes binary PNG, JPEG, GIF, or SVG data supplied through src. Tetra preserves the source dimensions unless width or height is provided; resizing uses nearest-neighbor interpolation. Animated GIFs retain their frames, and their frame delay is available through the read-only delay attribute.

ParameterTypeRequiredPurpose
srcstrYesBinary image data or SVG markup.
widthintNoOutput width in pixels.
heightintNoOutput height in pixels.
delayintNoRead-only GIF frame delay in milliseconds.

This example uses the same PNG with its unnecessary color-profile metadata removed, reducing the encoded value from more than 4,000 characters to about 350 without changing the image:

load("encoding/base64.star", "base64")

ICON = base64.decode(
"iVBORw0KGgoAAAANSUhEUgAAABkAAAAYCAMAAAA4a6b0AAAAJ1BMVEUAAABBJBb+0wvT" +
"min//vr71QQEBAT///cMCQQBCwD6zwT/0BL31g9Dk4qKAAAAAXRSTlMAQObYZgAAAItJ" +
"REFUKM99ktkSgCAIRQW1bPn/7w1kycg6T8TpojOYkgJGegKASn466hdCVIYxYG2mupIA" +
"DujELhDn5kU/a/miGzrGG6WsagDpS2oa4zWN+zNt00FYd61a64b/lMixe6lmdm8ymY" +
"vg622iYuPKcGHmHblVZkZBJqZ8eRAGjgvX2Bm3LTFj8nrCq7oAcPEFwi8JX50AAAAAS" +
"UVORK5CYII="
)

render.Image(src=ICON)
Rendered Image widget example

Marquee

Marquee scrolls content that does not fit its viewport. Horizontal scrolling moves right to left and requires width. Vertical scrolling moves bottom to top and requires height. Content that already fits remains still.

Use offset_start and offset_end to adjust where the motion begins and ends. When no scrolling is required, align accepts "start", "center", or "end".

ParameterTypeRequiredPurpose
childWidgetYesWidget to scroll when it exceeds the viewport.
widthintNoHorizontal viewport width.
heightintNoVertical viewport height.
offset_startintNoStarting position adjustment.
offset_endintNoEnding position adjustment.
scroll_directionstrNo"horizontal" (default) or "vertical".
alignstrNoPlacement when the child fits; defaults to "start".
delayintNoFrames to wait before scrolling; defaults to 0.
render.Marquee(
width=64,
child=render.Text("Welcome to SolidPixels", color="#fbbf24"),
offset_start=4,
offset_end=8,
)
Rendered Marquee widget example

Padding

Padding adds space around one child. Pass one integer to apply the same value on every side, or a (left, top, right, bottom) tuple for individual sides. With expanded=True, the widget fills the bounds supplied by its parent.

ParameterTypeRequiredPurpose
childWidgetYesWidget surrounded by padding.
padint or (int, int, int, int)NoInsets around the child.
expandedboolNoFill the available bounds.
colorcolorNoBackground fill behind the padded area.
render.Padding(
pad=(4, 2, 4, 2),
color="#172554",
child=render.Text("Live", color="#ffffff"),
)
Rendered Padding widget example

PieChart

PieChart displays proportional values as colored sectors. colors and weights are parallel lists, so each weight uses the color at the same index.

ParameterTypeRequiredPurpose
colors[color]YesSector colors.
weights[float]YesRelative sector sizes.
diameterintYesChart diameter in pixels.
render.PieChart(
colors=["#22c55e", "#eab308", "#ef4444"],
weights=[55, 30, 15],
diameter=30,
)
Rendered PieChart widget example

Plot

Plot draws a line or scatter series from (x, y) coordinates. It can style positive and negative values independently and optionally fill the region between the series and the x-axis.

ParameterTypeRequiredPurpose
data[(float, float)]YesOrdered (x, y) points.
widthintYesChart width in pixels.
heightintYesChart height in pixels.
colorcolorNoColor for values at or above zero; defaults to #fff.
color_invertedcolorNoColor for values below zero.
x_lim(float, float)NoVisible x-axis range.
y_lim(float, float)NoVisible y-axis range.
fillboolNoFill between the series and x-axis.
chart_typestrNo"line" (default) or "scatter".
fill_colorcolorNoFill color above zero.
fill_color_invertedcolorNoFill color below zero.
render.Plot(
data=[(0, 2), (1, 5), (2, 3), (3, -1), (4, 4)],
width=64,
height=32,
color="#22d3ee",
color_inverted="#c084fc",
y_lim=(-2, 6),
fill=True,
fill_color="#164e63",
fill_color_inverted="#581c87",
)
Rendered Plot widget example

Root

Root is the top-level widget returned by an app. Its descendants render onto the display canvas, beginning at the upper-left corner. For animated trees, delay sets the time between frames.

Set max_age when old output should expire rather than remain visible after a data source stops updating. show_full_animation asks the device to finish the animation even when it lasts longer than the normal app cycle.

ParameterTypeRequiredPurpose
childWidgetYesWidget tree to render.
delayintNoMilliseconds between animation frames.
max_ageintNoSeconds before the rendered result expires.
show_full_animationboolNoPlay the complete animation during each cycle.
def main(config):
return render.Root(
delay=100,
child=render.Text("Ready", color="#22d3ee"),
)
Rendered Root widget example

Return an empty list ([]) instead when an app should be omitted from the rotation because it has nothing to display.

Row

Row places children from left to right. Its natural width is the combined width of its children, and its height matches the tallest child. Set expanded to occupy all available horizontal space.

main_align controls horizontal distribution:

  • "start", "center", or "end"
  • "space_between", "space_evenly", or "space_around"

cross_align controls vertical placement with "start", "center", or "end".

ParameterTypeRequiredPurpose
children[Widget]YesWidgets arranged horizontally.
main_alignstrNoDistribution along the horizontal axis.
cross_alignstrNoAlignment along the vertical axis.
expandedboolNoFill the available width.
render.Row(
children=[
render.Box(width=10, height=8, color="#22d3ee"),
render.Box(width=14, height=12, color="#fbbf24"),
render.Box(width=20, height=16, color="#a855f7"),
],
)
Row widgets packed horizontally using their natural size

With expanded=True, the same children can use the available width and space_between distribution:

render.Row(
expanded=True,
main_align="space_between",
cross_align="end",
children=[
render.Box(width=10, height=8, color="#22d3ee"),
render.Box(width=14, height=12, color="#fbbf24"),
render.Box(width=20, height=16, color="#a855f7"),
],
)
Row widgets distributed horizontally with space between them

Sequence

Sequence plays animated children one after another. Each child remains active for its own frame count before Tetra advances to the next child.

ParameterTypeRequiredPurpose
children[Widget]YesAnimated widgets played in order.
render.Sequence(
children=[
render.Marquee(width=64, child=render.Text("First message")),
render.Marquee(width=64, child=render.Text("Second message")),
],
)
Rendered Sequence widget example

Stack

Stack paints children on top of one another in list order. Its dimensions are large enough to contain every child, making it useful for backgrounds, overlays, and simple compositing.

ParameterTypeRequiredPurpose
children[Widget]YesWidgets layered in order.
render.Stack(
children=[
render.Box(width=64, height=32, color="#111827"),
render.Text("LIVE", color="#ef4444"),
],
)
Rendered Stack widget example

Text

Text renders one line. The default font is tb-8; use font to select a different bundled face. height constrains its drawing area, while offset moves the glyphs vertically for baseline adjustments.

ParameterTypeRequiredPurpose
contentstrYesText to draw.
fontstrNoFont face name.
heightintNoDrawing-area height.
offsetintNoVertical glyph offset.
colorcolorNoText color.
render.Text(
content="SolidPixels",
font="6x13",
color="#22d3ee",
)
Rendered Text widget example

WrappedText

WrappedText lays text across multiple lines. Set width and height to bound the drawing area; omitted dimensions expand to fit the content. align accepts "left", "center", or "right".

ParameterTypeRequiredPurpose
contentstrYesText to draw.
fontstrNoFont face name.
heightintNoMaximum drawing height.
widthintNoMaximum drawing width.
linespacingintNoSpace between lines.
colorcolorNoText color.
alignstrNo"left", "center", or "right".
render.WrappedText(
content="Updates at a glance",
width=58,
align="center",
color="#f9fafb",
)
Rendered WrappedText widget example