

## Overview [#overview]

`DataTable` directly owns sorting, column pinning, column resizing, pagination and controlled/uncontrolled table state.

Search, filtering, column visibility, and bulk-action UI are covered on their own pages because they are composed around the table rather than folded into the `DataTable` API surface.

## Sorting [#sorting]

Turn on sorting with `enableSorting`. By default the table manages its own sorting state. Switch to controlled mode only when that state needs to live somewhere else.

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="SortingDataTableExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    function SortableTable() {
      return (
        <DataTable
          data={data}
          columns={columns}
          enableSorting
          initialSorting={[{ id: "name", desc: false }]}
        />
      );
    }
    ```
  </Tab>
</Tabs>

## Column Pinning [#column-pinning]

Turn on pinning with `enableColumnPinning` to let users stick important columns to the left or right edge of the table.

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="ColumnPinningDataTableExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    function PinnableTable() {
      const [columnPinning, setColumnPinning] = useState({
        left: ["name"],
        right: ["status"],
      });

      return (
        <DataTable
          data={data}
          columns={columns}
          enableColumnPinning
          columnPinning={columnPinning}
          onColumnPinningChange={setColumnPinning}
          onColumnPin={(columnId, position) => {
            console.log(columnId, position);
          }}
        />
      );
    }
    ```
  </Tab>
</Tabs>

## Column Resizing [#column-resizing]

Turn on resizing with `enableColumnResizing` to let users adjust column widths with drag handles.

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="ColumnResizingDataTableExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    function ResizableTable() {
      return (
        <DataTable
          data={data}
          columns={columns}
          enableColumnResizing
          onColumnResize={(columnId, size) => {
            console.log(columnId, size);
          }}
        />
      );
    }
    ```
  </Tab>
</Tabs>

## Pagination [#pagination]

Turn on pagination with `enablePagination`. The default uncontrolled state starts at page `0` with a page size of `10`.

<Tabs className="bg-transparent border-none rounded-none" items="['Preview', 'Code']">
  <Tab value="Preview" className="p-0">
    <Preview name="PaginatedDataTableExample" />
  </Tab>

  <Tab value="Code">
    ```tsx
    function PaginatedTable() {
      return (
        <DataTable
          data={data}
          columns={columns}
          enablePagination
          initialPagination={{
            pageIndex: 0,
            pageSize: 5,
          }}
        />
      );
    }
    ```
  </Tab>
</Tabs>

## Controlled vs Uncontrolled [#controlled-vs-uncontrolled]

Every built-in table feature follows the same pattern:

* pass `initial*` props for uncontrolled setup
* pass both `value` and `onChange` props for controlled state
* keep state outside the table only when another part of your UI needs it

```tsx
<DataTable
  data={data}
  columns={columns}
  enableSorting
  enableColumnPinning
  sorting={sorting}
  onSortingChange={setSorting}
  columnPinning={columnPinning}
  onColumnPinningChange={setColumnPinning}
/>
```

## Row Interaction and Escape Hatches [#row-interaction-and-escape-hatches]

Use `onRowClick` when rows should trigger navigation or open another surface. Use `tableOptions` only when you need a lower-level TanStack option that Cubitt does not expose directly.

## API Reference [#api-reference]

### Feature Flags [#feature-flags]

| Prop                   | Type      | Default | Description                                 |
| ---------------------- | --------- | ------- | ------------------------------------------- |
| `enableSorting`        | `boolean` | `false` | Enable sortable column headers              |
| `enableColumnPinning`  | `boolean` | `false` | Enable sticky left and right pinned columns |
| `enableColumnResizing` | `boolean` | `false` | Enable drag handles for column sizing       |
| `enablePagination`     | `boolean` | `false` | Enable TanStack pagination row model        |

### Sorting [#sorting-1]

| Prop              | Type                       | Default | Description                  |
| ----------------- | -------------------------- | ------- | ---------------------------- |
| `initialSorting`  | `SortingState`             | `[]`    | Initial uncontrolled sorting |
| `sorting`         | `SortingState`             | -       | Controlled sorting state     |
| `onSortingChange` | `OnChangeFn<SortingState>` | -       | Sorting change handler       |

### Column Pinning [#column-pinning-1]

| Prop                    | Type                             | Default | Description                                |
| ----------------------- | -------------------------------- | ------- | ------------------------------------------ |
| `initialColumnPinning`  | `ColumnPinningState`             | `{}`    | Initial uncontrolled pinning               |
| `columnPinning`         | `ColumnPinningState`             | -       | Controlled pinning state                   |
| `onColumnPinningChange` | `OnChangeFn<ColumnPinningState>` | -       | Pinning change handler                     |
| `onColumnPin`           | `(columnId, position) => void`   | -       | Called when a column is pinned or unpinned |

### Pagination [#pagination-1]

| Prop                 | Type                          | Default                          | Description                     |
| -------------------- | ----------------------------- | -------------------------------- | ------------------------------- |
| `initialPagination`  | `PaginationState`             | `{ pageIndex: 0, pageSize: 10 }` | Initial uncontrolled pagination |
| `pagination`         | `PaginationState`             | -                                | Controlled pagination state     |
| `onPaginationChange` | `OnChangeFn<PaginationState>` | -                                | Pagination change handler       |

### Resizing [#resizing]

| Prop             | Type                                       | Description                      |
| ---------------- | ------------------------------------------ | -------------------------------- |
| `onColumnResize` | `(columnId: string, size: number) => void` | Called after a column is resized |

### Other Core Props [#other-core-props]

| Prop           | Type                           | Description                       |
| -------------- | ------------------------------ | --------------------------------- |
| `onRowClick`   | `(row: Row<TData>) => void`    | Row click handler                 |
| `tableOptions` | `Partial<TableOptions<TData>>` | Additional TanStack Table options |
