Skip to content

Blocks

Whole screens and frames, finished: pass the data, get the page. Each is assembled from exported parts, to use one piece alone or build a variant.

Blocks are whole screens and frames, finished: pass the data and callbacks, get the page. A sidebar is the same logic in every app, so an app passes navigation and nothing else; a list is the table block plus rows and columns. Each block is assembled from parts that are exported too, so you can use one small piece alone or build a variant from the same parts.

import { AppShell, ListPage, ListTable } from '@arbol-ai/ui';

<AppShell navigation={navigation}>
  <ListPage title="Contacts" count={total} actions={<NewContactButton />}>
    <ListTable
      aria-label="Contacts"
      columns={columns}
      data={contacts}
      getRowHref={(contact) => `/contacts/${contact.id}`}
    />
  </ListPage>
</AppShell>;
Block What it brings
AppShell and its slots Sidebar from items, header, back link, companion panel; AccountMenu, OrganizationMenu, LogoTile, ProductMark
ListPage, ListTable Toolbar (search, filters, saved views, columns), sorting, row links and menus, every state, pages, bulk actions
RecordPage, SettingsPage Record header with pager and rename, tabs, properties aside; settings sections, cards, links and save bar
FormDialog, FormSheet (/form) A create or edit flow: fields, Cancel and a pending Submit, the server’s refusal, the discard guard
KpiGrid, ChartCard, ReportPage A period picker, KPI tiles from data, chart cards from series, breakdowns
Route states RouteErrorState, NotFoundState, NoAccessState, AppLoadingState, and TanStack Router adapters in /router

Tables, forms, routing, data fetching and virtualization are all TanStack: Table (DataTable), Form, Router, Query and Virtual (PickList).

Type to search…

↑↓ navigate↵ selectEsc close