Tabs

<k.Tabs> holds a list of tabs, each a group of blocks; the reader sees one tab at a time. The first tab is open. Use it to split the same results by grain or by view: a table by month in one tab, by week in another. With param, the open tab is kept in the URL (?grain=month) and acts as an input that When and the SQL can read; declare it in page.filterParams with input: "tabs".

Example

monthly.sql and weekly.sql:

-- Sales per month
select '2026-01' as month, 410 as sales
union all select '2026-02', 455
-- Sales per week
select '2026-W05' as week, 98 as sales
union all select '2026-W06', 104

In report.tsx:

import monthly from "./monthly.sql?raw"
import weekly from "./weekly.sql?raw"

// in defineReport({ … })
page: {
  filterParams: [
    {
      param: "grain",
      label: "Grain",
      input: "tabs",
      options: () => [
        { value: "month", label: "By month" },
        { value: "week", label: "By week" },
      ],
    },
  ],
},
queries: {
  monthly: query<{ month: string; sales: number }>(monthly),
  weekly: query<{ week: string; sales: number }>(weekly),
},
blocks: (k) => [
  <k.Tabs
    key="sales"
    title="Sales"
    param="grain"
    tabs={[
      {
        label: "By month",
        value: "month",
        blocks: (
          <k.Table
            series="monthly"
            columns={[{ key: "month", label: "Month", format: "month" }, { key: "sales", label: "Sales" }]}
          />
        ),
      },
      {
        label: "By week",
        value: "week",
        blocks: (
          <k.Table
            series="weekly"
            columns={[{ key: "week", label: "Week", format: "text" }, { key: "sales", label: "Sales" }]}
          />
        ),
      },
    ]}
  />,
],

Props

NameTypeRequiredDefaultMeaning
keytextyesA name unique on the page
tabslist of tabsyesThe tabs, in order; the first is open
titletext, or a function of the datanoA heading over the tabs
descriptiontext, or a function of the datanoA muted line under the heading
info{ what, rules, sql }noThe "(i)"
parama lowercase namenoKeeps the open tab in the URL as ?<param>=<value>; not from, to or page

A tab

KeyTypeRequiredMeaning
labeltextyesThe tab's name
valueletters, digits, -, _with paramThe tab's value in the URL
blocksblocksyesThe blocks in the tab

A table inside a tab may leave out its title.

Checks

A tab without label or blocks, or a block inside it naming a series or column the queries do not return, fails the typecheck.