# Example: Grid-level cell and header renderers

A support-ticket grid where renderBodyCell and renderHeaderCell on PretableSurface itself pick the presentation per column, the pattern a design-system wrapper reaches for instead of per-column render hooks.

Source: https://pretable.ai/examples/grid-level-renderers.md

```tsx TicketGrid.tsx
"use client";

import {
  PretableBadge,
  PretableStatus,
  PretableSurface,
  type PretableBadgeTone,
  type PretableStatusTone,
} from "@pretable/react";

import { columns } from "./columns";
import { tickets, type Ticket } from "./data";

const VIEWPORT_HEIGHT = 260;

const PRIORITY_TONE: Record<Ticket["priority"], PretableBadgeTone | undefined> =
  {
    high: "negative",
    medium: "warning",
    low: undefined,
  };

const STATUS_TONE: Record<Ticket["status"], PretableStatusTone> = {
  open: "info",
  "in-progress": "warning",
  resolved: "positive",
};

export function TicketGrid() {
  return (
    <div>
      <p style={{ margin: "0 0 8px", fontSize: 13 }}>
        <strong>Priority</strong> and <strong>Status</strong> are drawn by the
        surface's own <code>renderBodyCell</code>, not by a per-column{" "}
        <code>render</code> hook — useful when a wrapper component owns
        presentation for every column it renders, not just one.
      </p>
      <PretableSurface<Ticket>
        ariaLabel="Support tickets"
        columns={columns}
        getRowId={(row) => row.id}
        renderBodyCell={({ row, column, formattedValue }) => {
          if (column.id === "priority") {
            return (
              <PretableBadge tone={PRIORITY_TONE[row.priority]}>
                {row.priority}
              </PretableBadge>
            );
          }
          if (column.id === "status") {
            return (
              <PretableStatus tone={STATUS_TONE[row.status]}>
                {row.status}
              </PretableStatus>
            );
          }
          return formattedValue;
        }}
        renderHeaderCell={({ label }) => <strong>{label}</strong>}
        rows={tickets}
        viewportHeight={VIEWPORT_HEIGHT}
      />
    </div>
  );
}
```

```ts columns.ts
import type { PretableColumn } from "@pretable/react";

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

export const columns: PretableColumn<Ticket>[] = [
  { id: "subject", header: "Subject", widthPx: 220 },
  { id: "priority", header: "Priority", widthPx: 110 },
  { id: "status", header: "Status", widthPx: 130 },
];
```

```ts data.ts
export interface Ticket {
  id: string;
  subject: string;
  priority: "low" | "medium" | "high";
  status: "open" | "in-progress" | "resolved";
}

export const tickets: Ticket[] = [
  {
    id: "t1",
    subject: "Login redirect loop",
    priority: "high",
    status: "open",
  },
  {
    id: "t2",
    subject: "Export button disabled",
    priority: "medium",
    status: "in-progress",
  },
  {
    id: "t3",
    subject: "Typo in invoice footer",
    priority: "low",
    status: "resolved",
  },
  {
    id: "t4",
    subject: "Slow dashboard load",
    priority: "high",
    status: "in-progress",
  },
  { id: "t5", subject: "Dark mode contrast", priority: "low", status: "open" },
];
```
