Skip to content

grid

Rows a person searches, filters, sorts, selects and acts on, such as every open ticket and who is working on it.

source names a source of the screen; columns lists 1 to 30 columns, each a key (a column of the rows), a label and a kind: text, strong, muted, mono, number, status, badge, time or bar (numeric kinds align themselves). priority says when a column hides as the page narrows (primary never, secondary below 1060 px, tertiary below 720 px). tones maps a status or badge value to ok, warn, bad, info or neutral. search (true by default) searches every visible column; filters lists the columns a person can filter by. open adds the actions column last, an Open link on every row (the key column stays plain): a screen name opens /a/<app>/<open>?id=<row id>, $id the screen the row's id names. actions act on the selected rows: - set: { column, label, value } (or options to choose from), - delete: {} (always confirmed), - export: csv. plain: true drops the toolbar, selection and pager for a small read-only table. The address holds the grid's state, so a filtered view is a link. Put the column a person knows a row by first, as strong; give every column past three priority: tertiary so a phone keeps three. An empty cell shows a dash.

When to use

Use it when

  • Many rows a person works through, such as the open tickets of a queue.

  • Rows a person changes in bulk, such as assigning tickets to an agent or closing them.

  • A small table of facts, such as the policies in force, with `plain: true`.

Use another block when

The open tickets, assigned and closed in bulk

Filters
Columns
3 rows
Select rows to act on them
SelectedTicketSubjectAgentStatusOpenedActions
48213VPN drops every 20 minutesNetworkClosed by agent2026-10-31 09:12Open
48214Reset MFA on new phoneIdentityWaiting for requester2026-10-31 09:07Open
48215Expense tool shows last quarterAppsNeeds a person2026-10-31 08:58Open
grid:
  id: tickets
  source: tickets
  columns:
    - { key: id, label: Ticket, kind: strong }
    - { key: subject, label: Subject }
    - { key: agent, label: Agent, kind: badge }
    - { key: status, label: Status, kind: status, tones: { Closed by agent: ok, Needs a person: warn } }
    - { key: opened_at, label: Opened, kind: time, priority: secondary }
  filters: [agent, status]
  open: ticket
  actions:
    - set: { column: agent, label: Assign to…, options: [Identity, Network, Apps] }
    - set: { column: status, value: Closed by agent, label: Close, approval: true }
    - export: csv
<a id="tickets"></a>

| Ticket | Subject | Agent | Status | Opened | Open |
|---|---|---|---|---:|---|
| 48213 | VPN drops every 20 minutes | Network | Closed by agent | 2026-10-31 09:12 | [Open](/a/catalog/ticket?id=48213) |
| 48214 | Reset MFA on new phone | Identity | Waiting for requester | 2026-10-31 09:07 | [Open](/a/catalog/ticket?id=48214) |
| 48215 | Expense tool shows last quarter | Apps | Needs a person | 2026-10-31 08:58 | [Open](/a/catalog/ticket?id=48215) |

Showing 1–3 of 3

- #tickets.set-agent "Assign to…": POST /a/catalog/{screen}/act/tickets/set-agent · sel=row id, repeated per row, value=one of Identity, Network, Apps; sets agent · approval: no · cost: write
- #tickets.set-status-closed-by-agent "Close": POST /a/catalog/{screen}/act/tickets/set-status-closed-by-agent · sel=row id, repeated per row; sets status = Closed by agent · approval: yes · cost: write
- #tickets.export "Export CSV": GET /a/catalog/{screen}/act/tickets/export · CSV of the grid's current view · approval: no · cost: free

The agents, filtered by queue

Filters
Columns
2 rows
AgentQueueClosed this monthNeeds a person (%)
IdentityAccounts and access11204
AppsBusiness applications64022
grid:
  source: agents
  columns:
    - { key: name, label: Agent, kind: strong }
    - { key: queue, label: Queue }
    - { key: closed, label: Closed this month, kind: number }
    - { key: needs_person_pct, label: Needs a person (%), kind: number, priority: secondary }
  filters: [queue]
  page_size: 50
  actions:
    - export: csv
<a id="grid-1"></a>

| Agent | Queue | Closed this month | Needs a person (%) |
|---|---|---:|---:|
| Identity | Accounts and access | 1120 | 4 |
| Apps | Business applications | 640 | 22 |

Showing 1–2 of 2

- #grid-1.export "Export CSV": GET /a/catalog/{screen}/act/grid-1/export · CSV of the grid's current view · approval: no · cost: free

The policies in force, as a small table

PolicyApplies toState
Data stays in the EUEvery agentenforced
Orders over $500 need a managerProcurement agentenforced
grid:
  source: policies
  plain: true
  columns:
    - { key: policy, label: Policy, kind: strong }
    - { key: applies_to, label: Applies to }
    - { key: state, label: State, kind: status, tones: { enforced: ok } }
<a id="grid-1"></a>

| Policy | Applies to | State |
|---|---|---|
| Data stays in the EU | Every agent | enforced |
| Orders over $500 need a manager | Procurement agent | enforced |

Showing 1–2 of 2

States

  • ready

    the source's rows, drawn

  • empty

    the source has no rows: an Empty part saying why and what comes next

  • error

    the source failed: "We couldn't load …" naming the block's rows, the source's sentence and Try again; the page still answers 200

ActionNeedsDoesReversibleConfirm pageCost
seta selection of rows, or the rowsets the column to the value on those rowsyeswhen declaredwrite
deletea selection of rowsdeletes those rowsnoalwayswrite
exportnonedownloads the grid's current view as CSV (RFC 4180: CRLF after each record); written `- export: csv`yesneverfree
JSON Schema

Search

esc

Go to