Skip to content
Backlit
Esc
navigateopen⌘Jpreview
On this page

Widgets and charts

Show figures and charts that summarize data, for dashboards and overview pages.

A widget is a small block that summarizes data. It shows a figure, a chart, or both, with the text that explains them. Widgets are the parts of a dashboard, and they also work above a table to give the totals of a list.

This introduction explains the parts of a widget, how charts fit into it, and how to build a dashboard. The pages of this category have the full options.

The parts of a widget

A widget has two optional data parts, and it needs one of them at least.

The stat is one figure, such as the number of subscribers. You supply the value and a number field. The field gives the format, so the client can show 12480 as 12,480 or as 12.5K with the locale of the user. When you also supply the value of the prior period, the client calculates the change and shows it next to the figure.

The chart is a small visualization, such as the trend of the last 30 days. You create it with the charts factory and give it to the widget with setChart.

Around these parts, a widget has context: a title, a description, a footnote, and a caption. The example below shows two widgets with a stat and a change from the prior period.

import {
  defineResource,
  fields,
  widget,
} from '@backlit/sdk'

const orders = defineResource('orders', [])
const count = fields.number('count', { format: 'integer' })
const rate = fields.number('rate', {
  format: 'percent',
  decimals: 1,
})

orders.view('overview', () => [
  widget().setTitle('Subscribers').setStat({
    value: 12_480,
    field: count,
    prior: 11_900,
    delta: 'percent',
    tone: 'success',
  }),
  widget().setTitle('Open rate').setStat({
    value: 0.42,
    field: rate,
    prior: 0.4,
    delta: 'absolute',
    tone: 'success',
  }),
])

export default orders
{
  "kind": "success",
  "status": 200,
  "node": {
    "kind": "view",
    "resource": "orders",
    "name": "overview",
    "slots": {
      "content": [
        {
          "kind": "widget",
          "title": "Subscribers",
          "stat": {
            "value": 12480,
            "field": {
              "kind": "number",
              "name": "count",
              "format": "integer",
              "label": ""
            },
            "prior": 11900,
            "delta": "percent",
            "tone": "success"
          }
        },
        {
          "kind": "widget",
          "title": "Open rate",
          "stat": {
            "value": 0.42,
            "field": {
              "kind": "number",
              "name": "rate",
              "format": "percent",
              "decimals": 1,
              "label": ""
            },
            "prior": 0.4,
            "delta": "absolute",
            "tone": "success"
          }
        }
      ]
    }
  }
}

The sign of a change has no meaning by itself. An increase in subscribers is good, and an increase in refunds is not. Thus you set the tone of the stat, and the client selects the color for that tone.

Your query calculates the figures

A widget does not aggregate your data. Your view runs the count, the sum, or the average, and gives the result to the widget. Fields describe the values here in the same way that they describe the columns of a table. This is the usual case of a field that has no database column.

const revenue = fields.number('revenue', { format: 'currency', currency: 'USD' })

orders.view('overview', async () => {
  const { current, prior } = await db.orders.revenueByMonth()

  return widget()
    .setTitle('Revenue')
    .setStat({ value: current, prior, field: revenue, delta: 'percent', tone: 'success' })
})

Charts

A chart is not a block. It always goes inside a widget, and the widget gives it a title and its context. You give a chart your rows and the fields that read them. The number fields give the format of the axis values and the tooltips.

Your need Chart
Rank rows by one value, such as the top ten pages Bar list
Show one or more series against time or a category Line
Show a small trend next to a figure, without axes Spark area
Show the parts of one total, such as plan shares Category bar

Chart colors are tokens from 1 through 5 and not color values, so a chart follows the theme of your app in light mode and in dark mode.

Build a dashboard

A widget group tells the client that its widgets belong together. The group has no columns and no layout options. The client arranges the widgets from the width that is available. To give a group a heading, put it in a section.

return section('This month').setContent([
  widgets.group([subscribersWidget, openRateWidget, revenueWidget]),
  panel([table(recentOrders).setFields(columns)]).setTitle('Recent orders'),
])

Each figure of a dashboard usually needs its own query, and some queries are slow. A widget group accepts zones that produce a widget. Put a slow widget in a zone, so that a refresh of that widget does not run the queries of the other widgets.

Filters work on a dashboard in the same way that they work on a list. A date range filter lets the user select the time range, and a period filter lets the user select the grouping unit of a chart, such as day or month.

Pages of this category

Page Content
Widget The stat, the change from a prior period, tone, and context
Group Sets of widgets, and zones inside a group
Charts The four chart types and their options

Was this page helpful?