# Example: Declarative rows mode

A live-events grid in the default rows mode — pass rows and columns, and PretableSurface reconciles later rows props into one long-lived local row model for you.

Source: https://pretable.ai/examples/live-events-grid.md

```tsx EventGrid.tsx
"use client";

import { PretableSurface } from "@pretable/react";

import { columns } from "./columns";
import { events } from "./data";

const VIEWPORT_HEIGHT = 260;

export function EventGrid() {
  return (
    <PretableSurface
      ariaLabel="Live events"
      rows={events}
      columns={columns}
      getRowId={(row) => row.id}
      viewportHeight={VIEWPORT_HEIGHT}
    />
  );
}
```

```ts columns.ts
import { createColumnHelper } from "@pretable/core";

import type { EventRow } from "./data";

const column = createColumnHelper<EventRow>();

export const columns = [
  column.accessor("timestamp", { type: "text", header: "Time" }),
  column.accessor("message", { type: "text", header: "Message" }),
] as const;
```

```ts data.ts
export interface EventRow {
  id: string;
  timestamp: string;
  message: string;
}

export const events: EventRow[] = [
  {
    id: "e1",
    timestamp: "2026-08-12T09:14:00Z",
    message: "Deployment 482 shipped to production",
  },
  {
    id: "e2",
    timestamp: "2026-08-12T09:16:00Z",
    message: "Cache hit rate dropped below 90%",
  },
  {
    id: "e3",
    timestamp: "2026-08-12T09:19:00Z",
    message: "Autoscaler added 2 web workers",
  },
  {
    id: "e4",
    timestamp: "2026-08-12T09:24:00Z",
    message: "Cache hit rate recovered to 96%",
  },
  {
    id: "e5",
    timestamp: "2026-08-12T09:31:00Z",
    message: "Nightly backup completed in 4m12s",
  },
];
```
