# React Components/Data Table

## Props


| Name | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `columns` | `` | Yes |  | The columns definitions. |
| `data` | `` | Yes |  | The table data to display. |
| `enableMultiRowSelection` | `` | No | true | Whether the multi row selection is enabled. |
| `enableRowSelection` | `` | No |  | Whether the row selection is enabled. |
| `enableSorting` | `` | No | true | Whether the column sorting is enabled. |
| `getRowId` | `` | No |  | By default, the component will look for an id attribute in a data item to identify each row. Using this function, you can define another attribute to use instead (like uuid). |
| `loading` | `` | No |  | Whether the table data are in a loading state. This will replace each cell with a Skeleton. |
| `manualSorting` | `` | No |  | Whether the sorting is handled outside of the table. Use this is the sorting is managed on server-side. |
| `onColumnPinningChange` | `` | No |  | Callback fired when the pinned columns changes. |
| `onColumnVisibilityChange` | `` | No |  | Callback fired when the column visibility changes. |
| `onRowSelectionChange` | `` | No |  | Callback fired when the selected rows changes. |
| `onSortingChange` | `` | No |  | Callback fired when the columns sorting changes. |
| `state` | `` | No |  | @type=DataTableState The controlled table values. |
| `stickyHeader` | `` | No |  | Whether the header should be sticky. |


## Subcomponents


### DataTableEmpty




### DataTableHead



## Examples


### Anatomy Tech

```tsx
{
  tags: ['!dev'],
  render: ({}) => <div style={{
    display: 'flex',
    flexDirection: 'column',
    rowGap: 'var(--ods-theme-row-gap)'
  }}>
      <DataTable columns={sampleColumns} data={sampleData}>
        <DataTableHead />

        <DataTableBody />
      </DataTable>

      <DataTable columns={sampleColumns} data={[]}>
        <DataTableHead />

        <DataTableBody />

        <DataTableEmpty>
          Empty table data
        </DataTableEmpty>
      </DataTable>
    </div>
}
```

### Default

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableHead } from '@ovhcloud/ods-react';
import { useMemo } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30,
      email: 'john.doe@example.com',
      role: 'Admin',
      uuid: '5ae49b94-9ceb-4612-a087-4079a812bb0b'
    }, {
      firstName: 'Jane',
      lastName: 'Smith',
      age: 25,
      email: 'jane.smith@example.com',
      role: 'User',
      uuid: 'fb1c391c-bd88-4b96-ba39-8ab2a95d50bd'
    }, {
      firstName: 'Bob',
      lastName: 'Johnson',
      age: 35,
      email: 'bob.johnson@example.com',
      role: 'Manager',
      uuid: 'a83a58a6-a007-47f0-b04b-83989e502171'
    }], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    return <DataTable columns={sampleColumns} data={sampleData}>
        <DataTableHead />

        <DataTableBody />
      </DataTable>;
  }
}
```

### Demo

```tsx
{
  argTypes: orderControls({
    enableMultiRowSelection: {
      table: {
        category: CONTROL_CATEGORY.general
      },
      control: 'boolean'
    },
    enableRowSelection: {
      table: {
        category: CONTROL_CATEGORY.general
      },
      control: 'boolean'
    },
    enableSorting: {
      table: {
        category: CONTROL_CATEGORY.general
      },
      control: 'boolean'
    },
    loading: {
      table: {
        category: CONTROL_CATEGORY.general
      },
      control: 'boolean'
    }
  }),
  render: arg => <DataTable {...arg} columns={sampleColumns} data={sampleData}>
      <DataTableHead />

      <DataTableBody />
    </DataTable>
}
```

### Empty

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableEmpty, DataTableHead } from '@ovhcloud/ods-react';
import { useMemo } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    return <DataTable columns={sampleColumns} data={sampleData}>
        <DataTableHead />

        <DataTableBody />

        <DataTableEmpty>
          Empty table data
        </DataTableEmpty>
      </DataTable>;
  }
}
```

### Overview

```tsx
{
  tags: ['!dev'],
  parameters: {
    layout: 'centered'
  },
  render: ({}) => <DataTable columns={sampleColumns} data={sampleData}>
      <DataTableHead />

      <DataTableBody />
    </DataTable>
}
```

### Pagination Example

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableHead, PAGINATION_PER_PAGE, Pagination, TEXT_PRESET, Text } from '@ovhcloud/ods-react';
import { useCallback, useEffect, useMemo, useState } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
    };
    const PAGE_LIMIT = PAGINATION_PER_PAGE.option_10;
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    const [data, setData] = useState<Person[]>(Array(PAGE_LIMIT).fill({}));
    const [page, setPage] = useState(0);
    const [total, setTotal] = useState(0);
    const fetchData = useCallback(async (page: number) => {
      return fetch(`https://dummyjson.com/users?limit=${PAGE_LIMIT}&skip=${PAGE_LIMIT * (page - 1)}&select=firstName,lastName,age,email,role`).then(res => res.json()).then(({
        total,
        users
      }) => ({
        total,
        users
      }));
    }, []);
    useEffect(() => {
      fetchData(page).then(({
        total,
        users
      }) => {
        setData(users);
        setTotal(total);
      });
    }, [page]);
    return <div style={{
      display: 'flex',
      flexDirection: 'column',
      rowGap: '16px',
      alignItems: 'center',
      justifyContent: 'center'
    }}>
        <DataTable columns={sampleColumns} data={data}>
          <Text preset={TEXT_PRESET.caption} as="caption">Paginated Table</Text>

          <DataTableHead />

          <DataTableBody />
        </DataTable>

        <Pagination onPageChange={({
        page
      }) => setPage(page)} page={page} pageSize={PAGE_LIMIT} totalItems={total} />
      </div>;
  }
}
```

### Pinned Columns

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableEmpty, DataTableHead } from '@ovhcloud/ods-react';
import { useMemo } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30,
      email: 'john.doe@example.com',
      role: 'Admin',
      uuid: '5ae49b94-9ceb-4612-a087-4079a812bb0b'
    }, {
      firstName: 'Jane',
      lastName: 'Smith',
      age: 25,
      email: 'jane.smith@example.com',
      role: 'User',
      uuid: 'fb1c391c-bd88-4b96-ba39-8ab2a95d50bd'
    }, {
      firstName: 'Bob',
      lastName: 'Johnson',
      age: 35,
      email: 'bob.johnson@example.com',
      role: 'Manager',
      uuid: 'a83a58a6-a007-47f0-b04b-83989e502171'
    }], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    const pinningState = useMemo(() => ({
      left: ['age'],
      right: ['email']
    }), []);
    return <DataTable columns={sampleColumns} data={sampleData} state={{
      columnPinning: pinningState
    }} style={{
      width: '1200px'
    }}>
        <DataTableHead />

        <DataTableBody />

        <DataTableEmpty>
          Empty table data
        </DataTableEmpty>
      </DataTable>;
  }
}
```

### Sorting Controlled

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableHead, TEXT_PRESET, Text } from '@ovhcloud/ods-react';
import { useMemo, useState } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30,
      email: 'john.doe@domain2.com',
      role: 'Admin',
      uuid: '5ae49b94-9ceb-4612-a087-4079a812bb0b'
    }, {
      firstName: 'Jane',
      lastName: 'Smith',
      age: 25,
      email: 'jane.smith@domain1.com',
      role: 'User',
      uuid: 'fb1c391c-bd88-4b96-ba39-8ab2a95d50bd'
    }, {
      firstName: 'Bob',
      lastName: 'Johnson',
      age: 35,
      email: 'bob.johnson@domain3.com',
      role: 'Manager',
      uuid: 'a83a58a6-a007-47f0-b04b-83989e502171'
    }], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    const [sortingState, setSortingState] = useState<DataTableSortingState>([{
      id: 'role',
      desc: true
    }, {
      id: 'lastName',
      desc: true
    }]);
    return <DataTable columns={sampleColumns} data={sampleData} onSortingChange={setSortingState} state={{
      sorting: sortingState
    }}>
        <Text preset={TEXT_PRESET.caption} as="caption">Controlled sorting</Text>

        <DataTableHead />

        <DataTableBody />
      </DataTable>;
  }
}
```

### Sorting Custom Function

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableHead, TEXT_PRESET, Text } from '@ovhcloud/ods-react';
import { useMemo } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30,
      email: 'john.doe@domain2.com',
      role: 'Admin',
      uuid: '5ae49b94-9ceb-4612-a087-4079a812bb0b'
    }, {
      firstName: 'Jane',
      lastName: 'Smith',
      age: 25,
      email: 'jane.smith@domain1.com',
      role: 'User',
      uuid: 'fb1c391c-bd88-4b96-ba39-8ab2a95d50bd'
    }, {
      firstName: 'Bob',
      lastName: 'Johnson',
      age: 35,
      email: 'bob.johnson@domain3.com',
      role: 'Manager',
      uuid: 'a83a58a6-a007-47f0-b04b-83989e502171'
    }], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email',
      sortingFn: (rowA, rowB, columnId) => {
        const valueA = rowA.getValue<string>(columnId).split('@')[1].split('.')[0];
        const valueB = rowB.getValue<string>(columnId).split('@')[1].split('.')[0];
        return valueA.localeCompare(valueB);
      }
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    return <DataTable columns={sampleColumns} data={sampleData}>
        <Text preset={TEXT_PRESET.caption} as="caption">Email sorted by domain</Text>

        <DataTableHead />

        <DataTableBody />
      </DataTable>;
  }
}
```

### Sorting Disabled Columns

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableHead, TEXT_PRESET, Text } from '@ovhcloud/ods-react';
import { useMemo } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30,
      email: 'john.doe@domain2.com',
      role: 'Admin',
      uuid: '5ae49b94-9ceb-4612-a087-4079a812bb0b'
    }, {
      firstName: 'Jane',
      lastName: 'Smith',
      age: 25,
      email: 'jane.smith@domain1.com',
      role: 'User',
      uuid: 'fb1c391c-bd88-4b96-ba39-8ab2a95d50bd'
    }, {
      firstName: 'Bob',
      lastName: 'Johnson',
      age: 35,
      email: 'bob.johnson@domain3.com',
      role: 'Manager',
      uuid: 'a83a58a6-a007-47f0-b04b-83989e502171'
    }], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName',
      enableSorting: false
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role',
      enableSorting: false
    }], []);
    return <DataTable columns={sampleColumns} data={sampleData}>
        <Text preset={TEXT_PRESET.caption} as="caption">Sort disabled on some columns</Text>

        <DataTableHead />

        <DataTableBody />
      </DataTable>;
  }
}
```

### State Controlled

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableHead, TEXT_PRESET, Text } from '@ovhcloud/ods-react';
import { useMemo, useState } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30,
      email: 'john.doe@domain2.com',
      role: 'Admin',
      uuid: '5ae49b94-9ceb-4612-a087-4079a812bb0b'
    }, {
      firstName: 'Jane',
      lastName: 'Smith',
      age: 25,
      email: 'jane.smith@domain1.com',
      role: 'User',
      uuid: 'fb1c391c-bd88-4b96-ba39-8ab2a95d50bd'
    }, {
      firstName: 'Bob',
      lastName: 'Johnson',
      age: 35,
      email: 'bob.johnson@domain3.com',
      role: 'Manager',
      uuid: 'a83a58a6-a007-47f0-b04b-83989e502171'
    }], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    const [sortingState, setSortingState] = useState([{
      id: 'role',
      desc: true
    }]);
    return <DataTable columns={sampleColumns} data={sampleData} onSortingChange={setSortingState} state={{
      sorting: sortingState
    }}>
        <Text preset={TEXT_PRESET.caption} as="caption">Controlled sorted table</Text>

        <DataTableHead />

        <DataTableBody />
      </DataTable>;
  }
}
```

### Theme Generator

```tsx
{
  parameters: {
    layout: 'fullscreen'
  },
  tags: ['!dev'],
  render: ({}) => <DataTable columns={sampleColumns} data={sampleData}>
      <DataTableHead />

      <DataTableBody />
    </DataTable>
}
```

### Visibility Example

```tsx
{
  globals: {
    imports: `import { DataTable, DataTableBody, DataTableHead, TEXT_PRESET, Text } from '@ovhcloud/ods-react';
import { useMemo, useState } from 'react';`
  },
  parameters: {
    docs: {
      source: {
        ...staticSourceRenderConfig()
      }
    }
  },
  tags: ['!dev'],
  render: ({}) => {
    type Person = {
      firstName: string;
      lastName: string;
      age: number;
      email: string;
      role: string;
      uuid: string;
    };
    const sampleData: Person[] = useMemo(() => [{
      firstName: 'John',
      lastName: 'Doe',
      age: 30,
      email: 'john.doe@domain2.com',
      role: 'Admin',
      uuid: '5ae49b94-9ceb-4612-a087-4079a812bb0b'
    }, {
      firstName: 'Jane',
      lastName: 'Smith',
      age: 25,
      email: 'jane.smith@domain1.com',
      role: 'User',
      uuid: 'fb1c391c-bd88-4b96-ba39-8ab2a95d50bd'
    }, {
      firstName: 'Bob',
      lastName: 'Johnson',
      age: 35,
      email: 'bob.johnson@domain3.com',
      role: 'Manager',
      uuid: 'a83a58a6-a007-47f0-b04b-83989e502171'
    }], []);
    const sampleColumns: DataTableColumnDef<Person>[] = useMemo(() => [{
      id: 'firstName',
      header: 'First Name',
      accessorKey: 'firstName'
    }, {
      id: 'lastName',
      header: 'Last Name',
      accessorKey: 'lastName'
    }, {
      id: 'age',
      header: 'Age',
      accessorKey: 'age'
    }, {
      id: 'email',
      header: 'Email',
      accessorKey: 'email'
    }, {
      id: 'role',
      header: 'Role',
      accessorKey: 'role'
    }], []);
    const visibileColumn = useMemo(() => ({
      age: false
    }), []);
    return <DataTable columns={sampleColumns} data={sampleData} state={{
      columnVisibility: visibileColumn
    }}>
        <Text preset={TEXT_PRESET.caption} as="caption">Age column hidden</Text>

        <DataTableHead />

        <DataTableBody />
      </DataTable>;
  }
}
```