teatile

package module
v1.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2025 License: MIT Imports: 1 Imported by: 0

README

TeaTile

Latest Release GoDoc Build

Tiling layout manager for Bubble Tea.

If you're using multiple tea.Models you might've run into the annoying situation where you have to pass around tea.WindowSizeMsg literally everywhere and keep track of what's taking how much space. Forgot to set width somewhere? Sorry, you're TUI will now break in half, good luck finding the problem!

With teatile you can assign a Tile to hold a rectangular space's width and height and recalculate it if necessary.

Why TeaTile?

TeaTile aims to be minimal and simplistic it tries to fill a rectangular space, that's it.

Usage

go get -u github.com/bevicted/teatile@latest

GoDoc

Basic

// given that our main Tile has a height of 10 lines
tile := teatile.New().WithSize(0, 10)

headerTile := tile.NewSubtile().WithSize(0, 3)
contentTile := tile.NewSubtile()
footerTile := tile.NewSubtile()

// we have 3 subtiles joined vertically
teatile.JoinVertical(
	// takes 3 lines of space
	headerTile,

	// with no set height, these Tiles will fill the remaining space

	// fills (10 - 3) / 2 = 3 lines
	contentTile,
	// fills the remaining 10 - 3 - 3 = 4 lines
	footerTile,
)

// when it's time to render our in our View() function:
w, h := m.tiles.main.GetSize()
headerView := lipgloss.NewStyle().
	Width(w).
	MaxWidth(w).
	Height(h).
	MaxHeight(h).
	Render("header")
// might get annoying to do this for every Tile, so let's use helpers
contentView := teatile.SetStyleSize(lipgloss.NewStyle(), contentTile).
	Render("content")
footerView := teatile.SetStyleSize(lipgloss.NewStyle(), footerTile).
	Render("footer")
view := lipgloss.JoinVertical(
	headerView,
	contentView,
	footerView,
)

// use sizes for other calculations
// e.g.: move page down
_, h := subtile.GetSize()
CursorDown(h)
Example

In your main tea.Model, instead of holding the width and height as a field, hold your main Tile.

// I prefer saving multiple Tiles into a single struct, but you do you
type tiles struct {
	main   *teatile.Tile
	header *teatile.Tile
}

type Model struct {
	tiles tiles
...

func New() Model {
	// create your main Tile
	tile := teatile.New()

    // create a subtiles, set sizes where necessary
	// here we skip setting width with 0 and set height to 1 line
	headerTile := tile.NewSubtile().WithSize(0, 1)
	contentTile := tile.NewSubtile()
	footerTile := tile.NewSubtile().WithSize(0, 1)

	// tell the tiles that they are vertically next to eachother
	teatile.JoinVertical(headerTile, contentTile, footerTile)

	m := &Model{
		// save tiles we must reference later
		tiles: tiles{
			main:   tile,
			header: headerTile,
		},
		// pass down the tiles submodels need to fill
		contentModel: contentModel.New(contentTile),
		footerModel:  footer.New(footerTile),
...

func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
	switch msg := msg.(type) {
	case tea.WindowSizeMsg:
		// on window size change, set the size of the main Tile and tell it
		// to recalculate the occupied area. This will propagate to all
		// linked Tiles, be it horizontally/vertically joined or subtiles.
		m.tiles.main.WithSize(msg.Width, msg.Height).Recalculate()
...

// use OnRecalculate to connect custom components
func (m *Model) Init() tea.Cmd {
	m.tiles.main.OnRecalculate(func() {
		w, h := m.tiles.main.GetSize()
		m.textArea.SetWidth(w)
		m.textArea.SetHeight(h)
	})
	return nil
}

func (m *Model) View() string {
	// when rendering, get the size, you can rapidly call this as the size
	// only needs to be calculated once
	w, h := m.tiles.main.GetSize()
	return lipgloss.NewStyle().
		Width(w).
		MaxWidth(w).
		Height(h).
		MaxHeight(h).
		Render("my main tile")
}

Documentation

Overview

Package teatile provides a simple layout management system for Bubble Tea applications.

It allows allocating and managing rectangular spaces (tiles) that can be nested and sized automatically, which is useful for building complex TUI layouts with Bubble Tea.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func JoinHorizontal

func JoinHorizontal(tiles ...*Tile)

JoinHorizontal joins the specified tiles horizontally.

func JoinVertical

func JoinVertical(tiles ...*Tile)

JoinVertical joins the specified tiles vertically.

func SetStyleHeight added in v1.3.0

func SetStyleHeight[S style[S]](s S, t *Tile) S

func SetStyleSize added in v1.3.0

func SetStyleSize[S style[S]](s S, t *Tile) S

func SetStyleWidth added in v1.3.0

func SetStyleWidth[S style[S]](s S, t *Tile) S

Types

type Tile

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

Tile represents a rectangular space in the layout. Subtiles will strive to fill their parent's space.

func New

func New() *Tile

New creates a new Tile and returns a pointer to it.

func (*Tile) GetSize

func (t *Tile) GetSize() (int, int)

GetSize returns the width and height of the Tile, calculating them if necessary.

func (*Tile) NewSubtile

func (t *Tile) NewSubtile() *Tile

NewSubtile creates a new subtile.

func (*Tile) OnRecalculate

func (t *Tile) OnRecalculate(cb func())

OnRecalculate adds the specified callback function to the list of funcs that will be called on recalculation of the tile's size.

func (*Tile) Recalculate

func (t *Tile) Recalculate()

Recalculate forces a recalculation of the tile's size and calls OnRecalculate callbacks. This effect is recursively propagated to all subtiles as well.

func (*Tile) WithSize

func (t *Tile) WithSize(w, h int) *Tile

WithSize sets the width and height for the Tile.

Jump to

Keyboard shortcuts

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