Skip to content
Backlit
Esc
navigateopen⌘Jpreview
On this page

Tabs

Switch between bands of content that a reader takes one at a time.

A tabs block holds named tabs, each with any block or zone. The reader opens one tab at a time. Use it for a record page with more than one band of content: an issue’s overview, its links, and its recipients.

Tabs switch between different content. To switch one list between values of one field, use the segments block instead.

The active tab is local to the renderer. It does not enter the URL, and a tab change fetches nothing: every tab’s content arrives with the view. A zone inside a tab refreshes on its own state, and a zone in a closed tab does not fetch until the tab opens.

API

tabs(items: TabBuilder[]): TabsBuilder
tab(name: string, title: string): TabBuilder
Method on tabs Input Result
setInitial string Opens the named tab first.
setWidth "full" | "condensed" Stretches the tabs across the list, or hugs them.
setDensity "compact" Draws smaller tabs.
Method on tab Input Result
setIcon string Adds an icon beside the title.
setCount number, { tone?: Tone; variant?: "badge" } Adds a count, as muted text or as a badge.
setContent Producer[] Sets what the tab holds. Replaces the content.

Properties that you do not set are not included in the protocol output. A block with no tab, two tabs with one name, or an initial tab the block does not hold fails at resolve.

Basic tabs

Pass the tabs in their display order. The first one opens.

import {
  callout,
  defineResource,
  tab,
  tabs,
} from '@backlit/sdk'

const orders = defineResource('orders', [])

orders.view('detail', () =>
  tabs([
    tab('summary', 'Summary').setContent([
      callout('The totals.'),
    ]),
    tab('items', 'Items').setContent([
      callout('The lines.'),
    ]),
  ])
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "tabs",
          "slots": {
            "tabs": [
              {
                "name": "summary",
                "title": "Summary",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The totals."
                    }
                  ]
                }
              },
              {
                "name": "items",
                "title": "Items",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The lines."
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Initial tab

Name the tab that opens first.

import {
  callout,
  defineResource,
  tab,
  tabs,
} from '@backlit/sdk'

const orders = defineResource('orders', [])

orders.view('detail', () =>
  tabs([
    tab('summary', 'Summary').setContent([
      callout('The totals.'),
    ]),
    tab('items', 'Items').setContent([
      callout('The lines.'),
    ]),
  ]).setInitial('items')
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "tabs",
          "initial": "items",
          "slots": {
            "tabs": [
              {
                "name": "summary",
                "title": "Summary",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The totals."
                    }
                  ]
                }
              },
              {
                "name": "items",
                "title": "Items",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The lines."
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Icon and count

A tab can carry an icon and a count. The renderer formats the count in the client’s locale. Without a variant the count draws as muted text; badge draws it as a pill in its tone.

import {
  callout,
  defineResource,
  tab,
  tabs,
} from '@backlit/sdk'

const orders = defineResource('orders', [])

orders.view('detail', () =>
  tabs([
    tab('summary', 'Summary')
      .setIcon('receipt')
      .setContent([callout('The totals.')]),
    tab('items', 'Items')
      .setCount(4)
      .setContent([callout('The lines.')]),
    tab('returns', 'Returns')
      .setCount(1, { tone: 'danger', variant: 'badge' })
      .setContent([
        callout('One line came back.').setTone('danger'),
      ]),
  ])
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "tabs",
          "slots": {
            "tabs": [
              {
                "name": "summary",
                "title": "Summary",
                "icon": "receipt",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The totals."
                    }
                  ]
                }
              },
              {
                "name": "items",
                "title": "Items",
                "count": 4,
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The lines."
                    }
                  ]
                }
              },
              {
                "name": "returns",
                "title": "Returns",
                "count": 1,
                "countTone": "danger",
                "countVariant": "badge",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "One line came back.",
                      "tone": "danger"
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Width

full stretches the tabs across the list. condensed hugs their content, which is the default.

import {
  callout,
  defineResource,
  tab,
  tabs,
} from '@backlit/sdk'

const orders = defineResource('orders', [])

orders.view('detail', () =>
  tabs([
    tab('summary', 'Summary').setContent([
      callout('The totals.'),
    ]),
    tab('items', 'Items').setContent([
      callout('The lines.'),
    ]),
  ]).setWidth('full')
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "tabs",
          "width": "full",
          "slots": {
            "tabs": [
              {
                "name": "summary",
                "title": "Summary",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The totals."
                    }
                  ]
                }
              },
              {
                "name": "items",
                "title": "Items",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The lines."
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Density

compact draws smaller tabs, for a header that must not dominate the content.

import {
  callout,
  defineResource,
  tab,
  tabs,
} from '@backlit/sdk'

const orders = defineResource('orders', [])

orders.view('detail', () =>
  tabs([
    tab('summary', 'Summary').setContent([
      callout('The totals.'),
    ]),
    tab('items', 'Items').setContent([
      callout('The lines.'),
    ]),
  ]).setDensity('compact')
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "tabs",
          "density": "compact",
          "slots": {
            "tabs": [
              {
                "name": "summary",
                "title": "Summary",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The totals."
                    }
                  ]
                }
              },
              {
                "name": "items",
                "title": "Items",
                "slots": {
                  "content": [
                    {
                      "kind": "callout",
                      "text": "The lines."
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Was this page helpful?