bloom

Introduction

What bloom is, what it takes off your hands in a Bubble Tea program, and how its packages fit together.

bloom is a layout, compositing, and animation engine for Bubble Tea programs. You describe your view as a tree of nodes, built fresh from your model on every frame. bloom works out where everything goes, draws layers like dialogs and toasts on top, runs effects and animations, and tells you which node the mouse is over.

func (m *model) View() tea.View {
	return m.ui.View(m.width, m.height, bloom.Overlay(
		bloom.Column(
			bloom.Fill(bloom.Row(
				bloom.Fixed(24, m.sidebar).Collapsible(1),
				bloom.Fill(m.reader).Min(40),
			)),
			m.statusbar,
		),
		bloom.Layer(m.dialog).
			Modal().
			Backdrop(fx.Dim{Amount: 0.5}).
			Presence(m.dialogAnim, fx.Fade{}, fx.Slide{From: bloom.Bottom}),
	))
}

Pre-1.0

bloom's API may change in breaking ways until v1.0.0. Pin a version in your go.mod and check the release notes when you upgrade.

Why bloom exists

Bubble Tea gives you a model, an update loop, and a view that returns a string. Lip Gloss styles those strings and joins them side by side or top to bottom. That covers a lot, but some common needs take a surprising amount of code:

  • Sizing panes. A sidebar and a reader that share the width means measuring rendered strings, subtracting borders and padding, and redoing the math on every resize.
  • Layering. A dialog, dropdown, or toast has to be drawn over the rest of the screen. Strings can only be joined, not stacked, so you end up splicing lines by hand, and dimming what's underneath is harder still.
  • Mouse input. A click arrives as an X and Y. Working out which list item or button that was means keeping your own map of where you drew everything.
  • Focus. Tab order, a focused style, and a dialog that keeps focus inside it until it closes.
  • Animation. Tick messages, timers, and state machines, so a dialog can fade in or a toast can hide itself after two seconds.

bloom handles each of these in the view tree, so your model only holds application state and a few animation values.

The packages

PackageWhat it does
bloomLayout nodes (rows, columns, grids, boxes, text), overlays and layers, mouse routing, focus, and the Root that renders it all.
bloom/animAnimated numbers kept in your model: eased or spring Values, a Presence for showing and hiding, and Sequences of steps.
bloom/fxCell effects such as Fade, Slide, Iris, and Dim, used as transitions on nodes or as backdrops behind layers.
bloom/canvasThe cell surfaces effects draw on. You only need it to write your own effects.
bloom/flexThe space-sharing math behind rows and columns, plus the Justify options.

How it fits into Bubble Tea

bloom doesn't replace Bubble Tea's model or update loop. You keep writing Init, Update, and View; bloom lives inside them:

  • A *bloom.Root in your model renders the tree in View and returns the tea.View.
  • Any component with a View() string method, including Bubbles components and your own, can be placed in the tree as is.
  • Mouse handlers go on the nodes they're about, such as bloom.Text("save").On(on.Click(m.save)), and bloom runs the one under the pointer.
  • Animations are values in your model, advanced by messages like any other Bubble Tea state.

Where to go next

Last updated on

On this page