bloom

Grids and wrapping

Lay children out in equal-width columns with Grid, or flow them onto as many lines as they need with Wrap.

Rows and columns place children on one line. For a dashboard of cards, or a set of tags that should wrap like words in a paragraph, use Grid or Wrap.

Lay out cards in a grid

bloom.Grid(cols, children...) fills cols equal-width columns, row by row:

bloom.Grid(3, cards...).Gap(1, 0)
┌────────┐ ┌───────┐ ┌───────┐
│1       │ │2      │ │3      │
└────────┘ └───────┘ └───────┘
┌────────┐
│4       │
└────────┘
  • Gap(x, y) sets the space between columns and between rows.
  • A short last row keeps the same column widths, so cards line up.
  • Each row is as tall as its tallest cell. Rows share any extra height equally, and give up height in proportion to their own size when there isn't enough.
  • A cols below one means a single column.

Change the column count with the width

Combine a grid with a Layouter to pick the number of columns from the space available:

type cards struct {
	items []bloom.Child
}

func (c cards) View() string {
	return bloom.Render(c.Layout(bloom.Context{}), 0, 0)
}

func (c cards) Layout(ctx bloom.Context) bloom.Child {
	cols := max(ctx.Width/30, 1) // a column for every 30 cells
	return bloom.Grid(cols, c.items...).Gap(2, 1)
}

Size content inside a cell

A cell's content stretches to fill the cell. To size it differently, wrap it in a slot: a slot child in a grid sizes its content horizontally within its cell.

bloom.Grid(2,
	bloom.Fixed(12, badge), // 12 columns wide, inside a wider cell
	description,
)

Wrap children onto new lines

bloom.Wrap(children...) places children left to right at their natural sizes, starting a new line when the next one doesn't fit, like words in a paragraph. It suits tags, chips, and buttons:

chip := lipgloss.NewStyle().
	Foreground(lipgloss.Color("#191724")).
	Background(lipgloss.Color("#c4a7e7")).
	Padding(0, 1)

tags := make([]bloom.Child, len(article.Tags))
for i, tag := range article.Tags {
	tags[i] = bloom.Text("#" + tag).Style(chip)
}
bloom.Wrap(tags...).Gap(1, 1)
┌─────┐ ┌────┐ ┌─────┐
│alpha│ │beta│ │gamma│
└─────┘ └────┘ └─────┘
┌─────┐
│delta│
└─────┘
  • Gap(x, y) sets the space between children and between lines.
  • Each line is as tall as its tallest child.
  • A child wider than the whole container gets a line of its own and is clipped.
  • Slot rules don't apply inside a wrap: every child keeps its natural size.

Placed in an Auto slot, or with no slot, a wrap is as tall as all its lines, so the content below it moves down as tags wrap.

Last updated on

On this page