Skip to content
Backlit
Esc
navigateopen⌘Jpreview
On this page

Panel

Group related content inside one bounded surface.

A panel block makes a set of content read as one item. Use it for an order summary, a group of settings, or another part of a page that needs a visual boundary.

The panel holds content in the order that you provide it. Its title, description, badge, and footnote are optional. The renderer controls their position and visual style.

API

panel(content: Producer[]): PanelBuilder
Method Input Result
setTitle string, { icon?: string } Adds a title and an optional icon.
setDescription string, { icon?: string } Adds supporting text and an optional icon.
setBadge string, { tone?: Tone, icon?: string } Adds a short status label.
setFootnote string, { icon?: string } Adds text after the panel content.
setFilters StateBinding<FilterBar> Places a filter bar in the panel header.

Properties that you do not set are not included in the protocol output.

Basic panel

Pass the panel content as an array. The panel can hold any block or zone.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')])
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Title

Add a title when the panel content needs a name.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setTitle(
    'Order 1042'
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "title": "Order 1042",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Title icon

Pass an icon token with the title. The renderer resolves the token through its icon registry.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setTitle(
    'Order 1042',
    {
      icon: 'orders',
    }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "title": "Order 1042",
          "titleIcon": "orders",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Description

Add a description for supporting information about the complete panel.

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

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

orders.view('detail', () =>
  panel([
    callout('This order is ready to ship.'),
  ]).setDescription(
    'Placed by A. Customer on 12 August 2026.'
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "description": "Placed by A. Customer on 12 August 2026.",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Description icon

Pass an icon token when the description needs a visual marker.

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

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

orders.view('detail', () =>
  panel([
    callout('This order is ready to ship.'),
  ]).setDescription(
    'Placed by A. Customer on 12 August 2026.',
    { icon: 'activity' }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "description": "Placed by A. Customer on 12 August 2026.",
          "descriptionIcon": "activity",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Badge

Add a badge for a short qualifier or status. If you do not set a tone, the renderer uses its default badge style.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setBadge(
    'Priority'
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "badge": "Priority",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Badge tones

A badge tone gives semantic meaning to its status. The renderer controls the color for each tone.

Neutral

Use neutral for a status that does not need emphasis.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setBadge(
    'Standard',
    {
      tone: 'neutral',
    }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "badge": "Standard",
          "badgeTone": "neutral",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Info

Use info for a current state that does not report success, risk, or failure.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setBadge(
    'In transit',
    {
      tone: 'info',
    }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "badge": "In transit",
          "badgeTone": "info",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Success

Use success for a completed or intended state.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setBadge(
    'Paid',
    {
      tone: 'success',
    }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "badge": "Paid",
          "badgeTone": "success",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Warning

Use warning for a state that needs attention.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setBadge(
    'Delayed',
    {
      tone: 'warning',
    }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "badge": "Delayed",
          "badgeTone": "warning",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Danger

Use danger for a failed or destructive state.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setBadge(
    'Payment failed',
    {
      tone: 'danger',
    }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "badge": "Payment failed",
          "badgeTone": "danger",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Badge icon

A badge can include an icon token and a tone.

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

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

orders.view('detail', () =>
  panel([callout('This order is ready to ship.')]).setBadge(
    'Shipped',
    {
      icon: 'shipping',
      tone: 'success',
    }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "badge": "Shipped",
          "badgeTone": "success",
          "badgeIcon": "shipping",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Footnote

Add a footnote for information that applies after the complete panel content.

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

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

orders.view('detail', () =>
  panel([
    callout('This order is ready to ship.'),
  ]).setFootnote('Carrier updates can take up to one hour.')
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "footnote": "Carrier updates can take up to one hour.",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Footnote icon

Pass an icon token when the footnote needs a visual marker.

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

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

orders.view('detail', () =>
  panel([
    callout('This order is ready to ship.'),
  ]).setFootnote(
    'Carrier updates can take up to one hour.',
    { icon: 'activity' }
  )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "footnote": "Carrier updates can take up to one hour.",
          "footnoteIcon": "activity",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order is ready to ship."
              }
            ]
          }
        }
      ]
    }
  }
}

Filters

Pass the filter binding from the current view or zone. The protocol output includes the current resource and view address with the filter declarations.

import {
  callout,
  defineFilters,
  defineResource,
  filters,
  panel,
} from '@backlit/sdk'

const orders = defineResource('orders', [])
const orderFilters = defineFilters([
  filters.text('search').setLabel('Search orders'),
])

orders.view(
  'detail',
  { filters: orderFilters },
  (_ctx, view) =>
    panel([
      callout('Three orders match the current search.'),
    ]).setFilters(view.state.filters)
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "Three orders match the current search."
              }
            ],
            "filters": {
              "kind": "filters",
              "resource": "orders",
              "view": "detail",
              "keyword": "f",
              "definesResult": true,
              "dependsOnResult": false,
              "filters": [
                {
                  "kind": "text",
                  "name": "search",
                  "label": "Search orders"
                }
              ]
            }
          }
        }
      ]
    }
  }
}

All options

You can set all panel metadata, filters, and content on the same panel.

import {
  callout,
  defineFilters,
  defineResource,
  filters,
  panel,
} from '@backlit/sdk'

const orders = defineResource('orders', [])
const orderFilters = defineFilters([
  filters.text('search').setLabel('Search activity'),
])

orders.view(
  'detail',
  { filters: orderFilters },
  (_ctx, view) =>
    panel([
      callout(
        'This order left the warehouse at 09:30.'
      ).setTone('success'),
    ])
      .setTitle('Order 1042', { icon: 'orders' })
      .setDescription(
        'Placed by A. Customer on 12 August 2026.',
        {
          icon: 'activity',
        }
      )
      .setBadge('Shipped', {
        icon: 'shipping',
        tone: 'success',
      })
      .setFilters(view.state.filters)
      .setFootnote(
        'Carrier updates can take up to one hour.',
        {
          icon: 'activity',
        }
      )
)

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "detail",
    "slots": {
      "content": [
        {
          "kind": "panel",
          "title": "Order 1042",
          "titleIcon": "orders",
          "description": "Placed by A. Customer on 12 August 2026.",
          "descriptionIcon": "activity",
          "badge": "Shipped",
          "badgeTone": "success",
          "badgeIcon": "shipping",
          "footnote": "Carrier updates can take up to one hour.",
          "footnoteIcon": "activity",
          "slots": {
            "content": [
              {
                "kind": "callout",
                "text": "This order left the warehouse at 09:30.",
                "tone": "success"
              }
            ],
            "filters": {
              "kind": "filters",
              "resource": "orders",
              "view": "detail",
              "keyword": "f",
              "definesResult": true,
              "dependsOnResult": false,
              "filters": [
                {
                  "kind": "text",
                  "name": "search",
                  "label": "Search activity"
                }
              ]
            }
          }
        }
      ]
    }
  }
}

Actions and conditions

setActions([visitTo(...), submitTo(...)]) replaces the header controls. Each control requires text or an icon. These blocks have no row, so supply fixed argument values. See Targets. revealWhen(condition) controls the block inside a form. It has no enable condition. See Form conditions.

Was this page helpful?