Tables & Feeds
Three islands for rows you read one at a time — a table when exact values matter, a feed for things that happened in order, and a search box to find one row in many.
Three islands for rows you read one at a time: a table when exact values matter, a feed for things that happened in order, and a search box to find one row in many. Each is a real island below: bind it to fields in your data and the runtime renders it. See the islands overview for the full registry.
table.grid
What it is. A paginated table of raw rows. When to use it: when the exact numbers
matter and a chart would hide them: positions, transactions, line items. It needs only a
dataset; with no columns it shows every column in the data.
{
"type": "table.grid",
"title": "Positions",
"dataset": "positions",
"columns": [
{ "field": "ticker", "label": "Ticker" },
{ "field": "shares", "label": "Shares", "format": "int" },
{ "field": "value_eur", "label": "Value", "format": "eur" }
]
}Key options.
columns: [{ field, label?, format? }]: pick and order the columns and set each column's value format. Omit it to show every column.details: [{ field, label?, format? }]: fields hidden from the row and revealed in a click-to-open dialog, each with its own optional value format. Declaringdetailsmakes each row clickable.groupBy: { field, titleField?, subtitleField? }: render rows as collapsible sections byfield; the section title and subtitle read from each group's first row.drilldown: { island, match }: embed another island in the row-details dialog, its rows filtered bymatch(a map of drilldown-dataset column → clicked-row field). One level deep: a drilldown island has no drilldown of its own.expand: false: drop the see-all dialog and render every row inline (defaulttrue).
Tip
details and drilldown only do something once a row is clickable. A row becomes clickable
the moment you declare details (or a drilldown), so a table that's just for scanning needs
neither.
timeline.feed
What it is. A reverse-chronological feed of rows. When to use it: logs, activity
streams, a journal, anything that reads as "what happened, newest first." It needs a ts
(the timestamp) and a titleField; the runtime sorts so the newest row is on top and renders
each timestamp smartly (a date-only value as Jun 11, 2026, a real timestamp as
Jun 11, 21:30).
{
"type": "timeline.feed",
"title": "Activity",
"dataset": "activity",
"ts": "ts",
"titleField": "action",
"detail": "actor"
}Key options.
-
detail: a secondary string shown next to the title.kind: a category string. -
details/drilldown/expand: exactly as ontable.grid(click-to-open dialog, embedded filtered island, render-all toggle). -
groupBy: { field, titleField?, subtitleField? }: collapsible sections, same shape as on the table. -
Rich rows. Setting any of
highlight,stats, orfooterswitches a row from a single line to a header/stats/footer layout:highlight: { field, format?, unit? }: an emphasized value pinned to the right of the title.stats: [{ field, label?, format?, unit?, color? }]: labeled inline stats under the title; labels default to a palette,colorpins one.footer: [{ field, label?, format?, unit?, pill? }]: a meta line led by the timestamp;pill: truerenders the value as a badge.
Each of these takes an optional value format (
format) or free-formunitto style its value.
{
"type": "timeline.feed",
"title": "Workouts",
"dataset": "workouts",
"ts": "ts",
"titleField": "name",
"highlight": { "field": "strain", "format": "int" },
"stats": [
{ "field": "avg_hr", "label": "HR", "unit": "bpm" },
{ "field": "kcal", "label": "Cal", "unit": "kcal" }
],
"footer": [{ "field": "sport", "pill": true }]
}search.box
What it is. A client-side search input over a dataset. When to use it: the dataset is
large enough that you'd rather look a row up than scroll. Typing matches rows case-insensitively
across fields; results drop down as an autocomplete showing titleField, and selecting one
opens that row's full details.
{
"type": "search.box",
"dataset": "ingredients",
"fields": ["name", "category"],
"titleField": "name",
"detail": "category",
"placeholder": "Search foods…"
}Key options.
fields: [...]: the columns a query matches against (substring, case-insensitive).titleField: what each result row shows;detail: an optional secondary line under it.placeholder?: the input's placeholder text.limit?: the maximum number of visible results (default10).
Note
search.box matches with a plain client-side substring over the rows already loaded; it isn't
a SQL LIKE and doesn't page through the whole dataset. For a huge table, shape a narrower
sql dataset for it to search.
Charts
A family of islands for shape, comparison, distribution, and geography — lines and bars, parts of a whole, scatter and radar, heatmaps, funnels, and a world map.
Content & Layout
The islands that aren't charts of your data — a note for prose, a source doc for a file or link, a content editor for a workspace of markdown, a form for adding rows, and a layout row.