import { Canvas, Meta, Controls } from "@storybook/addon-docs/blocks";

import * as DataTableStories from "./DataTable.stories";

<Meta of={DataTableStories} />

# DataTable

The DataTable component provides a powerful and flexible way to display tabular data with features like sorting, column resizing, row selection, and custom cell rendering. It's built on top of @tanstack/react-table and offers a comprehensive solution for displaying and interacting with structured data.

## Usage

<Canvas of={DataTableStories.Documentation} source={ { code: `
import React, { useState } from "react";
import { DataTable, DataTableColumns, DataTableSorting } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
$selectable?: boolean;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const DataTableExample = () => {
const [selectedRows, setSelectedRows] = useState\<Entry[]\>([]);
const [sorting, setSorting] = useState\<DataTableSorting\>([]);

    return (
        <DataTable
            columns={columns}
            data={data}
            bordered={true}
            stickyHeader={true}
            selectedRows={selectedRows}
            onSelectRow={rows => setSelectedRows(rows)}
            sorting={sorting}
            onSortingChange={setSorting}
        />
    );

};

export default DataTableExample;

` } }
additionalActions={[
{
title: 'Open in GitHub',
onClick: () => {
window.open(
'https://github.com/webiny/webiny-js/blob/feat/new-admin-ui/packages/admin-ui/src/DataTable/DataTable.tsx',
'_blank'
);
},
}
]}
/>

<Controls of={DataTableStories.Documentation} />

```tsx
import React, { useState } from "react";
import { DataTable, DataTableColumns, DataTableSorting } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
  id: string;
  name: string;
  createdBy: string;
  lastModified: string;
  status: string;
  $selectable?: boolean;
}

// Define the columns structure
const columns: DataTableColumns<Entry> = {
  name: {
    header: "Title",
    enableSorting: true
  },
  createdBy: {
    header: "Author"
  },
  lastModified: {
    header: "Last Modified",
    enableSorting: true
  },
  status: {
    header: "Status"
  }
};

// Sample data
const data = [
  {
    id: "entry-1",
    name: "Getting Started Guide",
    createdBy: "John Doe",
    lastModified: "1 hour ago",
    status: "Published"
  },
  {
    id: "entry-2",
    name: "User Documentation",
    createdBy: "Jane Smith",
    lastModified: "3 days ago",
    status: "Draft"
  },
  {
    id: "entry-3",
    name: "API Reference",
    createdBy: "John Doe",
    lastModified: "1 week ago",
    status: "Published"
  }
];

const DataTableExample = () => {
  const [selectedRows, setSelectedRows] = useState<Entry[]>([]);
  const [sorting, setSorting] = useState<DataTableSorting>([]);

  return (
    <DataTable
      columns={columns}
      data={data}
      bordered={true}
      stickyHeader={true}
      selectedRows={selectedRows}
      onSelectRow={rows => setSelectedRows(rows)}
      sorting={sorting}
      onSortingChange={setSorting}
    />
  );
};

export default DataTableExample;
```

## Examples

### Default

<Canvas of={DataTableStories.Default} source={ { code: `

import React from "react";
import { DataTable, DataTableColumns } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const DataTableExample = () => {

    return (
        <DataTable
            columns={columns}
            data={data}
        />
    );

};

export default DataTableExample;

` } } />

### Bordered

<Canvas of={DataTableStories.Bordered} source={ { code: `
import React from "react";
import { DataTable, DataTableColumns } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const BorderedDataTableExample = () => {

    return (
        <DataTable
            columns={columns}
            data={data}
            bordered={true}
        />
    );

};

export default BorderedDataTableExample;

` } } />

### With Sticky Header

<Canvas of={DataTableStories.WithStickyHeader} source={ { code: `
import React from "react";
import { DataTable, DataTableColumns } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const WithStickyHeaderDataTableExample = () => {

    return (
        <DataTable
            columns={columns}
            data={data}
            stickyHeader={true}
        />
    );

};

export default WithStickyHeaderDataTableExample;

` } } />

### With Selectable Rows

<Canvas of={DataTableStories.WithSelectableRows} source={ { code: `
import React, { useState } from "react";
import { DataTable, DataTableColumns, DataTableSorting } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
$selectable?: boolean;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const WithSelectableRowsDataTableExample = () => {
const [selectedRows, setSelectedRows] = useState\<Entry[]\>([]);
const [sorting, setSorting] = useState\<DataTableSorting\>([]);

    return (
        <DataTable
            columns={columns}
            data={data}
            selectedRows={selectedRows}
            onSelectRow={rows => setSelectedRows(rows)}
        />
    );

};

export default WithSelectableRowsDataTableExample;
` } } />

### With Loading State

To demonstrate the loading state, we will simulate a 5 seconds delay before the data is loaded.

<Canvas of={DataTableStories.WithLoading} source={ { code: `

import React, { useEffect, useState } from "react";
import { DataTable, DataTableColumns } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data: Entry[] = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const WithLoadingDataTableExample = () => {
const [data, setData] = useState\<Entry[]\>([]);
const [loading, setLoading] = useState(true);

    useEffect(() => {
        const timer = setTimeout(() => {
            setData(data);
            setLoading(false);
        }, 5000); // simulate 5 seconds delay

        return () => clearTimeout(timer);
    }, []);

    return (
        <DataTable
            columns={columns}
            data={data}
            loading={loading}
        />
    );

};

export default WithLoadingDataTableExample;

` } } />

### With Custom Cell Renderer

<Canvas of={DataTableStories.WithCustomCellRenderer} source={ { code: `

import React, { useEffect, useState } from "react";
import { DataTable, DataTableColumns, Avatar, Text } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data: Entry[] = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const WithCustomCellRendererDataTableExample = () => {
return (

<DataTable
  columns={{
    ...columns,
    name: {
      ...columns.name,
      cell: entry => {
        return (
          <div className={"flex items-center gap-sm-extra"}>
            <Avatar
              image={<Avatar.Image src="https://github.com/webiny-bot.png" alt="@webiny" />}
              fallback={<Avatar.Fallback>{entry.name.charAt(0)}</Avatar.Fallback>}
              size={"xl"}
            />
            <div>
              <Text className={"text-neutral-primary font-semibold"} as={"div"}>
                {entry.name}
              </Text>
              <Text size={"sm"} className={"text-neutral-strong"} as={"div"}>
                Last updated: {entry.lastModified}
              </Text>
            </div>
          </div>
        );
      }
    }
  }}
  data={data}
/>
); };

export default WithCustomCellRendererDataTableExample;

` } } />

### With Custom Column Size

<Canvas of={DataTableStories.WithCustomColumnSize} source={ { code: `
import React from "react";
import { DataTable, DataTableColumns } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const WithCustomColumnSizeDataTableExample = () => {
return (

<DataTable
  columns={{
    ...columns,
    name: {
      ...columns.name,
      size: 200
    }
  }}
  data={data}
/>
); };

export default WithCustomColumnSize;
` } } />

### With Custom Column Class Name

<Canvas of={DataTableStories.WithCustomColumnClassName} source={ { code: `
import React from "react";
import { DataTable, DataTableColumns } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns\<Entry\> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const WithCustomColumnClassNameDataTableExample = () => {

    return (
        <DataTable
            columns={{
                ...columns,
                lastModified: {
                    ...columns.lastModified,
                    className: "bg-primary-subtle"
                },
                status: {
                    ...columns.status,
                    className: "text-right"
                }
            }}
            data={data}
        />
    );

};

export default WithCustomColumnClassNameDataTableExample;
` } } />

### With Sorting

> ⚠️ Webiny’s DataTable component doesn’t perform sorting for you.
> It only provides UI state (like sort indicators, sort direction, column clicked).
> You need to sort the data manually based on the sorting state.

<Canvas of={DataTableStories.WithSorting} source={ { code: `

import React, { useState } from "react";
import { DataTable, DataTableColumns, DataTableSorting } from "@webiny/admin-ui";

// Define the data structure
interface Entry {
id: string;
name: string;
createdBy: string;
lastModified: string;
status: string;
}

// Define the columns structure
const columns: DataTableColumns<Entry> = {
name: {
header: "Title",
enableSorting: true
},
createdBy: {
header: "Author"
},
lastModified: {
header: "Last Modified",
enableSorting: true
},
status: {
header: "Status"
}
};

// Sample data
const data: Entry[] = [
{
id: "entry-1",
name: "Getting Started Guide",
createdBy: "John Doe",
lastModified: "1 hour ago",
status: "Published"
},
{
id: "entry-2",
name: "User Documentation",
createdBy: "Jane Smith",
lastModified: "3 days ago",
status: "Draft"
},
{
id: "entry-3",
name: "API Reference",
createdBy: "John Doe",
lastModified: "1 week ago",
status: "Published"
}
];

const WithSortingDataTableExample = () => {
const [sorting, setSorting] = useState<DataTableSorting>([
{
id: "lastModified",
desc: true
}
]);

    return (
        <DataTable
            columns={columns}
            data={data}
            sorting={sorting}
            onSortingChange={setSorting}
        />
    );

};

export default WithSortingDataTableExample;
` } } />
