DataTable
Sortable table with rich column formatting — currency, percent, delta, status badges, dates, links, and booleans. Client-side sorting with staggered row animations.
Top Customers by Revenue
Ranked by total lifetime revenue across all plans
| Customer | Revenue | Growth | Plan | Since |
|---|---|---|---|---|
| Acme Corp | $48,200 | +23.5% | Enterprise | Jan 15, 2023 |
| Globex Inc | $35,800 | -4.2% | Business | Jun 1, 2022 |
| Initech | $29,100 | +12.8% | Enterprise | Aug 22, 2023 |
| Umbrella Co | $22,400 | +45.1% | Business | Feb 10, 2024 |
| Soylent Corp | $18,900 | +8.3% | Starter | May 30, 2024 |
Installation
npx taw-ui add data-tableThis copies the component source and schema into your project. You own the code — customize anything.
Usage
import { tool } from "ai"
import { DataTableSchema } from "@/components/taw/data-table"
export const showTable = tool({
description: "Show data in a sortable table",
parameters: z.object({ query: z.string() }),
outputSchema: DataTableSchema,
execute: async ({ query }) => {
const result = await queryDatabase(query)
return {
id: slugify(query),
title: result.title,
columns: result.columns.map(c => ({
key: c.key,
label: c.label,
type: c.type,
sortable: true,
})),
rows: result.rows,
total: result.total,
defaultSort: { key: "revenue", direction: "desc" },
source: { label: "Database", freshness: "just now" },
}
},
})import { DataTable } from "@/components/taw/data-table"
import type { TawToolPart } from "taw-ui"
function ToolOutput({ part }: { part: TawToolPart }) {
// Handles loading, error, and success states
return <DataTable part={part} />
}Column Types
9 built-in column types handle formatting without custom renderers.
| Field | Type | Description |
|---|---|---|
| text | default | Plain string |
| number | format | Locale-formatted number with optional decimals |
| currency | format | Currency-formatted with symbol (configurable via format.currency) |
| percent | format | Signed percentage with color coding (green/red) |
| delta | format | Arrow + signed number with color coding |
| date | format | Locale-formatted date (short month, day, year) |
| badge | visual | Pill badge with accent color |
| link | visual | Clickable link with dotted underline |
| boolean | visual | Checkmark (true) or cross (false) |
Props
| Field | Type | Description |
|---|---|---|
| part* | TawToolPart | Tool call lifecycle state — handles loading, error, and success |
| animate | boolean | Enable stagger row animations (default: true) |
| className | string | Additional CSS classes on the wrapper |
Schema
Cross-field validation ensures defaultSort.key exists in your columns — caught at parse time, not at render.
| Field | Type | Description |
|---|---|---|
| id* | string | Stable identifier |
| title | string | Table header title |
| description | string | Subtitle below the title |
| columns* | Column[] | Column definitions (min 1) |
| rows* | Record[] | Row data as key-value objects |
| total | number | Total row count (for pagination context) |
| defaultSort | { key, direction } | Initial sort column and direction |
| confidence | number (0-1) | AI confidence badge |
| caveat | string | Uncertainty note |
| source | Source | Data provenance (label + freshness) |
| Field | Type | Description |
|---|---|---|
| key* | string | Maps to row data keys |
| label* | string | Column header text |
| type | ColumnType | One of 9 types (default: "text") |
| align | "left" | "center" | "right" | Text alignment (default: "left") |
| sortable | boolean | Enable sort on this column (default: false) |
| width | string | CSS width (e.g. "120px", "20%") |
| format | { currency?, decimals? } | Extra formatting options for currency/number types |
Features
Click column headers to toggle asc/desc/none
Rich formatting without custom renderers
defaultSort.key must exist in columns, caught at parse time
Footer shows row count and data provenance
Rows animate in sequence on first render
Invalid columns show field-level details with suggestions