

## Overview [#overview]

Define stable columns with `createDataGridColumnHelper`. Column definitions
control content, sizing, available header actions, and accessibility metadata.
Configure merged layouts in the advanced
[Cell Spanning](/components/data-grid/cell-spanning) guide.

String headers automatically show actions based on their column settings.
Disable actions that do not make sense for a column, such as hiding on a
primary identifying or action column. For custom headers, enable the menu with
`meta.headerMenu` and provide its accessible name with `meta.headerLabel`.

Set `meta.rowHeader` on the primary identifying column and use `meta.align` for
content alignment. Columns share available width equally by default, so most
columns should omit both `flex` and `size`. Use `flex` only when a column needs
a different proportional share, such as a primary name column. Reserve `size`
for exact-width utility columns such as selection or actions. `flex` and `size`
are mutually exclusive, while `minSize` and `maxSize` bound both automatic
fitting and manual resizing.

Column resizing is opt-in. A resized column keeps its pixel width until sizing
is reset. The grid scrolls horizontally when exact widths and flexible minimum
widths no longer fit the viewport.

Use `useDataGridView` when visibility, order, or pinning belongs to a saved
view. Column sizing remains responsive to the current viewport. See
[Saved Views](/components/data-grid/saved-views).

## Examples [#examples]

### Sizing and resizing [#sizing-and-resizing]

Omit `flex` and `size` for an equal share, use `flex` for intentional weighting,
and use `size` for an exact pixel width. Set `minSize` and `maxSize` wherever a
column needs readable bounds. Enable resizing on the table and use
`enableResizing: false` for columns that should not resize.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="DataGridColumnSizingScenario" />
  </Tab>

  <Tab value="Code">
    ```tsx
    const columns = columnHelper.columns([
      columnHelper.accessor("name", {
        flex: 2,
        header: "Matter",
        minSize: 160,
        maxSize: 480,
      }),
      columnHelper.accessor("status", {
        header: "Status",
        minSize: 96,
        maxSize: 220,
      }),
      columnHelper.accessor("amount", {
        header: "Value",
        size: 120,
        enableResizing: false,
      }),
    ]);

    const table = useDataGridTable({
      columns,
      data,
      enableColumnPinning: false,
      enableColumnResizing: true,
      enableGrouping: false,
      enableHiding: false,
      enableSorting: false,
    });

    <PreviewFooter>
      <Button onClick={() => table.resetColumnSizing()} variant="secondary">
        Reset widths
      </Button>
    </PreviewFooter>
    <DataGrid table={table}>
      <DataGrid.Viewport aria-label="Resizable matter columns" />
    </DataGrid>
    ```
  </Tab>
</Tabs>

### Reordering [#reordering]

Set `enableColumnReordering` to add Move left and Move right header actions.
Add `enableColumnDragging` when drag handles are also required; dragging has no
effect unless reordering is enabled.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="DataGridColumnReorderingScenario" />
  </Tab>

  <Tab value="Code">
    ```tsx
    const table = useDataGridTable({
      columns,
      data,
      enableColumnPinning: false,
      enableColumnReordering: true,
      enableGrouping: false,
      enableHiding: false,
      enableSorting: false,
    });

    <PreviewFooter>
      <Button onClick={() => table.resetColumnOrder()} variant="secondary">
        Reset order
      </Button>
    </PreviewFooter>
    ```
  </Tab>
</Tabs>

### Visibility [#visibility]

Hideable columns appear in the header's Columns submenu. Keep identifying and
action columns visible with `enableHiding: false`.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="DataGridColumnVisibilityScenario" />
  </Tab>

  <Tab value="Code">
    ```tsx
    const columns = columnHelper.columns([
      columnHelper.accessor("name", {
        enableHiding: false,
        header: "Matter",
      }),
      columnHelper.accessor("status", { header: "Status" }),
      columnHelper.accessor("owner", { header: "Owner" }),
    ]);

    const table = useDataGridTable({ columns, data });
    ```
  </Tab>
</Tabs>

### Pinning [#pinning]

Eligible columns expose Pin to left and Pin to right header actions. Use
`initialState.columnPinning` when columns should start pinned; `start` pins left
and `end` pins right.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="DataGridColumnPinningScenario" />
  </Tab>

  <Tab value="Code">
    ```tsx
    const table = useDataGridTable({
      columns,
      data,
      initialState: {
        columnPinning: { start: ["name"], end: [] },
      },
    });
    ```
  </Tab>
</Tabs>

### Sorting [#sorting]

Configure sortable columns with `sortFn` and `enableSorting`. DataGrid adds
Asc and Desc header actions and lets users clear the active direction.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="DataGridSortingScenario" />
  </Tab>

  <Tab value="Code">
    ```tsx
    const columns = columnHelper.columns([
      columnHelper.accessor("name", {
        header: "Matter",
        sortFn: "text",
      }),
      columnHelper.accessor("amount", {
        header: "Value",
        sortFn: "basic",
      }),
    ]);

    const table = useDataGridTable({ columns, data });
    ```
  </Tab>
</Tabs>

### Filtering with Filters [#filtering-with-filters]

Use Cubitt Filters for product-facing filtering. `useDataGridFilters` prepares
the columns and table options; pass both results to `useDataGridTable` and
adapt the resulting table with `useDataGridFiltersControl`. See [Filters](/components/filters#datagrid-tanstack-table-v9)
for filtering strategies, options, and advanced field mappings.

<Tabs items="['Preview', 'Code']">
  <Tab value="Preview">
    <Preview name="DataGridFilteringScenario" />
  </Tab>

  <Tab value="Code">
    ```tsx
    import { useDataGridTable } from "@tilt-legal/cubitt-components/data-grid";
    import {
      defineFilters,
      Filters,
      useDataGridFilters,
      useDataGridFiltersControl,
    } from "@tilt-legal/cubitt-components/filters";
    import { Toolbar } from "@tilt-legal/cubitt-components/toolbar";

    const filterDefinitions = defineFilters([
      {
        key: "name",
        label: "Matter",
        type: "text",
        operators: [{ label: "Contains", value: "contains" }],
      },
      {
        key: "status",
        label: "Status",
        type: "select",
        operators: [{ label: "Is", value: "is" }],
        options: [
          { label: "Active", value: "Active" },
          { label: "Review", value: "Review" },
          { label: "Closed", value: "Closed" },
        ],
      },
    ] as const);

    const dataGridFilters = useDataGridFilters({
      columns,
      definition: filterDefinitions,
      strategy: "client",
    });

    const table = useDataGridTable({
      ...dataGridFilters.tableOptions,
      columns: dataGridFilters.columns,
      data,
    });
    const filtersControl = useDataGridFiltersControl(table);

    return (
      <Filters.Root {...filtersControl}>
        <Toolbar.Actions>
          <Filters.Trigger />
        </Toolbar.Actions>
        <div className="flex flex-wrap items-center gap-2.5">
          <Filters.Items />
        </div>
      </Filters.Root>
    );
    ```
  </Tab>
</Tabs>

## API Reference [#api-reference]

### Table options [#table-options]

| Option                   | Type                    | Default   | Description                                                  |
| ------------------------ | ----------------------- | --------- | ------------------------------------------------------------ |
| `enableColumnResizing`   | `boolean`               | `false`   | Enables column resize controls.                              |
| `columnResizeMode`       | `"onChange" \| "onEnd"` | `"onEnd"` | Controls whether widths update during or after resizing.     |
| `columnResizeDirection`  | `"ltr" \| "rtl"`        | `"ltr"`   | Sets the direction used to calculate resize drag offsets.    |
| `enableColumnReordering` | `boolean`               | `false`   | Adds Move left and Move right actions to eligible columns.   |
| `enableColumnDragging`   | `boolean`               | `false`   | Adds drag handles when reordering is enabled.                |
| `enableHiding`           | `boolean`               | `true`    | Allows eligible columns to appear in the Columns submenu.    |
| `enableColumnPinning`    | `boolean`               | `true`    | Allows eligible columns to expose start and end pin actions. |
| `enableSorting`          | `boolean`               | `true`    | Allows accessor columns to expose sorting actions.           |

### Column options [#column-options]

| Option                   | Type                                      | Default                    | Description                                                                   |
| ------------------------ | ----------------------------------------- | -------------------------- | ----------------------------------------------------------------------------- |
| `flex`                   | `number`                                  | `1` when `size` is omitted | Relative share of available width. Must be greater than zero.                 |
| `size`                   | `number`                                  | `undefined`                | Exact column width in pixels. Cannot be combined with `flex`.                 |
| `minSize`                | `number`                                  | `20`                       | Minimum width for automatic fitting and manual resizing.                      |
| `maxSize`                | `number`                                  | `Number.MAX_SAFE_INTEGER`  | Maximum width for automatic fitting and manual resizing.                      |
| `enableResizing`         | `boolean`                                 | Table setting              | Enables or disables resizing for this column.                                 |
| `enableColumnReordering` | `boolean`                                 | Table setting              | Overrides reordering for this column.                                         |
| `enableHiding`           | `boolean`                                 | `true`                     | Allows this column to be hidden.                                              |
| `enablePinning`          | `boolean`                                 | `true`                     | Allows this column to be pinned.                                              |
| `enableSorting`          | `boolean`                                 | `true`                     | Allows this accessor column to be sorted.                                     |
| `sortFn`                 | `SortFnOption<DataGridFeatures, TData>`   | `"auto"`                   | Selects or supplies the comparison function.                                  |
| `filterFn`               | `FilterFnOption<DataGridFeatures, TData>` | `"auto"`                   | Selects or supplies a custom filter function when Cubitt Filters is not used. |

### Table methods [#table-methods]

| API                           | Signature                 | Description                                                                     |
| ----------------------------- | ------------------------- | ------------------------------------------------------------------------------- |
| `table.resetColumnSizing`     | `(defaultState?) => void` | Restores initial widths, or clears sizing state when passed `true`.             |
| `table.resetColumnOrder`      | `(defaultState?) => void` | Restores the initial column order, or the definition order when passed `true`.  |
| `table.resetColumnVisibility` | `(defaultState?) => void` | Restores initial visibility, or shows every eligible column when passed `true`. |
| `table.resetColumnPinning`    | `(defaultState?) => void` | Restores initial pinning, or unpins every column when passed `true`.            |
| `table.resetSorting`          | `(defaultState?) => void` | Restores initial sorting, or clears it when passed `true`.                      |

### Column helpers [#column-helpers]

| API                         | Signature                                                          | Description                                                                    |
| --------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
| `columnHelper.group`        | `(options: GroupColumnDef) => GroupColumnDef`                      | Creates a grouped header without grouping rows.                                |
| `useDataGridFilters`        | `(options: UseDataGridFiltersOptions) => UseDataGridFiltersResult` | Prepares columns and table options for Cubitt Filters.                         |
| `useDataGridFiltersControl` | `(table: DataGridTable<TData>) => UseDataGridFiltersControlResult` | Adapts a configured table into `Filters.Root` props and current facet options. |

### Column metadata [#column-metadata]

| Field         | Type                           | Default   | Description                                                                                                                        |
| ------------- | ------------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `headerLabel` | `string`                       | -         | Plain-text name for accessibility and menu copy when the rendered header is not a string.                                          |
| `headerMenu`  | `boolean`                      | Automatic | String headers include a menu when actions are available. Set `true` on a compatible custom header or `false` to disable the menu. |
| `align`       | `"start" \| "center" \| "end"` | `"start"` | Aligns header and body content.                                                                                                    |
| `rowHeader`   | `boolean`                      | `false`   | Renders body cells as accessible row headers. Use for the primary identifying column.                                              |
