Skip to main content


Columns are simple objects and can be declared as such:

const columns = [
{ title: 'A', id: 'a', /*...*/ },
{ title: 'B', id: 'b', /*...*/ },


Type: JSX.Element
Default: null

Element to display in the header row.


Type: string

You can specify a unique ID for each column. This allows you to specify the column ID instead of its index when controlling the grid.


Sizing uses the flexbox algorithm, checkout some examples.


Type: number
Default: 0

Same as the flex-basis property. This is the initial width of the column in pixels before growing or shrinking to fit the grid width.


Type: number
Default: 1

Same as the flex-grow property. This is a unit-less factor that dictates how much this column should grow to occupy the entire available width of the grid.


Type: number
Default: 1

Same as the flex-shrink property. This is a unit-less factor that dictates how much this column should shrink to fit to the available width of the grid.


Type: number
Default: 100

Minimum width of the column in pixels. Can be 0 for no minimum value.


Type: number | null
Default: null

Maximum width of the column in pixels. Can be null for no maximum value.

Copy pasting


Type: ({ rowData, rowIndex }) => number | string | null

A function that returns the value of the copied cell. If the user copies multiple cells at once, this function will be called multiple times. It can return a string, a number, or null, but it will always be turned into a string in the end.


Type: ({ rowData, value, rowIndex }) => any

A function that takes in a row and the value to be pasted, and should return the updated row. If the value should be ignored, it should still return the unchanged row. The value is always a string, except if prePasteValues returns something else, and should therefore be casted to whatever type is needed.

It is recommended to make sure that the pasteValue can handle all values returned by copyValue otherwise a user might be able to copy something but not paste it.


Type: (values: string[]) => any[] | Promise<any[]>

This function is called right before pasteValue with all the data that the user is trying to paste for that column. This gives you the opportunity to treat the pasted data as a whole and change it before passing it to pasteValue.

This is where you would do some asynchronous work (eg. mapping names to actual IDs) and return a Promise.


Type: ({ rowData, rowIndex }) => any

A function that deletes the column value of a row. Used when the user cuts, clears a cell, or deletes a row.



Type: CellComponent

A React component that renders a cell. See props


Type: any

A value to pass to every cell component of the column through the columnData prop. Usually used to hold some kind of options for the column.

For example, to implement a select column you would use columnData to pass the choices:

const SelectComponent = ({ columnData: choices }) => {
// Render cell using `choices`

const selectColumn = (choices) => ({
columnData: choices,
component: SelectComponent,

function App() {
return <DataSheetGrid columns={[
{ ...selectColumn(['Light', 'Dark']), title: 'Theme' }
]} />


Type: string

CSS class of the header cell.


Type: string | (({ rowData, rowIndex, columnId }) => string | undefined)

CSS class of each cell of the column. Can be a string if the class is the same for all cells, or a function if you need a different class per row.



Type: boolean | (({ rowData, rowIndex }) => boolean)
Default: false

Disable the entire column by passing true, or disable it for specific rows by passing a function. Disabled cells cannot be edited but their values can still be copied.

Try toggling the "active" column:

{ title: 'Active', /*...*/ },
{ title: 'First name', disabled: ({ rowData }) => !, /*...*/ },
{ title: 'Last name', disabled: true, /*...*/ },

Notice that in this example you cannot delete a row using the Del key, this is because you can only delete empty rows. This might be problematic depending on your use-case, to solve this issue you can use isCellEmpty and always return true to ignore this column.


Type: boolean
Default: false

Usually when the user is editing a cell, pressing the up, down, or return key will exit editing mode. Setting disableKeys to true will prevent this behavior. This is used when the widget needs to handle the up and down keys itself (eg. to increase the value, or select a choice). Usually the widget also needs to handle the return key by calling stopEditing.


Type: boolean
Default: false

When you implement a widget using a portal (ie. a div that is not a direct children of the cell) you might want the cell to keep focus when the user interacts with that element (even though it is actually outside of the grid itself). This means that you have to handle the click event and call stopEditing yourself to release focus.



Type: ({ rowData, rowIndex }) => boolean
Default: () => false

When pressing Del, a user can only delete empty rows (a user can still delete non-empty rows using a right-click). A row is considered empty when all its cells are empty. This function allows to customize what is considered an empty cell.

Because the default value is a function that always returns false (meaning the cell is never considered empty), you must implement your own logic to let the user delete rows using the Del key.