# Data grid

Presents data in a two-dimensional DataGrid format, arranged in columns and rows in a rectangular form.

## Best practices

### Do

- Use a hyphen (-) for any empty values.
- Left-align textual data within DataGrid cells.
- Left-align categorical numeric data within DataGrid cells.
- Use the cell link variant instead of the cell text variant to help users distinguish links from other text content in adjoining cells.
- Use a subtle badge with a status icon instead of an outline badge.
- Consider a sticky header when a DataGrid has more than 20 items per page.
- Consider a sticky header when values may be ambiguous without column headers.
- Consider a sticky header when users need to act on resources upon selection.
- Consider a sticky header when a DataGrid has more than five columns or sortable columns.

### Don't

- Allow text to wrap to more than three rows.
- Leave too much white space after cell content.
- Use a sticky header in DataGrids without actions in the header.
- Use a sticky header for continuous scrolling.
- Place interactive elements inside DataGrid header cells.

## Behavior and states

- DataGrids don’t require reflow by default, but designers can set column priorities for smaller screens.
- Less critical columns may be hidden first; essential ones should always remain visible.
- If all columns are important, keep them all and allow horizontal scrolling instead.

## Default

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-datagrid--default.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

export const Default = () => {
    type Item = {
        file: {
            label: string;
            icon: React.JSX.Element;
        };
        author: {
            label: string;
            status: PresenceBadgeStatus;
        };
        lastUpdated: {
            label: string;
            timestamp: number;
        };
        lastUpdate: {
            label: string;
            icon: React.JSX.Element;
        };
    };
    const items: Item[] = [
        {
            file: { label: 'Meeting notes', icon: <DocumentRegular /> },
            author: { label: 'Max Mustermann', status: 'available' },
            lastUpdated: { label: '7h ago', timestamp: 1 },
            lastUpdate: { label: 'You edited this', icon: <EditRegular /> },
        },
        {
            file: { label: 'Thursday presentation', icon: <FolderRegular /> },
            author: { label: 'Erika Mustermann', status: 'busy' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Training recording', icon: <VideoRegular /> },
            author: { label: 'John Doe', status: 'away' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
            author: { label: 'Jane Doe', status: 'offline' },
            lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
            lastUpdate: { label: 'You shared this in a Teams chat', icon: <PeopleRegular /> },
        },
    ];
    const columns: TableColumnDefinition<Item>[] = [
        createTableColumn<Item>({
            columnId: 'file',
            compare: (first, second) => first.file.label.localeCompare(second.file.label),
            renderHeaderCell: () => 'File',
            renderCell: (item) => (<TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'author',
            compare: (first, second) => first.author.label.localeCompare(second.author.label),
            renderHeaderCell: () => 'Author',
            renderCell: (item) => (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
            {item.author.label}
          </TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdated',
            compare: (first, second) => first.lastUpdated.timestamp - second.lastUpdated.timestamp,
            renderHeaderCell: () => 'Last updated',
            renderCell: (item) => item.lastUpdated.label,
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdate',
            compare: (first, second) => first.lastUpdate.label.localeCompare(second.lastUpdate.label),
            renderHeaderCell: () => 'Last update',
            renderCell: (item) => (<TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>),
        }),
    ];
    const styles = /* css */ `
      .data-grid-default-example {
        min-width: 550px;
      }
    `;
    return (<>
        <style>{styles}</style>
        <DataGrid className="data-grid-default-example" items={items} columns={columns} sortable selectionMode="multiselect" getRowId={(item) => item.file.label} focusMode="composite">
          <DataGridHeader>
            <DataGridRow selectionCell={{
            checkboxIndicator: { 'aria-label': 'Select all rows' },
        }}>
              {({ renderHeaderCell }) => (<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>)}
            </DataGridRow>
          </DataGridHeader>
          <DataGridBody<Item>>
            {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{
                checkboxIndicator: { 'aria-label': 'Select row' },
            }}>
                {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
              </DataGridRow>)}
          </DataGridBody>
        </DataGrid>
      </>);
};

export default Default;
```

## API

Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. `?` means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.

### DataGrid API

```ts
interface DataGridProps {
  as?: "div" | "table";

  children?: any;

  className?: string;

  /**
   * CSS-only per-column flexbox overrides, keyed by `columnId` (same convention as
   * `columnSizingOptions`). Automatically picked up by this package's `DataGridHeaderCell`
   * and `DataGridCell` wrappers — no need to read `columnId` off the render prop yourself.
   *
   * Intended for static/non-resizable layouts. Not supported in combination with
   * `resizableColumns` — that takes precedence when both are set.
   */
  columnFlexOptions?: DataGridColumnFlexOptions;

  /**
   * Table columns
   */
  columns: TableColumnDefinition<any>[];

  /**
   * Options for column resizing, specific for each column
   */
  columnSizingOptions?: TableColumnSizingOptions;

  /**
   * For column resizing. Allows for a container size to be adjusted by a number of pixels, to make
   * sure the columns don't overflow the table.
   * By default, this value is calculated internally based on other props, but can be overriden.
   */
  containerWidthOffset?: number;

  /**
   * Used in uncontrolled mode to set initial selected items on mount
   */
  defaultSelectedItems?: Iterable<SelectionItemId>;

  /**
   * Used in uncontrolled mode to set initial sort column and direction on mount
   */
  defaultSortState?: SortState;

  /**
   * How focus navigation will work in the datagrid
   * @default cell
   */
  focusMode?: "none" | "cell" | "row_unstable" | "composite";

  getRowId?: ((item: any) => TableRowId);

  items: any[];

  /**
   * Render all table elements as divs instead of semantic table elements
   * Using divs no longer uses `display: table` layout but `display: flex`
   * @default false
   */
  noNativeElements?: boolean;

  /**
   * A callback triggered when a column is resized.
   */
  onColumnResize?: ((e: MouseEvent | TouchEvent | KeyboardEvent, data: { columnId: TableColumnId; width: number; }) => void);

  onSelectionChange?: ((e: MouseEvent<Element, MouseEvent> | KeyboardEvent<Element>, data: OnSelectionChangeData) => void);

  onSortChange?: ((e: MouseEvent<Element, MouseEvent>, sortState: SortState) => void);

  ref?: Ref<HTMLDivElement>;

  /**
   * Enables column resizing
   */
  resizableColumns?: boolean;

  /**
   * Custom options for column resizing.
   */
  resizableColumnsOptions?: { autoFitColumns?: boolean; };

  /**
   * Used to control selected items
   */
  selectedItems?: Iterable<SelectionItemId>;

  /**
   * Row appearance when selected
   * @default brand
   */
  selectionAppearance?: "none" | "brand" | "neutral";

  /**
   * Enables row selection and sets the selection mode
   * @default false
   */
  selectionMode?: "multiselect" | "single";

  /**
   * Affects the sizes of all table subcomponents
   * @default medium
   */
  size?: "small" | "medium" | "extra-small";

  /**
   * Whether the table is sortable
   * @default false
   */
  sortable?: boolean;

  /**
   * Used to control sorting
   */
  sortState?: SortState;

  style?: CSSProperties;

  /**
   * Enables subtle selection style
   * @default false
   */
  subtleSelection?: boolean;
}
```

### DataGridBody API

DataGridBody component

```ts
interface DataGridBodyProps {
  as?: "div" | "tbody";

  /**
   * Render function for rows
   */
  children: RowRenderFunction<unknown>;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### DataGridCell API

```ts
interface DataGridCellProps {
  as?: "div" | "td";

  children?: any;

  className?: string;

  /**
   * Used when there are nested focusble elements inside a focusable cell
   * - `group`: Enter keypress moves focus inside the cell, focus is trapped inside the cell until Escape keypress
   * - `cell`: The cell is focusable - if there are focusable elements in the cell use `group`
   * - `none`: The cell is not focusable
   * @default cell
   */
  focusMode?: "none" | "cell" | "group";

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### DataGridHeader API

DataGridHeader component

```ts
interface DataGridHeaderProps {
  as?: "div" | "thead";

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### DataGridHeaderCell API

```ts
interface DataGridHeaderCellProps {
  as?: "div" | "th";

  /**
   * aside content for anything that should be after main content of the table header cell
   */
  aside?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * Button handles correct narration and interactions for sorting;
   */
  button?: NonNullable<WithSlotShorthandValue<ARIAButtonSlotProps> | null>;

  children?: any;

  className?: string;

  /**
   * Used when there are nested focusble elements inside a focusable cell
   * - `group`: Enter keypress moves focus inside the cell, focus is trapped inside the cell until Escape keypress
   * - `cell`: The cell is focusable - if there are focusable elements in the cell use `group`
   * - `none`: The cell is not focusable
   * @default cell
   */
  focusMode?: "none" | "cell" | "group";

  ref?: Ref<HTMLDivElement>;

  /**
   * @default undefined
   */
  sortDirection?: "ascending" | "descending";

  sortIcon?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  style?: CSSProperties;
}
```

### DataGridRow API

DataGridRow component

```ts
interface DataGridRowProps {
  /**
   * A table row can have different variants. These appearances are
   * intended to be used with selection.
   * @default none
   */
  appearance?: "none" | "brand" | "neutral";

  as?: "div" | "tr";

  children: CellRenderFunction<unknown>;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  /**
   * When selection is enabled on the
   */
  selectionCell?: WithSlotShorthandValue<TableSelectionCellProps & RefAttributes<HTMLDivElement>> | null;

  style?: CSSProperties;
}
```

### DataGridSelectionCell API

DataGridSelectionCell component

```ts
interface DataGridSelectionCellProps {
  as?: "div" | "td";

  /**
   * Selection indicator if selection type is checkbox
   */
  checkboxIndicator?: (Omit<ComponentProps<Partial<CheckboxSlots>, "input">, "defaultChecked" | "onChange" | "size" | "checked"> & { checked?: boolean | "mixed"; children?: undefined; defaultChecked?: boolean | "mixed"; labelPosition?: "before" | "after" | undefined; onChange?: ((ev: ChangeEvent<HTMLInputElement>, data: CheckboxOnChangeData) => void) | undefined; shape?: "circular" | "square" | undefined; size?: "medium" | "large" | undefined; } & RefAttributes<HTMLInputElement>) | null | undefined;

  /**
   * @default false
   */
  checked?: boolean | "mixed";

  children?: any;

  className?: string;

  /**
   * Completely hides the selection cell
   * @deprecated cells should never use hidden, since doing so breaks table structure and screen reader navigation. Use `invisible` instead.
   */
  hidden?: boolean;

  /**
   * Hides the selection cell visually but takes up the same space
   * @default false
   */
  invisible?: boolean;

  /**
   * Selection indicator if selection type is radio
   */
  radioIndicator?: (Omit<ComponentProps<Partial<RadioSlots>, "input">, "onChange" | "size"> & { value?: string; labelPosition?: "below" | "after"; disabled?: boolean | undefined; onChange?: ((ev: ChangeEvent<HTMLInputElement>, data: RadioOnChangeData) => void) | undefined; } & RefAttributes<HTMLInputElement>) | null | undefined;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;

  /**
   * Only visible when checked or the parent row is hovered/focused
   * @default false
   */
  subtle?: boolean;

  /**
   * A table can have two kinds of selection modes.
   * @default checkbox
   */
  type?: "checkbox" | "radio";
}
```

## Implementation

CoreAI 0.12.0; Fluent 9.74.9.

[Setup and dependencies](/coreai-design-system/guides/Package.md).

Import components from `@coreai-ds/react-components`. CoreAI guidance above takes precedence over API demonstration examples.

## Composite Navigation

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-datagrid--composite-navigation.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";
import * as React from 'react';

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const CompositeNavigation = (): JSXElement => {
    return (<DataGrid selectionMode="multiselect" items={items} columns={columns} focusMode="composite" style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default CompositeNavigation;
```

## Custom Row Id

Source: Fluent, adapted for CoreAI.

By default row Ids are the index of the item in the collection. In order to use a row Id based on the data
use the `getRowId` prop.

[Download source](/coreai-design-system/source/examples/components-datagrid--custom-row-id.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { TableRowId } from "@coreai-ds/react-components";
import type { DataGridProps } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import { Checkbox } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import type { TableRowData } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const CustomRowId = (): JSXElement => {
    const [selectedRows, setSelectedRows] = React.useState(new Set<TableRowId>(['Thursday presentation']));
    const onSelectionChange: DataGridProps['onSelectionChange'] = (e, data) => {
        setSelectedRows(data.selectedItems);
    };
    return (<>
      <ul>
        {items.map(item => (<li key={item.file.label}>
            <Checkbox label={item.file.label} checked={selectedRows.has(item.file.label)}/>
          </li>))}
      </ul>

      <DataGrid items={items} columns={columns} selectionMode="multiselect" selectedItems={selectedRows} onSelectionChange={onSelectionChange} getRowId={item => item.file.label} style={{ minWidth: '550px' }}>
        <DataGridHeader>
          <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
            {({ renderHeaderCell }: TableColumnDefinition<Item>) => (<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>)}
          </DataGridRow>
        </DataGridHeader>
        <DataGridBody>
          {({ item, rowId }: TableRowData<Item>) => (<DataGridRow key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
              {({ renderCell }: TableColumnDefinition<Item>) => <DataGridCell>{renderCell(item)}</DataGridCell>}
            </DataGridRow>)}
        </DataGridBody>
      </DataGrid>
    </>);
};

export default CustomRowId;
```

## Data Grid Accordion

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-datagrid--data-grid-accordion.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { Accordion } from "@coreai-ds/react-components";
import { AccordionItem } from "@coreai-ds/react-components";
import { AccordionHeader } from "@coreai-ds/react-components";
import { AccordionPanel } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { ArrowDownloadRegular } from "@fluentui/react-icons";

export const DataGridAccordion = () => {
    type Item = {
        file: {
            label: string;
            icon: React.JSX.Element;
        };
        author: {
            label: string;
            status: PresenceBadgeStatus;
        };
        lastUpdated: {
            label: string;
            timestamp: number;
        };
        lastUpdate: {
            label: string;
            icon: React.JSX.Element;
        };
    };
    const items: Item[] = [
        {
            file: { label: 'Meeting notes', icon: <DocumentRegular /> },
            author: { label: 'Max Mustermann', status: 'available' },
            lastUpdated: { label: '7h ago', timestamp: 1 },
            lastUpdate: { label: 'You edited this', icon: <EditRegular /> },
        },
        {
            file: { label: 'Thursday presentation', icon: <FolderRegular /> },
            author: { label: 'Erika Mustermann', status: 'busy' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Training recording', icon: <VideoRegular /> },
            author: { label: 'John Doe', status: 'away' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
            author: { label: 'Jane Doe', status: 'offline' },
            lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
            lastUpdate: { label: 'You shared this in a Teams chat', icon: <PeopleRegular /> },
        },
    ];
    const columns: TableColumnDefinition<Item>[] = [
        createTableColumn<Item>({
            columnId: 'file',
            compare: (first, second) => first.file.label.localeCompare(second.file.label),
            renderHeaderCell: () => 'File',
            renderCell: (item) => (<TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'author',
            compare: (first, second) => first.author.label.localeCompare(second.author.label),
            renderHeaderCell: () => 'Author',
            renderCell: (item) => (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
            {item.author.label}
          </TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdated',
            compare: (first, second) => first.lastUpdated.timestamp - second.lastUpdated.timestamp,
            renderHeaderCell: () => 'Last updated',
            renderCell: (item) => item.lastUpdated.label,
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdate',
            compare: (first, second) => first.lastUpdate.label.localeCompare(second.lastUpdate.label),
            renderHeaderCell: () => 'Last update',
            renderCell: (item) => (<TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>),
        }),
    ];
    const styles = /* css */ `
      .data-grid-accordion-example {
        background-color: var(--colorNeutralBackground1);
        border: var(--strokeWidthThin) solid var(--colorNeutralStroke2);
        border-radius: var(--borderRadiusXLarge);
        display: flex;
        flex-direction: column;
        overflow: hidden;
      }
      .data-grid-accordion-example__header-button.fui-AccordionHeader__button {
        padding-left: var(--spacingHorizontalM);
        padding-right: var(--spacingHorizontalM);
      }
      .data-grid-accordion-example__panel {
        margin: 0;
      }
      .data-grid-accordion-example__grid {
        border-left-width: 0;
        border-radius: 0;
        border-right-width: 0;
      }
      .data-grid-accordion-example__footer {
        align-items: center;
        column-gap: var(--spacingHorizontalM);
        display: flex;
        justify-content: space-between;
        padding: var(--spacingVerticalS) var(--spacingHorizontalM);
      }
    `;
    return (<>
        <style>{styles}</style>
        <Accordion className="data-grid-accordion-example" collapsible defaultOpenItems="files">
          <AccordionItem value="files">
            <AccordionHeader button={{ className: 'data-grid-accordion-example__header-button' }}>
              Shared documents
            </AccordionHeader>
            <AccordionPanel className="data-grid-accordion-example__panel">
              <DataGrid className="data-grid-accordion-example__grid" items={items} columns={columns} sortable selectionMode="multiselect" getRowId={(item) => item.file.label} focusMode="composite">
                <DataGridHeader>
                  <DataGridRow selectionCell={{
            checkboxIndicator: { 'aria-label': 'Select all rows' },
        }}>
                    {({ renderHeaderCell }) => (<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>)}
                  </DataGridRow>
                </DataGridHeader>
                <DataGridBody<Item>>
                  {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{
                checkboxIndicator: { 'aria-label': 'Select row' },
            }}>
                      {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
                    </DataGridRow>)}
                </DataGridBody>
              </DataGrid>

              <div className="data-grid-accordion-example__footer">
                <Text preset="bodyStrong">Showing 4 of 128 items</Text>
                <Button appearance="transparent" icon={<ArrowDownloadRegular />}>
                  Export all
                </Button>
              </div>
            </AccordionPanel>
          </AccordionItem>
        </Accordion>
      </>);
};

export default DataGridAccordion;
```

## Data Grid Card

Source: CoreAI.

[Download source](/coreai-design-system/source/examples/components-datagrid--data-grid-card.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { ArrowDownloadRegular } from "@fluentui/react-icons";

export const DataGridCard = () => {
    type Item = {
        file: {
            label: string;
            icon: React.JSX.Element;
        };
        author: {
            label: string;
            status: PresenceBadgeStatus;
        };
        lastUpdated: {
            label: string;
            timestamp: number;
        };
        lastUpdate: {
            label: string;
            icon: React.JSX.Element;
        };
    };
    const items: Item[] = [
        {
            file: { label: 'Meeting notes', icon: <DocumentRegular /> },
            author: { label: 'Max Mustermann', status: 'available' },
            lastUpdated: { label: '7h ago', timestamp: 1 },
            lastUpdate: { label: 'You edited this', icon: <EditRegular /> },
        },
        {
            file: { label: 'Thursday presentation', icon: <FolderRegular /> },
            author: { label: 'Erika Mustermann', status: 'busy' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Training recording', icon: <VideoRegular /> },
            author: { label: 'John Doe', status: 'away' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
            author: { label: 'Jane Doe', status: 'offline' },
            lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
            lastUpdate: { label: 'You shared this in a Teams chat', icon: <PeopleRegular /> },
        },
    ];
    const columns: TableColumnDefinition<Item>[] = [
        createTableColumn<Item>({
            columnId: 'file',
            compare: (first, second) => first.file.label.localeCompare(second.file.label),
            renderHeaderCell: () => 'File',
            renderCell: (item) => (<TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'author',
            compare: (first, second) => first.author.label.localeCompare(second.author.label),
            renderHeaderCell: () => 'Author',
            renderCell: (item) => (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
            {item.author.label}
          </TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdated',
            compare: (first, second) => first.lastUpdated.timestamp - second.lastUpdated.timestamp,
            renderHeaderCell: () => 'Last updated',
            renderCell: (item) => item.lastUpdated.label,
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdate',
            compare: (first, second) => first.lastUpdate.label.localeCompare(second.lastUpdate.label),
            renderHeaderCell: () => 'Last update',
            renderCell: (item) => (<TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>),
        }),
    ];
    const styles = /* css */ `
      .data-grid-card-example {
        background-color: var(--colorNeutralBackground1);
        border: var(--strokeWidthThin) solid var(--colorNeutralStroke2);
        border-radius: var(--borderRadiusXLarge);
        display: flex;
        flex-direction: column;
        overflow: hidden;
      }
      .data-grid-card-example__header {
        display: flex;
        flex-direction: column;
        padding: var(--spacingVerticalM) var(--spacingHorizontalM);
        row-gap: var(--spacingVerticalXXS);
      }
      .data-grid-card-example__grid {
        border-left-width: 0;
        border-radius: 0;
        border-right-width: 0;
      }
      .data-grid-card-example__footer {
        align-items: center;
        column-gap: var(--spacingHorizontalM);
        display: flex;
        justify-content: space-between;
        padding: var(--spacingVerticalS) var(--spacingHorizontalM);
      }
    `;
    return (<>
        <style>{styles}</style>
        <div className="data-grid-card-example">
          <div className="data-grid-card-example__header">
            <Text preset="heading4">Shared documents</Text>
            <Text preset="bodyS">4 files · Updated 7h ago</Text>
          </div>

          <DataGrid className="data-grid-card-example__grid" items={items} columns={columns} sortable selectionMode="multiselect" getRowId={(item) => item.file.label} focusMode="composite">
            <DataGridHeader>
              <DataGridRow selectionCell={{
            checkboxIndicator: { 'aria-label': 'Select all rows' },
        }}>
                {({ renderHeaderCell }) => (<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>)}
              </DataGridRow>
            </DataGridHeader>
            <DataGridBody<Item>>
              {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{
                checkboxIndicator: { 'aria-label': 'Select row' },
            }}>
                  {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
                </DataGridRow>)}
            </DataGridBody>
          </DataGrid>

          <div className="data-grid-card-example__footer">
            <Text preset="bodyStrong">Showing 4 of 128 items</Text>
            <Button appearance="transparent" icon={<ArrowDownloadRegular />}>
              Export all
            </Button>
          </div>
        </div>
      </>);
};

export default DataGridCard;
```

## Flex Options

Source: CoreAI.

CoreAI-only: `columnFlexOptions` is a CSS-only, non-interactive alternative to
`resizableColumns` for static layouts. Give each column a `flexGrow`/`flexShrink`/
`flexBasis`/`minWidth`/`maxWidth` override (keyed by `columnId`, same convention as
`columnSizingOptions`) and the `DataGridHeaderCell`/`DataGridCell` wrappers apply it
automatically - no need to read `columnId` off the render prop yourself.

[Download source](/coreai-design-system/source/examples/components-datagrid--flex-options.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

export const FlexOptions = () => {
    type Item = {
        file: {
            label: string;
            icon: React.JSX.Element;
        };
        author: {
            label: string;
            status: PresenceBadgeStatus;
        };
        lastUpdated: {
            label: string;
            timestamp: number;
        };
        lastUpdate: {
            label: string;
            icon: React.JSX.Element;
        };
    };
    const items: Item[] = [
        {
            file: { label: 'Meeting notes', icon: <DocumentRegular /> },
            author: { label: 'Max Mustermann', status: 'available' },
            lastUpdated: { label: '7h ago', timestamp: 1 },
            lastUpdate: { label: 'You edited this', icon: <EditRegular /> },
        },
        {
            file: { label: 'Thursday presentation', icon: <FolderRegular /> },
            author: { label: 'Erika Mustermann', status: 'busy' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Training recording', icon: <VideoRegular /> },
            author: { label: 'John Doe', status: 'away' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
            author: { label: 'Jane Doe', status: 'offline' },
            lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
            lastUpdate: { label: 'You shared this in a Teams chat', icon: <PeopleRegular /> },
        },
    ];
    const columns: TableColumnDefinition<Item>[] = [
        createTableColumn<Item>({
            columnId: 'file',
            compare: (first, second) => first.file.label.localeCompare(second.file.label),
            renderHeaderCell: () => 'File',
            renderCell: (item) => (<TableCellLayout truncate media={item.file.icon}>
            {item.file.label}
          </TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'author',
            compare: (first, second) => first.author.label.localeCompare(second.author.label),
            renderHeaderCell: () => 'Author',
            renderCell: (item) => (<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>),
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdated',
            compare: (first, second) => first.lastUpdated.timestamp - second.lastUpdated.timestamp,
            renderHeaderCell: () => 'Last updated',
            renderCell: (item) => <TableCellLayout truncate>{item.lastUpdated.label}</TableCellLayout>,
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdate',
            compare: (first, second) => first.lastUpdate.label.localeCompare(second.lastUpdate.label),
            renderHeaderCell: () => 'Last update',
            renderCell: (item) => (<TableCellLayout truncate media={item.lastUpdate.icon}>
            {item.lastUpdate.label}
          </TableCellLayout>),
        }),
    ];
    const styles = /* css */ `
      .data-grid-flex-options-example {
        overflow-x: auto;
      }
    `;
    return (<>
        <style>{styles}</style>
        <DataGrid className="data-grid-flex-options-example" items={items} columns={columns} sortable getRowId={(item) => item.file.label} selectionMode="multiselect" columnFlexOptions={{
            file: { flexGrow: 1, flexShrink: 1, flexBasis: 0, minWidth: 0 },
            author: { flexGrow: 0.1, flexShrink: 0, flexBasis: 60 },
            lastUpdated: { flexGrow: 0.6, flexShrink: 1, flexBasis: 0, minWidth: '20ch' },
            lastUpdate: { flexGrow: 1, flexShrink: 1, flexBasis: 0, minWidth: 180 },
        }}>
          <DataGridHeader>
            <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
              {({ renderHeaderCell }) => (<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>)}
            </DataGridRow>
          </DataGridHeader>
          <DataGridBody<Item>>
            {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
                {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
              </DataGridRow>)}
          </DataGridBody>
        </DataGrid>
      </>);
};

export default FlexOptions;
```

## Focusable Elements In Cells

Source: Fluent, adapted for CoreAI.

When cells contain focusable elements, set the `focusMode` prop on the `DataGridCell` or `DataGridHeaderCell` components.

Use `group` when there are multiple focusable elements in cell,
`group` will enable the following behaviour:
- Enter will move focus into the cell
- Focus is trapped in the cell
- Escape will move focus back to the cell

Use `none` when there is one single focusable element in cell,
`none` will make the cell non-focusable.

Do not add nested focusable elements to a sortable `DataGridHeaderCell`, since they will be rendered within the sort button.

[Download source](/coreai-design-system/source/examples/components-datagrid--focusable-elements-in-cells.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { EditRegular } from "@fluentui/react-icons";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { MoreHorizontalRegular } from "@fluentui/react-icons";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { OpenRegular } from "@fluentui/react-icons";
import { DeleteRegular } from "@fluentui/react-icons";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";
import type { TableColumnId } from "@coreai-ds/react-components";
import type { DataGridCellFocusMode } from "@coreai-ds/react-components";
import * as React from 'react';

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        renderHeaderCell: () => {
            return (<>
          Author
          <Button appearance="transparent" aria-label="Edit" icon={<EditRegular />}/>
          <Menu positioning={{ autoSize: true }}>
            <MenuTrigger disableButtonEnhancement>
              <Button appearance="transparent" icon={<MoreHorizontalRegular />} aria-label="More options"/>
            </MenuTrigger>

            <MenuPopover>
              <MenuList>
                <MenuItem>Delete column</MenuItem>
                <MenuItem>Create new author</MenuItem>
              </MenuList>
            </MenuPopover>
          </Menu>
        </>);
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'singleAction',
        renderHeaderCell: () => {
            return 'Single action';
        },
        renderCell: () => {
            return <Button icon={<OpenRegular />}>Open</Button>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'actions',
        renderHeaderCell: () => {
            return 'Actions';
        },
        renderCell: () => {
            return (<>
          <Button aria-label="Edit" icon={<EditRegular />}/>
          <Button aria-label="Delete" icon={<DeleteRegular />}/>
        </>);
        },
    }),
];

const getCellFocusMode = (columnId: TableColumnId): DataGridCellFocusMode => {
    switch (columnId) {
        case 'singleAction':
            return 'none';
        case 'actions':
            return 'group';
        default:
            return 'cell';
    }
};

export const FocusableElementsInCells = (): JSXElement => {
    return (<DataGrid items={items} columns={columns} sortable selectionMode="multiselect" getRowId={item => item.file.label} onSelectionChange={(e, data) => console.log(data)} style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
          {({ columnId, renderHeaderCell }) => (<DataGridHeaderCell focusMode={columnId === 'author' ? 'group' : undefined}>
              {renderHeaderCell()}
            </DataGridHeaderCell>)}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell, columnId }) => (<DataGridCell focusMode={getCellFocusMode(columnId)}>{renderCell(item)}</DataGridCell>)}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default FocusableElementsInCells;
```

## Multiple Select

Source: Fluent, adapted for CoreAI.

In order to enable this feature the `selectionMode` prop needs to be set. The API surface is directly
equivalent to the usage of `useTableFeatures`.

[Download source](/coreai-design-system/source/examples/components-datagrid--multiple-select.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const MultipleSelect = (): JSXElement => {
    const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
    return (<DataGrid items={items} columns={columns} selectionMode="multiselect" defaultSelectedItems={defaultSelectedItems} style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default MultipleSelect;
```

## Multiple Select Controlled

Source: Fluent, adapted for CoreAI.

To enable selection, the `selectionMode` prop needs to be set. The API surface is directly
equivalent to the usage of `useTableFeatures`.

[Download source](/coreai-design-system/source/examples/components-datagrid--multiple-select-controlled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { TableRowId } from "@coreai-ds/react-components";
import type { DataGridProps } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const MultipleSelectControlled = (): JSXElement => {
    const [selectedRows, setSelectedRows] = React.useState(new Set<TableRowId>([1]));
    const onSelectionChange: DataGridProps['onSelectionChange'] = (e, data) => {
        setSelectedRows(data.selectedItems);
    };
    return (<DataGrid items={items} columns={columns} selectionMode="multiselect" selectedItems={selectedRows} onSelectionChange={onSelectionChange} style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default MultipleSelectControlled;
```

## Resizable Columns (preview)

Source: Fluent, adapted for CoreAI.

Columns can be made resizable by passing a prop `resizableColumns`. The resizing configuration for each 
column (like `minWidth` and `defaultWidth`), can be further customized by passing down a 
`columnSizingOptions` prop.

The control over the state of resizing can be achieved with the combination of `onColumnResize` callback 
and setting the `idealWidth` for a column in `columnSizingOptions`.

For accessibility, the `DataGrid` component supports keyboard navigation and screen reader navigation
To make features like column resizing work with keyboard navigation, the `Menu` component is used to provide
 a context menu for the header cells, which allows the user to access other DataGrid features.

Once an option is selected, the arrows keys can be used to interact with the `DataGrid` (e.g. resize columns).
`ESC`, `ENTER`, or `SPACE` can be used to return to the original navigation mode.

[Download source](/coreai-design-system/source/examples/components-datagrid--resizable-columns.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return (<TableCellLayout truncate media={item.file.icon}>
          {item.file.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout truncate media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return <TableCellLayout truncate>{item.lastUpdated.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return (<TableCellLayout truncate media={item.lastUpdate.icon}>
          {item.lastUpdate.label}
        </TableCellLayout>);
        },
    }),
];

const columnSizingOptions = {
    file: {
        minWidth: 80,
        defaultWidth: 120,
    },
    author: {
        defaultWidth: 180,
        minWidth: 120,
        idealWidth: 180,
    },
};

export const ResizableColumns = (): JSXElement => {
    const refMap = React.useRef<Record<string, HTMLElement | null>>({});
    return (<div style={{ overflowX: 'auto' }}>
      <DataGrid items={items} columns={columns} sortable getRowId={item => item.file.label} selectionMode="multiselect" resizableColumns columnSizingOptions={columnSizingOptions}>
        <DataGridHeader>
          <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
            {({ renderHeaderCell, columnId }, dataGrid) => dataGrid.resizableColumns ? (<Menu openOnContext>
                  <MenuTrigger>
                    <DataGridHeaderCell ref={el => {
                refMap.current[columnId] = el;
            }}>
                      {renderHeaderCell()}
                    </DataGridHeaderCell>
                  </MenuTrigger>
                  <MenuPopover>
                    <MenuList>
                      <MenuItem onClick={dataGrid.columnSizing_unstable.enableKeyboardMode(columnId)}>
                        Keyboard Column Resizing
                      </MenuItem>
                    </MenuList>
                  </MenuPopover>
                </Menu>) : (<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>)}
          </DataGridRow>
        </DataGridHeader>
        <DataGridBody<Item>>
          {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
              {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
            </DataGridRow>)}
        </DataGridBody>
      </DataGrid>
    </div>);
};

export default ResizableColumns;
```

## Resizable Columns Controlled

Source: CoreAI.

`resizableColumns` turns each column boundary into a drag handle. This story shows the
*controlled* pattern: widths live in your own state and `onColumnResize` writes them
back, so they survive re-renders. See **Resizable Columns** for the uncontrolled
default, where the grid auto-fits columns to the container.

Combine `columnSizingOptions` (per-column `minWidth`/`defaultWidth`/`idealWidth`) with
`onColumnResize`, and with `resizableColumnsOptions={{ autoFitColumns: false }}` to let
the grid overflow its container instead of squeezing columns — that also keeps a handle
on the last column.

Wrap the grid in a horizontally scrollable container so the overflow is reachable.
Resizing also works from the keyboard: open the header cell's context menu, choose
**Keyboard Column Resizing**, then use <kbd>←</kbd>/<kbd>→</kbd> (hold <kbd>Shift</kbd>
for finer steps) and <kbd>Enter</kbd>/<kbd>Esc</kbd> to exit.

`resizableColumns` and `columnFlexOptions` are mutually exclusive — see the Flex Options story.

[Download source](/coreai-design-system/source/examples/components-datagrid--resizable-columns-controlled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import * as React from 'react';
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import type { TableColumnSizingOptions } from "@coreai-ds/react-components";
import type { DataGridProps } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

export const ResizableColumnsControlled = () => {
    type Item = {
        file: {
            label: string;
            icon: React.JSX.Element;
        };
        author: {
            label: string;
            status: PresenceBadgeStatus;
        };
        lastUpdated: {
            label: string;
            timestamp: number;
        };
        lastUpdate: {
            label: string;
            icon: React.JSX.Element;
        };
    };
    const items: Item[] = [
        {
            file: { label: 'Meeting notes', icon: <DocumentRegular /> },
            author: { label: 'Max Mustermann', status: 'available' },
            lastUpdated: { label: '7h ago', timestamp: 1 },
            lastUpdate: { label: 'You edited this', icon: <EditRegular /> },
        },
        {
            file: { label: 'Thursday presentation', icon: <FolderRegular /> },
            author: { label: 'Erika Mustermann', status: 'busy' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Training recording', icon: <VideoRegular /> },
            author: { label: 'John Doe', status: 'away' },
            lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
            lastUpdate: { label: 'You recently opened this', icon: <OpenRegular /> },
        },
        {
            file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
            author: { label: 'Jane Doe', status: 'offline' },
            lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
            lastUpdate: { label: 'You shared this in a Teams chat', icon: <PeopleRegular /> },
        },
    ];
    const columns: TableColumnDefinition<Item>[] = [
        createTableColumn<Item>({
            columnId: 'file',
            compare: (first, second) => first.file.label.localeCompare(second.file.label),
            renderHeaderCell: () => 'File',
            renderCell: (item) => (<TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'author',
            compare: (first, second) => first.author.label.localeCompare(second.author.label),
            renderHeaderCell: () => 'Author',
            renderCell: (item) => (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
            {item.author.label}
          </TableCellLayout>),
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdated',
            compare: (first, second) => first.lastUpdated.timestamp - second.lastUpdated.timestamp,
            renderHeaderCell: () => 'Last updated',
            renderCell: (item) => item.lastUpdated.label,
        }),
        createTableColumn<Item>({
            columnId: 'lastUpdate',
            compare: (first, second) => first.lastUpdate.label.localeCompare(second.lastUpdate.label),
            renderHeaderCell: () => 'Last update',
            renderCell: (item) => (<TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>),
        }),
    ];
    const [columnSizing, setColumnSizing] = React.useState<TableColumnSizingOptions>({
        file: { minWidth: 120, defaultWidth: 240, idealWidth: 240 },
        author: { minWidth: 120, defaultWidth: 200, idealWidth: 200 },
        lastUpdated: { minWidth: 120, defaultWidth: 180, idealWidth: 180 },
        lastUpdate: { minWidth: 140, defaultWidth: 220, idealWidth: 220 },
    });
    const onColumnResize: DataGridProps['onColumnResize'] = (_event, { columnId, width }) => {
        setColumnSizing((current) => ({
            ...current,
            [columnId]: { ...current[columnId], idealWidth: width, defaultWidth: width },
        }));
    };
    const styles = /* css */ `
      .data-grid-resizable-example {
        overflow-x: auto;
      }
    `;
    return (<>
        <style>{styles}</style>
        <DataGrid className="data-grid-resizable-example" items={items} columns={columns} sortable getRowId={(item) => item.file.label} selectionMode="multiselect" resizableColumns resizableColumnsOptions={{ autoFitColumns: false }} columnSizingOptions={columnSizing} onColumnResize={onColumnResize}>
          <DataGridHeader>
            <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
              {({ renderHeaderCell, columnId }, dataGrid) => (<Menu openOnContext>
                  <MenuTrigger>
                    <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
                  </MenuTrigger>
                  <MenuPopover>
                    <MenuList>
                      <MenuItem onClick={dataGrid.columnSizing_unstable.enableKeyboardMode(columnId)}>
                        Keyboard Column Resizing
                      </MenuItem>
                    </MenuList>
                  </MenuPopover>
                </Menu>)}
            </DataGridRow>
          </DataGridHeader>
          <DataGridBody<Item>>
            {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
                {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
              </DataGridRow>)}
          </DataGridBody>
        </DataGrid>
      </>);
};

export default ResizableColumnsControlled;
```

## Resizable Columns - Disabled container auto-fit

Source: Fluent, adapted for CoreAI.

In the previous example, the columns are automatically fitted to the container. This means that the columns are
squeezed when the container is narrowed, until the
minimum width is reached, and the last column is extended past its optimal width to fill the available
space. This also effectively prevents the user from making the columns wider than the total width of the 
container, as the columns are automatically resized to fit the container.

This behavior can be disabled by passing `resizableColumnsOptions` prop to Datagrid,
with the `{autoFitColumns: false}` option.

With this option, the columns can be made wider than the container, and the container will overflow.
Also, the automatic resizing of adjacent columns will be disabled, as the column are now allowed to be wider
that the container. This also enables the resize handle on the last column.

[Download source](/coreai-design-system/source/examples/components-datagrid--resizable-columns-disable-auto-fit.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return (<TableCellLayout truncate media={item.file.icon}>
          {item.file.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout truncate media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return <TableCellLayout truncate>{item.lastUpdated.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return (<TableCellLayout truncate media={item.lastUpdate.icon}>
          {item.lastUpdate.label}
        </TableCellLayout>);
        },
    }),
];

const columnSizingOptions = {
    file: {
        minWidth: 80,
        defaultWidth: 180,
    },
    author: {
        defaultWidth: 180,
        minWidth: 120,
        idealWidth: 180,
    },
};

export const ResizableColumnsDisableAutoFit = (): JSXElement => {
    const refMap = React.useRef<Record<string, HTMLElement | null>>({});
    return (<div style={{ overflowX: 'auto' }}>
      <DataGrid items={items} columns={columns} sortable getRowId={item => item.file.label} selectionMode="multiselect" resizableColumns columnSizingOptions={columnSizingOptions} resizableColumnsOptions={{
            autoFitColumns: false,
        }}>
        <DataGridHeader>
          <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
            {({ renderHeaderCell, columnId }, dataGrid) => dataGrid.resizableColumns ? (<Menu openOnContext>
                  <MenuTrigger>
                    <DataGridHeaderCell ref={el => {
                refMap.current[columnId] = el;
            }}>
                      {renderHeaderCell()}
                    </DataGridHeaderCell>
                  </MenuTrigger>
                  <MenuPopover>
                    <MenuList>
                      <MenuItem onClick={dataGrid.columnSizing_unstable.enableKeyboardMode(columnId)}>
                        Keyboard Column Resizing
                      </MenuItem>
                    </MenuList>
                  </MenuPopover>
                </Menu>) : (<DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>)}
          </DataGridRow>
        </DataGridHeader>
        <DataGridBody<Item>>
          {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
              {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
            </DataGridRow>)}
        </DataGridBody>
      </DataGrid>
    </div>);
};

export default ResizableColumnsDisableAutoFit;
```

## Selection Appearance

Source: Fluent, adapted for CoreAI.

The `selectionAppearance` prop will vary the appearance of selected rows. The default appearance is a brand
background color. However a neutral (grey) background is also available.

[Download source](/coreai-design-system/source/examples/components-datagrid--selection-appearance.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const SelectionAppearance = (): JSXElement => {
    const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
    return (<DataGrid items={items} columns={columns} selectionMode="multiselect" selectionAppearance="neutral" defaultSelectedItems={defaultSelectedItems} style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default SelectionAppearance;
```

## Single Select

Source: Fluent, adapted for CoreAI.

To enable selection, the `selectionMode` prop needs to be set. The API surface is directly
equivalent to the usage of `useTableFeatures`.

[Download source](/coreai-design-system/source/examples/components-datagrid--single-select.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const SingleSelect = (): JSXElement => {
    const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
    return (<DataGrid items={items} columns={columns} selectionMode="single" defaultSelectedItems={defaultSelectedItems} style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ radioIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default SingleSelect;
```

## Single Select Controlled

Source: Fluent, adapted for CoreAI.

To enable selection, the `selectionMode` prop needs to be set. The API surface is directly
equivalent to the usage of `useTableFeatures`.

[Download source](/coreai-design-system/source/examples/components-datagrid--single-select-controlled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { TableRowId } from "@coreai-ds/react-components";
import type { DataGridProps } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const SingleSelectControlled = (): JSXElement => {
    const [selectedRows, setSelectedRows] = React.useState(new Set<TableRowId>([1]));
    const onSelectionChange: DataGridProps['onSelectionChange'] = (e, data) => {
        setSelectedRows(data.selectedItems);
    };
    return (<DataGrid items={items} columns={columns} selectionMode="single" selectedItems={selectedRows} onSelectionChange={onSelectionChange} style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ radioIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default SingleSelectControlled;
```

## Sort

Source: Fluent, adapted for CoreAI.

To enable sorting, the `sortable` prop needs to be set. 

> ⚠️ Column definitions without a `compare` function will not be sortable.

> Due to screen reader support, the sort status might not be announced once a sortable column header
is invoked. [This is a known issue.](https://github.com/nvaccess/nvda/issues/10890)
However the implementation still follows the
[pattern recommended by the WAI](https://www.w3.org/WAI/ARIA/apg/example-index/table/sortable-table.html)

[Download source](/coreai-design-system/source/examples/components-datagrid--sort.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { DataGridProps } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        renderHeaderCell: () => {
            return 'Not sortable';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const Sort = (): JSXElement => {
    const defaultSortState = React.useMemo<Parameters<NonNullable<DataGridProps['onSortChange']>>[1]>(() => ({ sortColumn: 'file', sortDirection: 'ascending' }), []);
    return (<DataGrid items={items} columns={columns} sortable defaultSortState={defaultSortState} style={{ minWidth: '500px' }}>
      <DataGridHeader>
        <DataGridRow>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default Sort;
```

## Sort Controlled

Source: Fluent, adapted for CoreAI.

To enable sorting, the `sortable` prop needs to be set. The API surface is directly
equivalent to the usage of `useTableFeatures`.

[Download source](/coreai-design-system/source/examples/components-datagrid--sort-controlled.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import type { DataGridProps } from "@coreai-ds/react-components";
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const SortControlled = (): JSXElement => {
    const [sortState, setSortState] = React.useState<Parameters<NonNullable<DataGridProps['onSortChange']>>[1]>({
        sortColumn: 'file',
        sortDirection: 'ascending',
    });
    const onSortChange: DataGridProps['onSortChange'] = (e, nextSortState) => {
        setSortState(nextSortState);
    };
    return (<DataGrid items={items} columns={columns} sortable sortState={sortState} onSortChange={onSortChange} style={{ minWidth: '500px' }}>
      <DataGridHeader>
        <DataGridRow>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default SortControlled;
```

## Subtle Selection

Source: Fluent, adapted for CoreAI.

To enable subtle selection mode, the `subtleSelection` should be set.
The selection indicator slot will only
appear when:
- the `DataGridRow` component is hovered.
- The current focused element is within the `DataGridRow`
- The `DataGridSelectionCell` is checked

[Download source](/coreai-design-system/source/examples/components-datagrid--subtle-selection.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { DataGrid } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { DocumentRegular } from "@fluentui/react-icons";
import { EditRegular } from "@fluentui/react-icons";
import { FolderRegular } from "@fluentui/react-icons";
import { OpenRegular } from "@fluentui/react-icons";
import { VideoRegular } from "@fluentui/react-icons";
import { DocumentPdfRegular } from "@fluentui/react-icons";
import { PeopleRegular } from "@fluentui/react-icons";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { DataGridHeader } from "@coreai-ds/react-components";
import { DataGridRow } from "@coreai-ds/react-components";
import { DataGridHeaderCell } from "@coreai-ds/react-components";
import { DataGridBody } from "@coreai-ds/react-components";
import { DataGridCell } from "@coreai-ds/react-components";

type FileCell = {
    label: string;
    icon: JSXElement;
};

type AuthorCell = {
    label: string;
    status: PresenceBadgeStatus;
};

type LastUpdatedCell = {
    label: string;
    timestamp: number;
};

type LastUpdateCell = {
    label: string;
    icon: JSXElement;
};

type Item = {
    file: FileCell;
    author: AuthorCell;
    lastUpdated: LastUpdatedCell;
    lastUpdate: LastUpdateCell;
};

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 1 },
        lastUpdate: {
            label: 'You edited this',
            icon: <EditRegular />,
        },
    },
    {
        file: { label: 'Thursday presentation', icon: <FolderRegular /> },
        author: { label: 'Erika Mustermann', status: 'busy' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Training recording', icon: <VideoRegular /> },
        author: { label: 'John Doe', status: 'away' },
        lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
        lastUpdate: {
            label: 'You recently opened this',
            icon: <OpenRegular />,
        },
    },
    {
        file: { label: 'Purchase order', icon: <DocumentPdfRegular /> },
        author: { label: 'Jane Doe', status: 'offline' },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
        renderHeaderCell: () => {
            return 'File';
        },
        renderCell: item => {
            return <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>;
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
        renderHeaderCell: () => {
            return 'Author';
        },
        renderCell: item => {
            return (<TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
        renderHeaderCell: () => {
            return 'Last updated';
        },
        renderCell: item => {
            return item.lastUpdated.label;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
        renderHeaderCell: () => {
            return 'Last update';
        },
        renderCell: item => {
            return <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>;
        },
    }),
];

export const SubtleSelection = (): JSXElement => {
    const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
    return (<DataGrid items={items} columns={columns} selectionMode="multiselect" subtleSelection defaultSelectedItems={defaultSelectedItems} style={{ minWidth: '550px' }}>
      <DataGridHeader>
        <DataGridRow selectionCell={{ checkboxIndicator: { 'aria-label': 'Select all rows' } }}>
          {({ renderHeaderCell }) => <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>}
        </DataGridRow>
      </DataGridHeader>
      <DataGridBody<Item>>
        {({ item, rowId }) => (<DataGridRow<Item> key={rowId} selectionCell={{ checkboxIndicator: { 'aria-label': 'Select row' } }}>
            {({ renderCell }) => <DataGridCell>{renderCell(item)}</DataGridCell>}
          </DataGridRow>)}
      </DataGridBody>
    </DataGrid>);
};

export default SubtleSelection;
```

## Virtualization

Source: Fluent, adapted for CoreAI.

Virtualizating the DataGrid component involves recomposing components to use a virtualized container.
This is already done in the extension package `@fluentui-contrib/react-data-grid-react-window` which provides
extended DataGrid components that are powered
by [react-window](https://react-window.vercel.app/#/examples/list/fixed-size).

The example below shows how to use this extension package to virtualize the DataGrid component.

Here some useful links for the package:
- [Storybook documentation](https://microsoft.github.io/fluentui-contrib/react-data-grid-react-window/?path=/story/datagrid--virtualized-data-grid)
- [NPM page](https://www.npmjs.com/package/@fluentui-contrib/react-data-grid-react-window)
- [README](https://github.com/microsoft/fluentui-contrib/blob/main/packages/react-data-grid-react-window/README.md)

> ⚠️ Make sure to memoize the row render function to avoid excessive unmouting/mounting of components.
react-window will [create components based on this renderer](https://react-window.vercel.app/#/api/FixedSizeList)

[Download source](/coreai-design-system/source/examples/components-datagrid--virtualization.tsx)

```tsx
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';

export const Virtualization = (): JSXElement => {
    return (<iframe style={{ width: '100%', height: 500, border: 'none' }} src="https://microsoft.github.io/fluentui-contrib/react-data-grid-react-window/iframe.html?id=packages-react-data-grid-react-window--virtualized-data-grid&viewMode=story"/>);
};

export default Virtualization;
```

## Resources

- [Figma component](https://www.figma.com/design/eXfSQrRg3poHRgmr0ivN5V/CoreAI-Figma-Library?node-id=298485-9476)