Skip to content

Columns

Configure column behavior, resizing, reordering, and display options.

interface ColumnDef<T> {
field: keyof T | string; // Data field
header: string; // Header text
width?: string; // CSS width (e.g., '200px', '20%')
align?: 'left' | 'right' | 'center';
sortable?: boolean; // Default: true
flashOnChange?: boolean; // Flash on value changes
formatter?: (value: unknown, row: T) => ReactNode;
cellClass?: (value: unknown, row: T) => string;
resizable?: boolean; // Per-column resize control
reorderable?: boolean; // Per-column reorder control
minWidth?: number; // Minimum width in px
maxWidth?: number; // Maximum width in px
}
const columns = [
{ field: 'symbol', header: 'Symbol', width: '100px' },
{ field: 'name', header: 'Name', width: '200px' },
{ field: 'price', header: 'Price', align: 'right', width: '100px' },
];

Access nested object properties with dot notation:

interface User {
id: number;
profile: {
name: string;
email: string;
};
address: {
city: string;
};
}
const columns = [
{ field: 'profile.name', header: 'Name' },
{ field: 'profile.email', header: 'Email' },
{ field: 'address.city', header: 'City' },
];
<DataGrid
data={data}
columns={columns}
rowKey="id"
resizable
/>

Persist column widths in state or storage:

const [columnWidths, setColumnWidths] = useState<Record<string, number>>({
symbol: 100,
name: 200,
price: 100,
});
<DataGrid
data={data}
columns={columns}
rowKey="id"
resizable
columnWidths={columnWidths}
onColumnResize={(field, width) =>
setColumnWidths(prev => ({ ...prev, [field]: width }))
}
/>
<DataGrid
data={data}
columns={columns}
rowKey="id"
resizable
minColumnWidth={80} // Global minimum
maxColumnWidth={400} // Global maximum
/>
// Or per-column
const columns = [
{ field: 'symbol', header: 'Symbol', minWidth: 60, maxWidth: 150 },
{ field: 'description', header: 'Description', minWidth: 200 },
];

When resizing hits a limit, the resize handle turns red and the cursor shows not-allowed.

const columns = [
{ field: 'symbol', header: 'Symbol', resizable: false }, // Fixed width
{ field: 'name', header: 'Name' }, // Resizable
{ field: 'price', header: 'Price' }, // Resizable
];
<DataGrid
data={data}
columns={columns}
rowKey="id"
reorderable
/>

Persist column order:

const [columnOrder, setColumnOrder] = useState(['symbol', 'name', 'price']);
<DataGrid
data={data}
columns={columns}
rowKey="id"
reorderable
columnOrder={columnOrder}
onColumnReorder={setColumnOrder}
/>
function usePersistedColumnOrder(key: string, defaultOrder: string[]) {
const [order, setOrder] = useState<string[]>(() => {
const saved = localStorage.getItem(key);
return saved ? JSON.parse(saved) : defaultOrder;
});
const handleReorder = (newOrder: string[]) => {
setOrder(newOrder);
localStorage.setItem(key, JSON.stringify(newOrder));
};
return [order, handleReorder] as const;
}
// Usage
const [columnOrder, setColumnOrder] = usePersistedColumnOrder(
'my-grid-columns',
['symbol', 'name', 'price']
);
const columns = [
{ field: 'symbol', header: 'Symbol', reorderable: false }, // Pinned
{ field: 'name', header: 'Name' }, // Can be reordered
{ field: 'price', header: 'Price' }, // Can be reordered
];
const columns = [
{ field: 'symbol', header: 'Symbol', align: 'left' }, // Default
{ field: 'name', header: 'Name', align: 'center' },
{ field: 'price', header: 'Price', align: 'right' }, // Numbers
];

Columns are sortable by default. Disable sorting for specific columns:

const columns = [
{ field: 'symbol', header: 'Symbol', sortable: true }, // Sortable (default)
{ field: 'actions', header: 'Actions', sortable: false }, // Not sortable
];

Return a string or React element:

const columns = [
{
field: 'price',
header: 'Price',
formatter: (value) => `$${value.toFixed(2)}`,
},
{
field: 'change',
header: 'Change',
formatter: (value, row) => (
<span style={{ color: value >= 0 ? 'green' : 'red' }}>
{value >= 0 ? '+' : ''}{value.toFixed(2)}%
</span>
),
},
{
field: 'status',
header: 'Status',
formatter: (value) => {
const colors = { active: 'green', pending: 'yellow', inactive: 'gray' };
return <span className={`status-${value}`}>{value}</span>;
},
},
];

Apply conditional CSS classes:

const columns = [
{
field: 'pnl',
header: 'P&L',
cellClass: (value) => value >= 0 ? 'positive' : 'negative',
},
{
field: 'status',
header: 'Status',
cellClass: (value, row) => {
if (row.urgent) return 'cell-urgent';
return `status-${value}`;
},
},
];
.positive { color: var(--grid-bid); }
.negative { color: var(--grid-ask); }
.cell-urgent { background: rgba(239, 68, 68, 0.2); }

Enable flash effects for real-time data:

const columns = [
{ field: 'symbol', header: 'Symbol' }, // No flash
{ field: 'price', header: 'Price', flashOnChange: true },
{ field: 'volume', header: 'Volume', flashOnChange: true },
];

Values flash:

  • Green when value increases
  • Red when value decreases

See Flash Highlighting for details.