tess

package module
v0.0.0-...-72dc74b Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 3, 2026 License: MIT Imports: 8 Imported by: 0

README

tess

A layout engine in Go powered by Yoga.

// Create a root Node
root, err := tess.NewNode()
root.SetWidth(tess.Point(400))
root.SetHeight(tess.Point(300))
root.SetPadding(tess.Edges{All: tess.Point(20)})

// Add a child to the root Node
child, err := tess.NewNode()
child.SetWidth(tess.Percent(100))
child.SetHeight(tess.Point(150))
root.AppendChild(child)

// Compute the layout to get final positions and sizes
root.ComputeLayout(tess.Container{})

// Get computed layout for a child
layout := root.GetChild(0).GetLayout()
// Use these values to render your element on screen
layout.Left()
layout.Top()
layout.Width()
layout.Height()

Introduction

tess determines the position and size of UI element using browser-style flexbox and style attributes.

It can be used to build terminal UIs, game interfaces, PDF layouts, or anything else where you need flexible box-model positioning.

Core concepts

Nodes - are the building blocks of your layout tree. Each node represents a UI element that needs positioning and sizing.

Styles - controls how nodes behave (width, height, padding, flex direction, etc). Think CSS properties, but for any rendering system.

Layouts - contains the final calculated positions and sizes of nodes that you can use to render elements on screen.

Usage

Installation

go get github.com/AnatoleLucet/tess

Getting started

As a starter project, let's center a div node! (I know right!?)

package main

import (
	"fmt"

	"github.com/AnatoleLucet/tess"
)

func main() {
  // Create a 500x500 container with children aligned and justified to center
  root, err := tess.NewNode()
  root.SetWidth(tess.Point(500)) // Points are the base unit for all measurements (think pixels but with a scale factor applied)
  root.SetHeight(tess.Point(500))
  root.SetJustifyContent(tess.JustifyCenter)
  root.SetAlignItems(tess.AlignCenter)

  // Add a child of 200x200 to the container
  child, err := tess.NewNode()
  child.SetWidth(tess.Point(200))
  child.SetHeight(tess.Point(200))
  root.AppendChild(child)

  root.ComputeLayout(tess.Container{})

  layout := child.GetLayout()
  layout.Left() // 150 (child is centered!)
  layout.Top() // 150
}

Styling

Apply styles to nodes either by calling setter methods or passing a Style struct at creation.

root, err := tess.NewNode()
root.SetWidth(tess.Point(500))
root.SetHeight(tess.Point(500))
// or
root, err := tess.NewNode(&tess.Style{
  Width: tess.Point(500),
  Height: tess.Point(500),
})
Units

tess supports multiple unit types for sizing and positioning:

node.SetWidth(tess.Point(500))    // Absolute points
node.SetWidth(tess.Percent(100))  // Percentage of parent

node.SetWidth(tess.Auto())        // Automatic sizing
node.SetWidth(tess.Stretch())     // Stretch to fill
node.SetWidth(tess.MaxContent())  // Size to content
node.SetWidth(tess.FitContent())  // Fit content with constraints

node.SetWidth(tess.Undefined())   // Unset (use default behavior)
Edges
node.SetMargin(tess.Edges{Horizontal: tess.Point(10)})
node.SetMargin(tess.Edges{Start: tess.Point(10), End: tess.Point(10)})

node.SetPadding(tess.Edges{All: tess.Point(20)})

node.SetBorder(tess.Edges{Bottom: tess.Point(2)})

Computing layouts

After creating your node tree and setting styles, call ComputeLayout() to calculate positions and sizes:

err := root.ComputeLayout(tess.Container{})

The Container parameter specifies available space constraints. Pass an empty container to use the root node's dimensions, or specify width/height to constrain the layout:

err := root.ComputeLayout(tess.Container{
  Width: 1920,
  Height: 1080,

  Direction: tess.RTL, // You can also pass a direction for LTR support!
})

Call ComputeLayout() again whenever you change styles or the node tree to recalculate positions.

Configuring

Configs control global layout behavior. By default, all nodes share the same config.

config := tess.NewConfig()

// Controls pixel density for layout rounding - set to your display's DPI scale
config.SetPointScaleFactor(2.0) // e.g. 2x supersampling for high-DPI displays

// Apply config to a node (and optionally its children if they share this config)
root, err := tess.NewNode()
root.SetConfig(config)

TODOs

  • measurement callbacks
  • baseline callbacks
  • more examples

Credits

  • yoga for powering everything under the hood (so much little salt in this bad boy)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BoxSizingType

type BoxSizingType int
const (
	ContentBox BoxSizingType = iota
	BorderBox
)

func (BoxSizingType) String

func (t BoxSizingType) String() string

type Config

type Config struct {
	// contains filtered or unexported fields
}

func NewConfig

func NewConfig() *Config

func (*Config) GetPointScaleFactor

func (c *Config) GetPointScaleFactor() float32

func (*Config) SetPointScaleFactor

func (c *Config) SetPointScaleFactor(scale float32)

type Container

type Container struct {
	Width     float32
	Height    float32
	Direction DirectionType
}

type DirectionType

type DirectionType int
const (
	Inherit DirectionType = iota
	LTR
	RTL
)

func (DirectionType) String

func (t DirectionType) String() string

type DisplayType

type DisplayType int
const (
	Flex DisplayType = iota
	Contents
	None
)

func (DisplayType) String

func (t DisplayType) String() string

type Edges

type Edges struct {
	Top, Bottom, Left, Right Value
	Start, End               Value
	Horizontal, Vertical     Value
	All                      Value
}

Edges represents values for the edges of a box. Note: Start and End will always be prioritized over Left and Right when both are set.

type FlexAlign

type FlexAlign int
const (
	AlignAuto FlexAlign = iota
	AlignStretch
	AlignBaseline
	AlignStart
	AlignEnd
	AlignCenter
	AlignSpaceBetween
	AlignSpaceAround
	AlignSpaceEvenly
)

func (FlexAlign) String

func (a FlexAlign) String() string

type FlexDirection

type FlexDirection int
const (
	Column FlexDirection = iota
	ColumnReverse
	Row
	RowReverse
)

func (FlexDirection) String

func (a FlexDirection) String() string

type FlexJustify

type FlexJustify int
const (
	JustifyStart FlexJustify = iota
	JustifyEnd
	JustifyCenter
	JustifySpaceBetween
	JustifySpaceAround
	JustifySpaceEvenly
)

func (FlexJustify) String

func (a FlexJustify) String() string

type FlexWrap

type FlexWrap int
const (
	NoWrap FlexWrap = iota
	Wrap
	WrapReverse
)

func (FlexWrap) String

func (t FlexWrap) String() string

type Gap

type Gap struct {
	Row    Value
	Column Value
	All    Value
}

Gap represents the gap values for rows and columns.

type Layout

type Layout struct {
	// contains filtered or unexported fields
}

func (*Layout) AbsoluteBottom

func (l *Layout) AbsoluteBottom() float32

func (*Layout) AbsoluteLeft

func (l *Layout) AbsoluteLeft() float32

func (*Layout) AbsoluteRight

func (l *Layout) AbsoluteRight() float32

func (*Layout) AbsoluteTop

func (l *Layout) AbsoluteTop() float32

func (*Layout) Border

func (l *Layout) Border() *LayoutEdges

func (*Layout) Bottom

func (l *Layout) Bottom() float32

func (*Layout) Direction

func (l *Layout) Direction() DirectionType

func (*Layout) HadOverflow

func (l *Layout) HadOverflow() bool

func (*Layout) Height

func (l *Layout) Height() float32

func (*Layout) Left

func (l *Layout) Left() float32

func (*Layout) Margin

func (l *Layout) Margin() *LayoutEdges

func (*Layout) Padding

func (l *Layout) Padding() *LayoutEdges

func (*Layout) RawHeight

func (l *Layout) RawHeight() float32

func (*Layout) RawWidth

func (l *Layout) RawWidth() float32

func (*Layout) Right

func (l *Layout) Right() float32

func (*Layout) Top

func (l *Layout) Top() float32

func (*Layout) Width

func (l *Layout) Width() float32

type LayoutEdges

type LayoutEdges struct {
	// contains filtered or unexported fields
}

func (*LayoutEdges) Bottom

func (e *LayoutEdges) Bottom() float32

func (*LayoutEdges) Left

func (e *LayoutEdges) Left() float32

func (*LayoutEdges) Right

func (e *LayoutEdges) Right() float32

func (*LayoutEdges) Top

func (e *LayoutEdges) Top() float32

type MeasureFunc

type MeasureFunc func(node *Node, width float32, widthMode MeasureMode, height float32, heightMode MeasureMode) Size

type MeasureMode

type MeasureMode int
const (
	MeasureModeUndefined MeasureMode = iota
	MeasureModeExactly
	MeasureModeAtMost
)

func (MeasureMode) String

func (m MeasureMode) String() string

type Node

type Node struct {
	// contains filtered or unexported fields
}

func NewNode

func NewNode(styles ...*Style) (*Node, error)

func (*Node) AppendChild

func (n *Node) AppendChild(child *Node)

func (*Node) Apply

func (n *Node) Apply(style *Style) error

Apply applies a Style to the node

func (*Node) Children

func (n *Node) Children() iter.Seq[*Node]

func (*Node) Clone

func (n *Node) Clone() *Node

func (*Node) CloneRecursive

func (n *Node) CloneRecursive() *Node

func (*Node) ComputeLayout

func (n *Node) ComputeLayout(container Container) error

func (*Node) Free

func (n *Node) Free()

func (*Node) FreeRecursive

func (n *Node) FreeRecursive()

func (*Node) GetAlignContent

func (n *Node) GetAlignContent() FlexAlign

func (*Node) GetAlignItems

func (n *Node) GetAlignItems() FlexAlign

func (*Node) GetAlignSelf

func (n *Node) GetAlignSelf() FlexAlign

func (*Node) GetAspectRatio

func (n *Node) GetAspectRatio() float32

func (*Node) GetBorder

func (n *Node) GetBorder() *StyleEdges

func (*Node) GetBottom

func (n *Node) GetBottom() Value

func (*Node) GetBoxSizing

func (n *Node) GetBoxSizing() BoxSizingType

func (*Node) GetChild

func (n *Node) GetChild(index int) *Node

func (*Node) GetChildCount

func (n *Node) GetChildCount() int

func (*Node) GetConfig

func (n *Node) GetConfig() *Config

func (*Node) GetDirection

func (n *Node) GetDirection() DirectionType

func (*Node) GetDisplay

func (n *Node) GetDisplay() DisplayType

func (*Node) GetFlexBasis

func (n *Node) GetFlexBasis() Value

func (*Node) GetFlexDirection

func (n *Node) GetFlexDirection() FlexDirection

func (*Node) GetFlexGrow

func (n *Node) GetFlexGrow() float32

func (*Node) GetFlexShrink

func (n *Node) GetFlexShrink() float32

func (*Node) GetFlexWrap

func (n *Node) GetFlexWrap() FlexWrap

func (*Node) GetGap

func (n *Node) GetGap() *StyleGap

func (*Node) GetHeight

func (n *Node) GetHeight() Value

func (*Node) GetJustifyContent

func (n *Node) GetJustifyContent() FlexJustify

func (*Node) GetLayout

func (n *Node) GetLayout() *Layout

func (*Node) GetLeft

func (n *Node) GetLeft() Value

func (*Node) GetMargin

func (n *Node) GetMargin() *StyleEdges

func (*Node) GetMaxHeight

func (n *Node) GetMaxHeight() Value

func (*Node) GetMaxWidth

func (n *Node) GetMaxWidth() Value

func (*Node) GetMinHeight

func (n *Node) GetMinHeight() Value

func (*Node) GetMinWidth

func (n *Node) GetMinWidth() Value

func (*Node) GetNodeType

func (n *Node) GetNodeType() NodeType

func (*Node) GetOverflow

func (n *Node) GetOverflow() OverflowType

func (*Node) GetPadding

func (n *Node) GetPadding() *StyleEdges

func (*Node) GetParent

func (n *Node) GetParent() *Node

func (*Node) GetPosition

func (n *Node) GetPosition() PositionType

func (*Node) GetRight

func (n *Node) GetRight() Value

func (*Node) GetTop

func (n *Node) GetTop() Value

func (*Node) GetWidth

func (n *Node) GetWidth() Value

func (*Node) HasMeasureFunc

func (n *Node) HasMeasureFunc() bool

func (*Node) HasNewLayout

func (n *Node) HasNewLayout() bool

func (*Node) InsertChild

func (n *Node) InsertChild(child *Node, index int)

func (*Node) IsDirty

func (n *Node) IsDirty() bool

func (*Node) MarkDirty

func (n *Node) MarkDirty()

MarkDirty marks the node as dirty. This will cause the next layout computation to recalculate this node and its children.

Note: this method should only be used for nodes with a custom measure function. Nodes without a measure function are marked dirty automatically when their style properties are changed.

func (*Node) RemoveAllChildren

func (n *Node) RemoveAllChildren()

func (*Node) RemoveChild

func (n *Node) RemoveChild(child *Node)

func (*Node) Reset

func (n *Node) Reset()

func (*Node) SetAlignContent

func (n *Node) SetAlignContent(align FlexAlign) error

func (*Node) SetAlignItems

func (n *Node) SetAlignItems(align FlexAlign) error

func (*Node) SetAlignSelf

func (n *Node) SetAlignSelf(align FlexAlign) error

func (*Node) SetAspectRatio

func (n *Node) SetAspectRatio(aspectRatio float32) error

func (*Node) SetBorder

func (n *Node) SetBorder(edges Edges) error

SetBorder sets the border widths for the node. Note: Borders can only be set in points.

func (*Node) SetBottom

func (n *Node) SetBottom(bottom Value) error

func (*Node) SetBoxSizing

func (n *Node) SetBoxSizing(boxSizing BoxSizingType) error

func (*Node) SetChildren

func (n *Node) SetChildren(children []*Node)

func (*Node) SetConfig

func (n *Node) SetConfig(config *Config)

func (*Node) SetDirection

func (n *Node) SetDirection(direction DirectionType) error

func (*Node) SetDirty

func (n *Node) SetDirty(dirty bool)

SetDirty directly sets the dirty flag on a node without propagating to parent.

func (*Node) SetDisplay

func (n *Node) SetDisplay(display DisplayType) error

func (*Node) SetFlexBasis

func (n *Node) SetFlexBasis(flexBasis Value) error

func (*Node) SetFlexDirection

func (n *Node) SetFlexDirection(direction FlexDirection) error

func (*Node) SetFlexGrow

func (n *Node) SetFlexGrow(flexGrow float32) error

func (*Node) SetFlexShrink

func (n *Node) SetFlexShrink(flexShrink float32) error

func (*Node) SetFlexWrap

func (n *Node) SetFlexWrap(wrap FlexWrap) error

func (*Node) SetGap

func (n *Node) SetGap(gap Gap) error

SetGap sets the gap sizes for the node. Note: Gaps can be set in points or percent.

func (*Node) SetHasNewLayout

func (n *Node) SetHasNewLayout(hasNewLayout bool)

func (*Node) SetHeight

func (n *Node) SetHeight(height Value) error

func (*Node) SetJustifyContent

func (n *Node) SetJustifyContent(justify FlexJustify) error

func (*Node) SetLeft

func (n *Node) SetLeft(left Value) error

func (*Node) SetMargin

func (n *Node) SetMargin(edges Edges) error

SetMargin sets the margin widths for the node. Note: Margins can be set in points, percent, or auto.

func (*Node) SetMaxHeight

func (n *Node) SetMaxHeight(maxHeight Value) error

func (*Node) SetMaxWidth

func (n *Node) SetMaxWidth(maxWidth Value) error

func (*Node) SetMeasureFunc

func (n *Node) SetMeasureFunc(fn MeasureFunc)

func (*Node) SetMinHeight

func (n *Node) SetMinHeight(minHeight Value) error

func (*Node) SetMinWidth

func (n *Node) SetMinWidth(minWidth Value) error

func (*Node) SetNodeType

func (n *Node) SetNodeType(nodeType NodeType) error

func (*Node) SetOverflow

func (n *Node) SetOverflow(overflow OverflowType) error

func (*Node) SetPadding

func (n *Node) SetPadding(edges Edges) error

SetPadding sets the padding for the node. Note: Padding can only be set in points or percent.

func (*Node) SetParent

func (n *Node) SetParent(parent *Node)

func (*Node) SetPosition

func (n *Node) SetPosition(position PositionType) error

func (*Node) SetRight

func (n *Node) SetRight(right Value) error

func (*Node) SetTop

func (n *Node) SetTop(top Value) error

func (*Node) SetWidth

func (n *Node) SetWidth(width Value) error

func (*Node) Snapshot

func (n *Node) Snapshot() *Node

Snapshot creates a deep clone of the node tree while preserving the dirty state. Unlike CloneRecursive which marks cloned nodes as dirty, Snapshot maintains the original dirty status, allowing cached layout computations to be reused.

func (*Node) UnsetMeasureFunc

func (n *Node) UnsetMeasureFunc()

type NodeType

type NodeType int
const (
	NodeTypeDefault NodeType = iota
	NodeTypeText
)

func (NodeType) String

func (t NodeType) String() string

type OverflowType

type OverflowType int
const (
	Visible OverflowType = iota
	Hidden
	Scroll
)

func (OverflowType) String

func (t OverflowType) String() string

type PositionType

type PositionType int
const (
	Static PositionType = iota
	Relative
	Absolute
)

func (PositionType) String

func (t PositionType) String() string

type Size

type Size struct {
	Width  float32
	Height float32
}

type Style

type Style struct {
	// Display & Layout
	Display        DisplayType
	FlexDirection  FlexDirection
	JustifyContent FlexJustify
	AlignItems     FlexAlign
	AlignSelf      FlexAlign
	AlignContent   FlexAlign
	FlexWrap       FlexWrap
	Direction      DirectionType

	// Dimensions
	Width, Height       Value
	MinWidth, MinHeight Value
	MaxWidth, MaxHeight Value
	AspectRatio         float32

	// Spacing
	Padding Edges
	Margin  Edges
	Border  Edges
	Gap     Gap

	// Flex item properties
	FlexGrow   float32
	FlexShrink float32
	FlexBasis  Value

	// Positioning
	Position                 PositionType
	Top, Right, Bottom, Left Value

	// Overflow
	Overflow OverflowType

	// Box Sizing
	BoxSizing BoxSizingType
}

type StyleEdges

type StyleEdges struct {
	// contains filtered or unexported fields
}

func (*StyleEdges) GetBottom

func (e *StyleEdges) GetBottom() Value

func (*StyleEdges) GetEnd

func (e *StyleEdges) GetEnd() Value

func (*StyleEdges) GetLeft

func (e *StyleEdges) GetLeft() Value

func (*StyleEdges) GetRight

func (e *StyleEdges) GetRight() Value

func (*StyleEdges) GetStart

func (e *StyleEdges) GetStart() Value

func (*StyleEdges) GetTop

func (e *StyleEdges) GetTop() Value

type StyleGap

type StyleGap struct {
	// contains filtered or unexported fields
}

func (*StyleGap) GetAll

func (g *StyleGap) GetAll() Value

func (*StyleGap) GetColumn

func (g *StyleGap) GetColumn() Value

func (*StyleGap) GetRow

func (g *StyleGap) GetRow() Value

type Unit

type Unit int
const (
	UnitUndefined Unit = iota
	UnitPoint
	UnitPercent
	UnitMaxContent
	UnitFitContent
	UnitAuto
	UnitStretch
)

func (Unit) String

func (u Unit) String() string

type Value

type Value struct {
	// contains filtered or unexported fields
}

func Auto

func Auto() Value

func FitContent

func FitContent() Value

func MaxContent

func MaxContent() Value

func Percent

func Percent(percents float32) Value

func Point

func Point(points float32) Value

func Stretch

func Stretch() Value

func Undefined

func Undefined() Value

func (Value) String

func (v Value) String() string

func (Value) Unit

func (v Value) Unit() Unit

func (Value) Value

func (v Value) Value() float32

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL