crispmeasured from Attio

CRUD flow

Create, read, update, and delete on one live table — the concrete companion to the Patterns guide.

The four data-app verbs on one surface, all live. This is the Records Table with nothing hidden — try each step below on the real component and watch the record count and cells change. It's the hands-on companion to the CRUD & Detail Patterns guide.

8 records
Googlegoogle.com
182,000Mountain View, CA
Sundar Pichaitwitter.com/google29,800,000linkedin.com/company/google
307,000,000,000
Stripestripe.com
8,000San Francisco, CA
Patrick Collisontwitter.com/stripe1,200,000linkedin.com/company/stripe
16,000,000,000
Figmafigma.com
1,300San Francisco, CA
Dylan Fieldtwitter.com/figma540,000linkedin.com/company/figma
600,000,000
Notionnotion.so
800San Francisco, CA
Ivan Zhaotwitter.com/notionhq480,000linkedin.com/company/notionhq
400,000,000
Linearlinear.app
60Remote
Karri Saarinentwitter.com/linear120,000linkedin.com/company/linear
30,000,000
Vercelvercel.com
500San Francisco, CA
Guillermo Rauchtwitter.com/vercel310,000linkedin.com/company/vercel
100,000,000
OpenAIopenai.com
3,500San Francisco, CA
Sam Altmantwitter.com/openai4,200,000linkedin.com/company/openai
3,400,000,000
Anthropicanthropic.com
1,000San Francisco, CA
Dario Amodeitwitter.com/anthropicai520,000linkedin.com/company/anthropic
1,000,000,000

Walk each verb

Create. Click + New (top-right) to open the create Dialog — fill a field or two and hit Create record (or ⌘↵); the row appears and the count bumps. For a quicker add, the + New record row at the bottom appends an editable "Untitled" row inline. → Two weights of create: a considered modal, and a one-click inline row.

Read. The table is already reading: click a column header → Sort ascending / descending, or open Filter to pick an attribute and set a condition (contains / is / is empty). The footer aggregates each column (Sum / Count). → Sort, filter, and aggregate are the reading tools; the list is home base.

Update. Double-click any text / number / url / date cell to edit it in place; Enter commits, Escape cancels. Open a column header's menu to rename it or move it left / right. → Editing happens in the grid — no separate form, applied optimistically.

Delete. Tick one or more row checkboxes to raise the bulk action bar (N Selected); open More → Delete (styled red) to remove them, or Add to list for the safe bulk action. → Destructive actions live one menu-layer down behind an explicit selection.

Wiring it to a backend

Every mutation above updates local state — the table is controlled, so productionising it is swapping the setters for API calls:

<RecordsTable
  rows={rows}
  columns={columns}
  onSelectionChange={setSelected}
  // create → POST, inline edit → PATCH, delete → DELETE,
  // each applied optimistically to `rows` then reconciled on response
/>

Because state flows top-down and updates are optimistic, the UI stays instant and the network layer stays a thin edge around it.

On this page