Skip to content

Programmatic API

curveo edited this page May 12, 2026 · 8 revisions

Programmatic API

The programmatic API lets you build TesseraUI panels directly in Java — useful for highly dynamic screens, reusable widgets, or situations where an HTML template adds unnecessary indirection.


TesseraPanel

The core container widget.

Creating panels

// Column (vertical stack)
TesseraPanel panel = TesseraPanel.column(x, y, width, height);

// Row (horizontal stack)
TesseraPanel row = TesseraPanel.row(x, y, width, height);

// Grid (N columns)
TesseraPanel grid = TesseraPanel.grid(3, x, y, width, height);

Styling

panel
    .background(0xFF1A1208)          // ARGB colour
    .border(1, 0xFFB87333)           // thickness, ARGB colour
    .borderRadius(4)
    .padding(8)                      // all sides
    .padding(4, 8, 4, 8)             // top, right, bottom, left
    .gap(6)                          // space between children
    .opacity(0.9f);

Hover styles

panel
    .hoverBackground(0xFF2A3050)
    .hoverBorder(0xFFE8A24A);

Adding children

// Natural size, no flex participation
panel.add(child);

// With flex weight (grow and shrink equally)
panel.add(child, 1);

// Full CSS flex parameters: grow, shrink, basis, order, zIndex, alignSelf, marginTopAuto, margins
panel.add(child, 1f, 1f, 0, 0, 0, null, false, 0, 0, 0, 0);

Layout

Call layout() after adding all children or after resizing:

panel.layout();

Sizing utilities

// Measure height needed to fit all content
int height = panel.fitContentHeight();
panel.setSize(panel.getWidth(), height);
panel.layout();

Events

panel.onClick(() -> System.out.println("clicked"));
panel.onRightClick(() -> openContextMenu());

TesseraLabel

Single-line or wrapping text label.

TesseraLabel label = new TesseraLabel(0, 0, width, height, "Hello world");
label
    .color(TesseraPalette.CREAM)
    .fontSize(7f)
    .fontWeight(700)             // bold
    .textAlign("center")
    .wrap(true)                  // enable word-wrap
    .opacity(0.8f);

TesseraButton

TesseraButton btn = new TesseraButton(0, 0, 80, 14);
btn
    .label("Save")
    .bgColor(0xFF5C3A1E)
    .labelColor(TesseraPalette.COPPER_HI)
    .fontSize(7f)
    .onClick(this::onSave)
    .hoverBgColor(0xFF7C5A2E);

TesseraInput

Single-line text field.

TesseraInput input = new TesseraInput(0, 0, 120, 14);
input
    .placeholder("Enter name…")
    .text("default")
    .maxLength(32)
    .bgColor(0xFF2A2010)
    .borderColor(TesseraPalette.COPPER_LO)
    .textColor(TesseraPalette.CREAM)
    .padding(5, 3)
    .onChange(value -> this.name = value)
    .onSubmit(value -> this.save());

Persistent state

Attach a TesseraInputState to preserve text across rebuilds:

private final TesseraInputState nameState = new TesseraInputState();

// On rebuild:
input.state(nameState);

TesseraTextArea

Multi-line text field.

TesseraTextArea ta = new TesseraTextArea(0, 0, 200, 60);
ta
    .placeholder("Write here…")
    .maxLength(2048)
    .rows(4)
    .bgColor(0xFF2A2010)
    .onChange(value -> this.notes = value);

TesseraCheckbox

TesseraCheckbox cb = new TesseraCheckbox(0, 0, 10, 10, /* checked= */ false);
cb.onToggle(checked -> this.enabled = checked);

TesseraSlider

TesseraSlider slider = new TesseraSlider(0, 0, 100, 10, 0f, 100f, 50f);
slider.onInput(value -> this.volume = Float.parseFloat(value));

TesseraDropdown

TesseraDropdown dd = new TesseraDropdown(0, 0, 100, 14);
dd.addOption("easy",   "Easy");
dd.addOption("normal", "Normal");
dd.addOption("hard",   "Hard");
dd.select("normal");
dd.onSelect(value -> this.difficulty = value);

TesseraIcon

TesseraIcon icon = new TesseraIcon(0, 0, 16, 16);
icon
    .texture(ResourceLocation.fromNamespaceAndPath("yourmod", "textures/gui/icons/settings.png"))
    .tint(TesseraPalette.COPPER_HI)
    .size(16, 16)
    .onClick(this::openSettings);

TesseraBadge

TesseraBadge badge = new TesseraBadge(0, 0, 12, "Epic", 0xFF8B5CF6);
badge.textColor(0xFFFFFFFF).paddingH(6);

TesseraTabPanel

TesseraTabPanel tabs = new TesseraTabPanel(0, 0, 200, 120);

TesseraPanel generalTab = TesseraPanel.column(0, 0, 200, 106).padding(6).gap(4);
generalTab.add(new TesseraLabel(0, 0, 188, 10, "General settings"));
generalTab.layout();

TesseraPanel advancedTab = TesseraPanel.column(0, 0, 200, 106).padding(6).gap(4);
advancedTab.layout();

tabs.addTab("General",  generalTab);
tabs.addTab("Advanced", advancedTab);

TesseraVirtualList

Efficient scrolling list that renders only visible rows:

List<TesseraModel> items = /* ... */;
int rowHeight = 18;

TesseraVirtualList list = TesseraVirtualList.of(items, rowHeight, model -> {
    TesseraPanel row = TesseraPanel.row(0, 0, listWidth, rowHeight).gap(4).padding(2, 4, 2, 4);
    row.add(new TesseraLabel(0, 0, 0, 10, model.resolve("name")).color(TesseraPalette.CREAM));
    row.layout();
    return row;
});
list.setSize(listWidth, 100);
list.background(TesseraPalette.BG1);
panel.add(list);

TesseraScreen

Base class for screens that use TesseraUI:

public class MyScreen extends TesseraScreen {

    private TesseraPanel root;

    public MyScreen() {
        super(Component.literal("My Screen"));
    }

    @Override
    protected void init() {
        rebuild();
    }

    private void rebuild() {
        int pw = Math.min(width, 400);
        int ph = Math.min(height, 260);
        root = TesseraPanel.column((width - pw) / 2, (height - ph) / 2, pw, ph)
                .background(TesseraPalette.BG0)
                .border(1, TesseraPalette.COPPER_LO)
                .padding(8).gap(6);

        root.add(new TesseraLabel(0, 0, pw - 16, 10, "My Screen")
                .color(TesseraPalette.COPPER_HI).fontSize(8f));

        root.layout();
    }

    @Override
    protected TesseraPanel tesseraRoot() { return root; }

    @Override
    public boolean isPauseScreen() { return false; }
}

TesseraScreen automatically wires:

  • render() — background + root panel + overlays
  • mouseClicked(), mouseDragged(), mouseReleased(), mouseScrolled()
  • keyPressed(), charTyped()
  • renderTesseraOverlays() — inventory picker, drag ghost, tooltips

Clone this wiki locally