---
title: Blocks
description: Compose the content and the layout of a screen from blocks.
---

A block is a part of a screen. A view returns blocks, and the client renders each
block with its own component. You compose a screen by putting blocks inside other
blocks, in the same way that you compose a React tree from components.

This introduction explains the two categories of blocks, how to compose a layout
from them, and how to select a block. The page for each block has the full options.

## Two categories of blocks

A data block displays the data that your view supplies. `table`, `list`, `datalist`,
and `timeline` are data blocks. You give a data block your records and the fields
that it must show. The SDK converts each value to its protocol form, and the client
renders it.

```ts
table(rows).setFields(orders.pick('reference', 'customer', 'total'))
```

A container block gives structure to a page. `section`, `panel`, `tabs`, and `group`
are container blocks. A container block has a content slot that holds other blocks,
and some container blocks have a second slot. A `section` has an `aside` slot for
content that goes next to the main content.

```ts
section('Orders').setContent([panel([table(rows).setFields(columns)])])
```

Forms and widgets are blocks too, and they go in the same slots. They have their own
introductions: [Forms](/reference/forms) and [Widgets](/reference/widgets).

## Compose a layout

Backlit has no grid, no columns, and no spacing options. You declare the structure
of a page, and the client decides the layout from that structure and from the width
that is available. A `section` with an `aside` renders as two columns on a wide
screen and as one column on a narrow screen, and your view does not change.

The example below builds a detail page. The `section` gives the page a heading. Its
content slot has a panel, and its aside slot has a second panel.

<BacklitExample path="section/aside" view="detail" />

The content of a slot is an array of builders, so you compose it with normal
TypeScript. Use a condition or an array spread to include a block for some requests
only. Create the blocks inside the view callback, so each request gets new builders.

```ts
section('Order').setContent([
  ...(order.isOverdue ? [callout('The payment is overdue.').setTone('warning')] : []),
  panel([datalist(order).setFields(orders.pick('reference', 'customer', 'total'))]),
])
```

## Select a block

| Your need                                                           | Block                                   |
| ------------------------------------------------------------------- | --------------------------------------- |
| Show many records in columns, to scan and compare them              | [Table](/reference/blocks/table)         |
| Show many records as rows with a title, a description, and metadata | [List](/reference/blocks/list)           |
| Show events in time order                                           | [Timeline](/reference/blocks/timeline)   |
| Show one record as labeled values, for a detail page                | [Datalist](/reference/blocks/datalist)   |
| Show a short message next to the content that it describes          | [Callout](/reference/blocks/callout)     |
| Divide a page into regions with a heading, filters, and actions     | [Section](/reference/blocks/section)     |
| Put content inside one surface with a boundary                      | [Panel](/reference/blocks/panel)         |
| Switch between sets of content on one page                          | [Tabs](/reference/blocks/tabs)           |
| Keep related blocks together without a heading or a boundary        | [Group](/reference/blocks/group)         |
| Show one select filter as a row of buttons above a list             | [Segments](/reference/blocks/segments)   |

Two pairs of blocks are easy to confuse.

Use a `section` for a region of the page and a `panel` for one item with a boundary.
A list page is usually a `section` that has the filters and the actions, with a
`panel` inside it that has the table.

Use `tabs` to switch between different content, and `segments` to switch one list
between the values of one field, such as the status of a subscriber.

## Block metadata

Most blocks accept the same optional metadata: a title, a description, a badge, and
a footnote. You set them with methods on the builder, such as `setTitle`. The client
controls their position and their style, so a title looks the same on each block of
your app.

## Blocks and zones

A block gets its data from the view callback, so a change to the data needs a new
request for the view. When a part of a page must load again without the other parts,
put it in a zone. A zone goes in the same slots as a block, and it has its own
callback. See [Zones](/reference/views/zone).

When no built-in block fits, an extension can add a block. See
[Extensions](/extensions).
