# Table

Low-level primitives for building customizable data tables. Subcomponents: TableHeader, TableHeaderCell, TableBody, TableRow, TableCell, TableSelectionCell, TableCellLayout.

## Default

Source: CoreAI.

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        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 />,
        },
    },
];

export const Default = (): JSXElement => {
    return (<Table arial-label="Default table" style={{ minWidth: '510px' }}>
      <TableHeader>
        <TableRow>
          {columns.map((column) => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map((item) => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{
                    status: item.author.status as PresenceBadgeStatus,
                }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>
                {item.lastUpdate.label}
              </TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

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.

### Table API

Table component

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

  children?: any;

  className?: string;

  /**
   * 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;

  ref?: Ref<HTMLDivElement>;

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

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

  style?: CSSProperties;
}
```

### TableBody API

TableBody component

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

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### TableCell API

TableCell component

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

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### TableCellLayout API

TableCellLayout component

```ts
interface TableCellLayoutProps {
  /**
   * Renders design variants of the table cell
   * @default undefined
   */
  appearance?: "primary";

  as?: "div";

  children?: any;

  className?: string;

  /**
   * A layout wrapper for the main and description slots
   */
  content?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * Secondary text that describes or complements the main text
   */
  description?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * Main text for the table cell. Children of the root slot are automatically rendered here
   */
  main?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  /**
   * Slot for an icon or other visual element
   */
  media?: WithSlotShorthandValue<{ as?: "span"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "ref"> & { ref?: ((instance: HTMLSpanElement | null) => void) | RefObject<HTMLSpanElement> | null; }, "children"> & { children?: any; }> | null | undefined;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;

  /**
   * Renders content with overflow: hidden and text-overflow: ellipsis
   */
  truncate?: boolean;
}
```

### TableHeader API

TableHeader component

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

  children?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### TableHeaderCell API

TableHeaderCell component

```ts
interface TableHeaderCellProps {
  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;

  ref?: Ref<HTMLDivElement>;

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

  /**
   * @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;
}
```

### TableRow API

TableRow component

```ts
interface TableRowProps {
  /**
   * 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?: any;

  className?: string;

  ref?: Ref<HTMLDivElement>;

  style?: CSSProperties;
}
```

### TableSelectionCell API

TableSelectionCell component

```ts
interface TableSelectionCellProps {
  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.

## Cell Actions

Source: Fluent, adapted for CoreAI.

`TableCellActions` is a container that is visible when the `TableRow`is hovered
or when the current focused element is within the row. It is commonly used to contain interactive actions
like buttons, but can be used for any generic content. Please ensure that the contents of cell actions
are accessible.

[Download source](/coreai-design-system/source/examples/components-table--cell-actions.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { TableCellActions } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { EditFilled } from "@fluentui/react-icons";
import { MoreHorizontalFilled } from "@fluentui/react-icons";
import { MoreHorizontalRegular } from "@fluentui/react-icons";
import { Avatar } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        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 EditIcon = bundleIcon(EditFilled, EditRegular);

const MoreHorizontalIcon = bundleIcon(MoreHorizontalFilled, MoreHorizontalRegular);

export const CellActions = (): JSXElement => {
    return (<Table aria-label="Table with cell actions" style={{ minWidth: '500px' }}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
              <TableCellActions>
                <Button icon={<EditIcon />} appearance="subtle" aria-label="Edit"/>
                <Button icon={<MoreHorizontalIcon />} appearance="subtle" aria-label="More actions"/>
              </TableCellActions>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default CellActions;
```

## Cell Navigation

Source: Fluent, adapted for CoreAI.

The `Table` primitive components do not support keyboard navigation. This should be added by users.
Cell navigation can be achieved simply using the `useArrowNavigationGroup` utility provided by the Library.

>⚠️ Once there is any kind of keyboard navigation on the component it must follow the
>[aria role="grid" pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/examples/data-grids/).

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useArrowNavigationGroup } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        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 />,
        },
    },
];

export const CellNavigation = (): JSXElement => {
    const keyboardNavAttr = useArrowNavigationGroup({ axis: 'grid' });
    return (<Table {...keyboardNavAttr} role="grid" aria-label="Table with grid keyboard navigation" style={{ minWidth: '600px' }}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
          <TableHeaderCell />
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow key={item.file.label}>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              {item.lastUpdated.label}
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
            <TableCell role="gridcell">
              <TableCellLayout>
                <Button icon={<EditRegular />}>Edit</Button>
              </TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default CellNavigation;
```

## Composite Navigation

Source: Fluent, adapted for CoreAI.

Different keyboard navigation strategies are supported through  the `focusMode` prop.
Composite navigation combines row focus and cell focus. By default the user navigates the table
by row. When the user presses the right arrow key, focus mode switches to cells of the current row.

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableCompositeNavigation } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        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 />,
        },
    },
];

export const CompositeNavigation = (): JSXElement => {
    const { tableRowTabsterAttribute, tableTabsterAttribute, onTableKeyDown } = useTableCompositeNavigation();
    return (<Table role="grid" aria-label="Table with grid keyboard navigation" noNativeElements onKeyDown={onTableKeyDown} style={{ minWidth: '500px' }} {...tableTabsterAttribute}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell tabIndex={0} key={column.columnKey}>
              {column.label}
            </TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow tabIndex={0} key={item.file.label} {...tableRowTabsterAttribute}>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              {item.lastUpdated.label}
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default CompositeNavigation;
```

## Data Grid

Source: Fluent, adapted for CoreAI.

The `DataGrid` component is a composition of the `useTableFeatures` hook and primitive `Table` components
along with some convenience features such as accessible markup and event handlers.
Any feature of the `DataGrid` is achievable with the primitive components and hook

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import { useTableSort } from "@coreai-ds/react-components";
import * as React from 'react';
import type { TableColumnId } from "@coreai-ds/react-components";
import { useArrowNavigationGroup } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const DataGrid = (): JSXElement => {
    const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, sort: { getSortDirection, toggleColumnSort, sort }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'multiselect',
            defaultSelectedItems: new Set([0, 1]),
        }),
        useTableSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } }),
    ]);
    const rows = sort(getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ') {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    }));
    const headerSortProps = (columnId: TableColumnId) => ({
        onClick: (e: React.MouseEvent) => {
            toggleColumnSort(e, columnId);
        },
        sortDirection: getSortDirection(columnId),
    });
    const keyboardNavAttr = useArrowNavigationGroup({ axis: 'grid' });
    return (<Table {...keyboardNavAttr} role="grid" sortable aria-label="DataGrid implementation with Table primitives" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} aria-checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} role="checkbox" onClick={toggleAllRows} checkboxIndicator={{ 'aria-label': 'Select all rows ' }}/>
          <TableHeaderCell {...headerSortProps('file')}>File</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('author')}>Author</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdated')}>Last updated</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdate')}>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, onClick, onKeyDown, appearance }) => (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
            <TableSelectionCell role="gridcell" aria-selected={selected} checked={selected} checkboxIndicator={{ 'aria-label': 'Select row' }}/>
            <TableCell tabIndex={0} role="gridcell" aria-selected={selected}>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              {item.lastUpdated.label}
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default DataGrid;
```

## Focusable Elements In Cells

Source: Fluent, adapted for CoreAI.

When the keyboard navigation is implemented on a Table, there needs to be special handling for cells
that contain multiple focusable elements. In these cases, the `TableCell` should be focusable and the
following keyboard pattern should apply:
- Enter keypress should move focus inside the cell
- Focus should be trapped while it is in a cell
- Escape keypress hould focus back on the cell

This can be done using the `useFocusableGroup` hook with the tab behaviour set to `limited-trap-focus`.
The props returned from the hook should be spread to the `TableCell`.

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useArrowNavigationGroup } from "@coreai-ds/react-components";
import { useFocusableGroup } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { DeleteRegular } from "@fluentui/react-icons";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
    { columnKey: 'actions', label: 'Actions' },
];

const items = [
    {
        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 />,
        },
    },
];

export const FocusableElementsInCells = (): JSXElement => {
    const keyboardNavAttr = useArrowNavigationGroup({ axis: 'grid' });
    const focusableGroupAttr = useFocusableGroup({ tabBehavior: 'limited-trap-focus' });
    return (<Table {...keyboardNavAttr} role="grid" aria-label="Table with grid keyboard navigation" style={{ minWidth: '620px' }}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow key={item.file.label}>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              {item.lastUpdated.label}
            </TableCell>
            <TableCell tabIndex={0} role="gridcell">
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
            <TableCell role="gridcell" tabIndex={0} {...focusableGroupAttr}>
              <TableCellLayout>
                <Button icon={<EditRegular />} aria-label="Edit"/>
                <Button icon={<DeleteRegular />} aria-label="Delete"/>
              </TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default FocusableElementsInCells;
```

## Memoization

Source: Fluent, adapted for CoreAI.

There is no single correct way to memoize components. It is important to note that memoization is not free
and should only be used to optimize scenarios that can be identified as performance bottlenecks. This
example demonstrates a reasonable memoization strategy to memoize entire table. When a row's selection
changes, only the affected row is re-rendered.

[Download source](/coreai-design-system/source/examples/components-table--memoization.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import { useTableSort } from "@coreai-ds/react-components";
import type { TableColumnId } from "@coreai-ds/react-components";
import * as React from 'react';
import { useArrowNavigationGroup } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import type { TableSelectionState } from "@coreai-ds/react-components";
import type { TableRowProps } from "@coreai-ds/react-components";
import type { TableRowId } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

type TableSelectableRowProps = {
    toggleRow: TableSelectionState['toggleRow'];
    item: Item;
    selected: boolean;
    appearance: TableRowProps['appearance'];
    rowId: TableRowId;
};

const TableSelectableRow: React.FC<TableSelectableRowProps> = props => {
    const { item, selected, appearance, rowId, toggleRow } = props;
    const onClick = React.useCallback((e: React.MouseEvent<HTMLDivElement>) => toggleRow(e, rowId), [toggleRow, rowId]);
    const onKeyDown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
        if (e.key === ' ') {
            e.preventDefault();
            toggleRow(e, rowId);
        }
    }, [toggleRow, rowId]);
    return (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
      <TableSelectionCell role="gridcell" aria-selected={selected} checked={selected} checkboxIndicator={{ 'aria-label': 'Select row' }}/>
      <TableCell tabIndex={0} role="gridcell" aria-selected={selected}>
        <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
      </TableCell>
      <TableCell tabIndex={0} role="gridcell">
        <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
          {item.author.label}
        </TableCellLayout>
      </TableCell>
      <TableCell tabIndex={0} role="gridcell">
        {item.lastUpdated.label}
      </TableCell>
      <TableCell tabIndex={0} role="gridcell">
        <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
      </TableCell>
    </TableRow>);
};

const TableSelectableRowMemoized = React.memo(TableSelectableRow);

export const Memoization = (): JSXElement => {
    const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, sort: { getSortDirection, toggleColumnSort, sort }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'multiselect',
            defaultSelectedItems: new Set([0, 1]),
        }),
        useTableSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } }),
    ]);
    const rows = sort(getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    }));
    const headerSortProps = (columnId: TableColumnId) => ({
        onClick: (e: React.MouseEvent) => {
            toggleColumnSort(e, columnId);
        },
        sortDirection: getSortDirection(columnId),
    });
    const keyboardNavAttr = useArrowNavigationGroup({ axis: 'grid' });
    return (<Table {...keyboardNavAttr} role="grid" sortable aria-label="DataGrid implementation with Table primitives" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} aria-checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} role="checkbox" onClick={toggleAllRows} checkboxIndicator={{ 'aria-label': 'Select all rows ' }}/>
          <TableHeaderCell {...headerSortProps('file')}>File</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('author')}>Author</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdated')}>Last updated</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdate')}>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, appearance, rowId }) => (<TableSelectableRowMemoized key={rowId} rowId={rowId} toggleRow={toggleRow} item={item} selected={selected} appearance={appearance}/>))}
      </TableBody>
    </Table>);
};

export default Memoization;
```

## Multiple Select

Source: Fluent, adapted for CoreAI.

Selection can be achieved easily by combining the `TableSelectionCell` component along with
other primitive components. `useTableFeatures` can handle state management for selection,
although its use is not
necessary if users already have their own state management.

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import * as React from 'react';
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
    }),
    createTableColumn<Item>({
        columnId: 'author',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const MultipleSelect = (): JSXElement => {
    const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'multiselect',
            defaultSelectedItems: new Set([0, 1]),
        }),
    ]);
    const rows = getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ') {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    });
    const toggleAllKeydown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
        if (e.key === ' ') {
            toggleAllRows(e);
            e.preventDefault();
        }
    }, [toggleAllRows]);
    return (<Table aria-label="Table with multiselect" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} onClick={toggleAllRows} onKeyDown={toggleAllKeydown} checkboxIndicator={{ 'aria-label': 'Select all rows ' }}/>
          <TableHeaderCell>File</TableHeaderCell>
          <TableHeaderCell>Author</TableHeaderCell>
          <TableHeaderCell>Last updated</TableHeaderCell>
          <TableHeaderCell>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, onClick, onKeyDown, appearance }) => (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
            <TableSelectionCell checked={selected} checkboxIndicator={{ 'aria-label': 'Select row' }}/>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default MultipleSelect;
```

## Multiple Select Controlled

Source: Fluent, adapted for CoreAI.

By default our hook is uncontrolled. However, it is possible to control selection features with external
user state.

[Download source](/coreai-design-system/source/examples/components-table--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 { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
    }),
    createTableColumn<Item>({
        columnId: 'author',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const MultipleSelectControlled = (): JSXElement => {
    const [selectedRows, setSelectedRows] = React.useState(() => new Set<TableRowId>([0, 1]));
    const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'multiselect',
            selectedItems: selectedRows,
            onSelectionChange: (e, data) => setSelectedRows(data.selectedItems),
        }),
    ]);
    const rows = getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ') {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    });
    const toggleAllKeydown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
        if (e.key === ' ') {
            toggleAllRows(e);
            e.preventDefault();
        }
    }, [toggleAllRows]);
    return (<Table aria-label="Table with controlled multiselect" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} onClick={toggleAllRows} onKeyDown={toggleAllKeydown} checkboxIndicator={{ 'aria-label': 'Select all rows ' }}/>
          <TableHeaderCell>File</TableHeaderCell>
          <TableHeaderCell>Author</TableHeaderCell>
          <TableHeaderCell>Last updated</TableHeaderCell>
          <TableHeaderCell>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, onClick, onKeyDown, appearance }) => (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
            <TableSelectionCell checked={selected} checkboxIndicator={{ 'aria-label': 'Select row' }}/>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default MultipleSelectControlled;
```

## Non Native Elements

Source: Fluent, adapted for CoreAI.

By default `Table` components will render native semantic `<table>` HTML elements.
Native semantic elements provide the best accessibility support and it is recommended to user them.
However, for certain use cases (i.e. Virtualization) the native semantic elements are not advisable
due to strict browser layouting. Using the `noNativeElements` prop will ensure that all components are
rendered as divs while ensuring a layout experience similar to semantic table elements.

[Download source](/coreai-design-system/source/examples/components-table--non-native-elements.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        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 />,
        },
    },
];

export const NonNativeElements = (): JSXElement => {
    return (<Table noNativeElements aria-label="Table without semantic HTML elements" style={{ minWidth: '500px' }}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default NonNativeElements;
```

## Primary Cell

Source: Fluent, adapted for CoreAI.

A primary cell creates emphasis by increasing icon size and font weight for the main text.
Generally the primary cell should be used in the first column of a table, but there is no obligation
to do so and can be used in any column by the user.

[Download source](/coreai-design-system/source/examples/components-table--primary-cell.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { TableCellActions } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { EditFilled } from "@fluentui/react-icons";
import { MoreHorizontalFilled } from "@fluentui/react-icons";
import { MoreHorizontalRegular } from "@fluentui/react-icons";
import { Avatar } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        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 EditIcon = bundleIcon(EditFilled, EditRegular);

const MoreHorizontalIcon = bundleIcon(MoreHorizontalFilled, MoreHorizontalRegular);

export const PrimaryCell = (): JSXElement => {
    return (<Table aria-label="Table with primary cell layout" style={{ minWidth: '500px' }}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon} description="My Organization" appearance="primary">
                {item.file.label}
              </TableCellLayout>
              <TableCellActions>
                <Button icon={<EditIcon />} appearance="subtle" aria-label="Edit"/>
                <Button icon={<MoreHorizontalIcon />} appearance="subtle" aria-label="More actions"/>
              </TableCellActions>
            </TableCell>

            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default PrimaryCell;
```

## Resizable Columns - controlled (preview)

Source: Fluent, adapted for CoreAI.

This example demonstrates how `columnSizingOptions` can be used in combination with 
`onColumnResize` callback to control the width of each column from the parent component.

The table itself still makes sure the columns are laid out in such a way that they fit in the container.

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 advanced Table features.

This example also demonstrates how columns can be removed or added.

[Download source](/coreai-design-system/source/examples/components-table--resizable-columns-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 { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import type { TableColumnId } 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 { useTableFeatures } 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 { useTableColumnSizing_unstable } from "@coreai-ds/react-components";
import { useTableSort } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Label } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { DismissRegular } 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 { TableBody } from "@coreai-ds/react-components";
import { TableCell } 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 columnNames: {
    [key: TableColumnId]: string;
} = {
    file: 'File',
    author: 'Author',
    lastUpdated: 'Last updated',
    lastUpdate: 'Last update',
};

const columnsDef: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        renderHeaderCell: () => <>{columnNames.file}</>,
        renderCell: (item: Item) => (<TableCellLayout truncate media={item.file.icon}>
        {item.file.label}
      </TableCellLayout>),
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        renderHeaderCell: () => <>{columnNames.author}</>,
        renderCell: (item: Item) => (<TableCellLayout truncate media={<Avatar name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
        {item.author.label}
      </TableCellLayout>),
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        renderHeaderCell: () => <>{columnNames.lastUpdated}</>,
        renderCell: (item: Item) => <TableCellLayout truncate>{item.lastUpdated.label}</TableCellLayout>,
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        renderHeaderCell: () => <>{columnNames.lastUpdate}</>,
        renderCell: (item: Item) => (<TableCellLayout truncate media={item.lastUpdate.icon}>
        {item.lastUpdate.label}
      </TableCellLayout>),
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const ResizableColumnsControlled = (): JSXElement => {
    const [columns, setColumns] = React.useState<TableColumnDefinition<Item>[]>(columnsDef);
    const [columnSizingOptions, setColumnSizingOptions] = React.useState<TableColumnSizingOptions>({
        file: {
            idealWidth: 300,
            minWidth: 190,
        },
        author: {
            minWidth: 170,
            defaultWidth: 250,
        },
        lastUpdated: {
            minWidth: 120,
        },
        lastUpdate: {
            minWidth: 220,
        },
    });
    const removeColumn = (index: number) => {
        setColumns([...columns.slice(0, index), ...columns.slice(index + 1)]);
    };
    const addColumn = () => {
        const currentColumnIds = columns.map(({ columnId }) => columnId);
        const missingColumnIndex = columnsDef.findIndex(({ columnId }) => !currentColumnIds.includes(columnId));
        if (missingColumnIndex !== -1) {
            const missingColumn = columnsDef[missingColumnIndex];
            setColumns(state => [...state.slice(0, missingColumnIndex), missingColumn, ...state.slice(missingColumnIndex)]);
        }
    };
    const onWidthChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        let newWidth = parseInt(e.target.value, 10);
        if (Number.isNaN(newWidth)) {
            newWidth = 0;
        }
        setColumnSizingOptions(state => ({
            ...state,
            file: {
                ...state.file,
                idealWidth: newWidth,
            },
        }));
    };
    const onMinWidthChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        let newMinWidth = parseInt(e.target.value, 10);
        if (Number.isNaN(newMinWidth)) {
            newMinWidth = 0;
        }
        setColumnSizingOptions(state => ({
            ...state,
            file: {
                ...state.file,
                minWidth: newMinWidth,
            },
        }));
    };
    const onColumnResize = React.useCallback((_: KeyboardEvent | TouchEvent | MouseEvent | undefined, { columnId, width, }: {
        columnId: TableColumnId;
        width: number;
    }) => {
        setColumnSizingOptions(state => ({
            ...state,
            [columnId]: {
                ...state[columnId],
                idealWidth: width,
            },
        }));
    }, []);
    const { getRows, sort: { getSortDirection, toggleColumnSort, sort }, columnSizing_unstable: columnSizing, tableRef, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableColumnSizing_unstable({ columnSizingOptions, onColumnResize }),
        useTableSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } }),
    ]);
    const headerSortProps = (columnId: TableColumnId) => ({
        onClick: (e: React.MouseEvent) => {
            toggleColumnSort(e, columnId);
        },
        sortDirection: getSortDirection(columnId),
    });
    const rows = sort(getRows());
    const inputId = useId('first-column');
    return (<>
      <p>
        <Label htmlFor={`${inputId}-width`}>First column width: </Label>
        <Input type="number" id={`${inputId}-width`} onChange={onWidthChange} value={columnSizingOptions.file.idealWidth ? columnSizingOptions.file.idealWidth.toString() : ''}/>
      </p>
      <p>
        <Label htmlFor={`${inputId}-minwidth`}>First column minWidth: </Label>
        <Input type="number" id={`${inputId}-minwidth`} onChange={onMinWidthChange} value={columnSizingOptions.file.minWidth ? columnSizingOptions.file.minWidth?.toString() : ''}/>
      </p>
      <p>
        <Button onClick={addColumn} disabled={columns.length === columnsDef.length}>
          Add removed column
        </Button>
      </p>
      <div style={{ overflowX: 'auto' }}>
        <Table sortable aria-label="Table with sort" ref={tableRef} {...columnSizing.getTableProps()}>
          <TableHeader>
            <TableRow>
              {columns.map((column, index) => (<Menu openOnContext key={column.columnId}>
                  <MenuTrigger>
                    <TableHeaderCell key={column.columnId} {...columnSizing.getTableHeaderCellProps(column.columnId)} {...headerSortProps(column.columnId)}>
                      {column.renderHeaderCell()}
                      <Button appearance="transparent" aria-label={`Remove ${columnNames[column.columnId]} column`} size="small" icon={<DismissRegular />} style={{ position: 'absolute', right: 0 }} onClick={() => removeColumn(index)}/>
                    </TableHeaderCell>
                  </MenuTrigger>
                  <MenuPopover>
                    <MenuList>
                      <MenuItem onClick={columnSizing.enableKeyboardMode(column.columnId)}>
                        Keyboard Column Resizing
                      </MenuItem>
                    </MenuList>
                  </MenuPopover>
                </Menu>))}
            </TableRow>
          </TableHeader>
          <TableBody>
            {rows.map(({ item }) => (<TableRow key={item.file.label}>
                {columns.map(column => (<TableCell key={column.columnId} {...columnSizing.getTableCellProps(column.columnId)}>
                    {column.renderCell(item)}
                  </TableCell>))}
              </TableRow>))}
          </TableBody>
        </Table>
      </div>
    </>);
};

export default ResizableColumnsControlled;
```

## Resizable Columns - Disabled container auto-fit

Source: Fluent, adapted for CoreAI.

By default, the column sizing feature will automatically fit the columns to the content.
This behavior can be disabled by setting the`autoFitColumns` option to`false`.

Make sure to also enable `noNativeElements` option to prevent displaying the table elements as
native elements, as the native elements won't overflow the parent table.

[Download source](/coreai-design-system/source/examples/components-table--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 type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import { useTableFeatures } 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 { useTableColumnSizing_unstable } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { TableHeaderCell } 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 { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columnsDef: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        renderHeaderCell: () => <>File</>,
    }),
    createTableColumn<Item>({
        columnId: 'author',
        renderHeaderCell: () => <>Author</>,
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        renderHeaderCell: () => <>Last updated</>,
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        renderHeaderCell: () => <>Last update</>,
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const columnSizingOptions = {
    file: {
        idealWidth: 300,
        minWidth: 150,
    },
    author: {
        minWidth: 110,
        defaultWidth: 250,
    },
    lastUpdate: {
        minWidth: 150,
    },
};

export const ResizableColumnsDisableAutoFit = (): JSXElement => {
    const [columns] = React.useState<TableColumnDefinition<Item>[]>(columnsDef);
    // eslint-disable-next-line @typescript-eslint/naming-convention
    const { getRows, columnSizing_unstable, tableRef } = useTableFeatures({
        columns,
        items,
    }, [useTableColumnSizing_unstable({ columnSizingOptions, autoFitColumns: false })]);
    const rows = getRows();
    return (<div style={{ overflowX: 'auto' }}>
      <Table ref={tableRef} {...columnSizing_unstable.getTableProps()} noNativeElements={true}>
        <TableHeader>
          <TableRow>
            {columns.map(column => (<Menu openOnContext key={column.columnId}>
                <MenuTrigger>
                  <TableHeaderCell key={column.columnId} {...columnSizing_unstable.getTableHeaderCellProps(column.columnId)}>
                    {column.renderHeaderCell()}
                  </TableHeaderCell>
                </MenuTrigger>
                <MenuPopover>
                  <MenuList>
                    <MenuItem onClick={columnSizing_unstable.enableKeyboardMode(column.columnId)}>
                      Keyboard Column Resizing
                    </MenuItem>
                  </MenuList>
                </MenuPopover>
              </Menu>))}
          </TableRow>
        </TableHeader>
        <TableBody>
          {rows.map(({ item }) => (<TableRow key={item.file.label}>
              <TableCell {...columnSizing_unstable.getTableCellProps('file')}>
                <TableCellLayout truncate media={item.file.icon}>
                  {item.file.label}
                </TableCellLayout>
              </TableCell>
              <TableCell {...columnSizing_unstable.getTableCellProps('author')}>
                <TableCellLayout truncate media={<Avatar name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                  {item.author.label}
                </TableCellLayout>
              </TableCell>
              <TableCell {...columnSizing_unstable.getTableCellProps('lastUpdated')}>
                <TableCellLayout truncate>{item.lastUpdated.label}</TableCellLayout>
              </TableCell>
              <TableCell {...columnSizing_unstable.getTableCellProps('lastUpdate')}>
                <TableCellLayout truncate media={item.lastUpdate.icon}>
                  {item.lastUpdate.label}
                </TableCellLayout>
              </TableCell>
            </TableRow>))}
        </TableBody>
      </Table>
    </div>);
};

export default ResizableColumnsDisableAutoFit;
```

## Resizable Columns (preview)

Source: Fluent, adapted for CoreAI.

The Table component contains logic to support column resizing. To enable resizing,
use the `useTableFeatures` hook in combination with the `useTableColumnSizing_unstable` plugin.
The resulting `columnSizing_unstable` object contains methods needed to make resizing work.

In this example we are choosing an uncontrolled approach, which still allows us to set column 
width in an imperative matter (try changing the input value).

Options can be passed to the plugin to define minimum, default and optimal 
(in a controlled scenario) width of the column.

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 advanced Table features.

To learn about how to control widths from the parent, please see the example below.

[Download source](/coreai-design-system/source/examples/components-table--resizable-columns-uncontrolled.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 { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } from "@coreai-ds/react-components";
import type { TableColumnSizingOptions } from "@coreai-ds/react-components";
import { useTableFeatures } 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 { useTableColumnSizing_unstable } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { Input } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { TableHeaderCell } 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 { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columnsDef: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        renderHeaderCell: () => <>File</>,
    }),
    createTableColumn<Item>({
        columnId: 'author',
        renderHeaderCell: () => <>Author</>,
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        renderHeaderCell: () => <>Last updated</>,
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        renderHeaderCell: () => <>Last update</>,
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const ResizableColumnsUncontrolled = (): JSXElement => {
    const [columns] = React.useState<TableColumnDefinition<Item>[]>(columnsDef);
    const [columnSizingOptions] = React.useState<TableColumnSizingOptions>({
        file: {
            idealWidth: 300,
            minWidth: 150,
        },
        author: {
            minWidth: 110,
            defaultWidth: 250,
        },
        lastUpdate: {
            minWidth: 150,
        },
    });
    // eslint-disable-next-line @typescript-eslint/naming-convention
    const { getRows, columnSizing_unstable, tableRef } = useTableFeatures({
        columns,
        items,
    }, [useTableColumnSizing_unstable({ columnSizingOptions })]);
    const [inputValue, setInputValue] = React.useState('300');
    const onWidthChange = (e: React.ChangeEvent<HTMLInputElement>) => {
        setInputValue(e.target.value);
        const numeric = parseInt(e.target.value, 10);
        if (!Number.isNaN(numeric)) {
            columnSizing_unstable.setColumnWidth('file', numeric);
        }
    };
    const rows = getRows();
    const inputId = useId('column-width');
    return (<>
      <p>
        <label htmlFor={inputId}>First column width: </label>
        <Input type="number" id={inputId} onChange={onWidthChange} value={inputValue ? inputValue.toString() : ''}/>
      </p>
      <div style={{ overflowX: 'auto' }}>
        <Table sortable aria-label="Table with sort" ref={tableRef} {...columnSizing_unstable.getTableProps()}>
          <TableHeader>
            <TableRow>
              {columns.map(column => (<Menu openOnContext key={column.columnId}>
                  <MenuTrigger>
                    <TableHeaderCell key={column.columnId} {...columnSizing_unstable.getTableHeaderCellProps(column.columnId)}>
                      {column.renderHeaderCell()}
                    </TableHeaderCell>
                  </MenuTrigger>
                  <MenuPopover>
                    <MenuList>
                      <MenuItem onClick={columnSizing_unstable.enableKeyboardMode(column.columnId)}>
                        Keyboard Column Resizing
                      </MenuItem>
                    </MenuList>
                  </MenuPopover>
                </Menu>))}
            </TableRow>
          </TableHeader>
          <TableBody>
            {rows.map(({ item }) => (<TableRow key={item.file.label}>
                <TableCell {...columnSizing_unstable.getTableCellProps('file')}>
                  <TableCellLayout truncate media={item.file.icon}>
                    {item.file.label}
                  </TableCellLayout>
                </TableCell>
                <TableCell {...columnSizing_unstable.getTableCellProps('author')}>
                  <TableCellLayout truncate media={<Avatar name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                    {item.author.label}
                  </TableCellLayout>
                </TableCell>
                <TableCell {...columnSizing_unstable.getTableCellProps('lastUpdated')}>
                  <TableCellLayout truncate>{item.lastUpdated.label}</TableCellLayout>
                </TableCell>
                <TableCell {...columnSizing_unstable.getTableCellProps('lastUpdate')}>
                  <TableCellLayout truncate media={item.lastUpdate.icon}>
                    {item.lastUpdate.label}
                  </TableCellLayout>
                </TableCell>
              </TableRow>))}
          </TableBody>
        </Table>
      </div>
    </>);
};

export default ResizableColumnsUncontrolled;
```

## Selection With Cell Actions

Source: Fluent, adapted for CoreAI.

When using cell actions with row selection, some event handling logic is necessary so that
invoking the cell actions does not invoke the row (therefore invoking selection).
How this is done will depend on each use case, so this event handling is not handled by any of
the library components. This examples handles such events by using `preventDefault` and `defaultPrevented`
properties.

[Download source](/coreai-design-system/source/examples/components-table--selection-with-cell-actions.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import * as React from 'react';
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { TableCellActions } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { EditFilled } from "@fluentui/react-icons";
import { MoreHorizontalFilled } from "@fluentui/react-icons";
import { MoreHorizontalRegular } from "@fluentui/react-icons";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
    }),
    createTableColumn<Item>({
        columnId: 'author',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

const EditIcon = bundleIcon(EditFilled, EditRegular);

const MoreHorizontalIcon = bundleIcon(MoreHorizontalFilled, MoreHorizontalRegular);

export const SelectionWithCellActions = (): JSXElement => {
    const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'multiselect',
            defaultSelectedItems: new Set([0, 1]),
        }),
    ]);
    const rows = getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => !e.defaultPrevented && toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ' && !e.defaultPrevented) {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    });
    const toggleAllKeydown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
        if (e.key === ' ') {
            toggleAllRows(e);
            e.preventDefault();
        }
    }, [toggleAllRows]);
    const onClickCellActions = (e: React.MouseEvent<HTMLDivElement>) => e.preventDefault();
    const onKeyDownCellActions = (e: React.KeyboardEvent<HTMLDivElement>) => e.key === ' ' && e.preventDefault();
    return (<Table aria-label="Table with multiselect" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} onClick={toggleAllRows} onKeyDown={toggleAllKeydown} checkboxIndicator={{ 'aria-label': 'Select all rows ' }}/>
          <TableHeaderCell>File</TableHeaderCell>
          <TableHeaderCell>Author</TableHeaderCell>
          <TableHeaderCell>Last updated</TableHeaderCell>
          <TableHeaderCell>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, onClick, onKeyDown, appearance }) => (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
            <TableSelectionCell checked={selected} checkboxIndicator={{ 'aria-label': 'Select row' }}/>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
              <TableCellActions onClick={onClickCellActions} onKeyDown={onKeyDownCellActions}>
                <Button icon={<EditIcon />} appearance="subtle" aria-label="Edit"/>
                <Button icon={<MoreHorizontalIcon />} appearance="subtle" aria-label="More actions"/>
              </TableCellActions>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default SelectionWithCellActions;
```

## Single Select

Source: Fluent, adapted for CoreAI.

The single selection scenario is similar to the multiple selection scenario. The `TableSelectionCell`
Can render both checkbox and radio style components which are Fluent
[Checkbox](https://react.fluentui.dev/?path=/docs/components-checkbox--default) and [Radio](https://react.fluentui.dev/?path=/docs/components-radio--default)
components. While the design recommendation is to use checkbox for multiselect and radio for single select.
There is no obligation to do so.

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import * as React from 'react';
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
    }),
    createTableColumn<Item>({
        columnId: 'author',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const SingleSelect = (): JSXElement => {
    const { getRows, selection: { toggleRow, isRowSelected }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'single',
            defaultSelectedItems: new Set([1]),
        }),
    ]);
    const rows = getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ') {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    });
    return (<Table aria-label="Table with single selection" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell type="radio" invisible/>
          <TableHeaderCell>File</TableHeaderCell>
          <TableHeaderCell>Author</TableHeaderCell>
          <TableHeaderCell>Last updated</TableHeaderCell>
          <TableHeaderCell>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, onClick, onKeyDown, appearance }) => (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
            <TableSelectionCell checked={selected} type="radio" radioIndicator={{ 'aria-label': 'Select row' }}/>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default SingleSelect;
```

## Single Select Controlled

Source: Fluent, adapted for CoreAI.

By default the `useTableFeatures` hook is uncontrolled. 
However, it is possible to control selection features with external
user state.

[Download source](/coreai-design-system/source/examples/components-table--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 { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
    }),
    createTableColumn<Item>({
        columnId: 'author',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const SingleSelectControlled = (): JSXElement => {
    const [selectedRows, setSelectedRows] = React.useState(() => new Set<TableRowId>([1]));
    const { getRows, selection: { toggleRow, isRowSelected }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'single',
            selectedItems: selectedRows,
            onSelectionChange: (e, data) => setSelectedRows(data.selectedItems),
        }),
    ]);
    const rows = getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ') {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    });
    return (<Table aria-label="Table with controlled single selection" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell type="radio" invisible/>
          <TableHeaderCell>File</TableHeaderCell>
          <TableHeaderCell>Author</TableHeaderCell>
          <TableHeaderCell>Last updated</TableHeaderCell>
          <TableHeaderCell>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, onClick, onKeyDown, appearance }) => (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
            <TableSelectionCell checked={selected} type="radio" radioIndicator={{ 'aria-label': 'Select row' }}/>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default SingleSelectControlled;
```

## Size Extra Small

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-table--size-extra-small.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' as const },
        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' as const },
        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' as const },
        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' as const },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const SizeExtraSmall = (): JSXElement => {
    return (<Table size="extra-small" aria-label="Table with extra-small size" style={{ minWidth: '400px' }}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default SizeExtraSmall;
```

## Size Small

Source: Fluent, adapted for CoreAI.

[Download source](/coreai-design-system/source/examples/components-table--size-small.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } 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 { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import * as React from 'react';

const columns = [
    { columnKey: 'file', label: 'File' },
    { columnKey: 'author', label: 'Author' },
    { columnKey: 'lastUpdated', label: 'Last updated' },
    { columnKey: 'lastUpdate', label: 'Last update' },
];

const items = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' as const },
        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' as const },
        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' as const },
        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' as const },
        lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 3 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const SizeSmall = (): JSXElement => {
    return (<Table size="small" aria-label="Table with small size" style={{ minWidth: '475px' }}>
      <TableHeader>
        <TableRow>
          {columns.map(column => (<TableHeaderCell key={column.columnKey}>{column.label}</TableHeaderCell>))}
        </TableRow>
      </TableHeader>
      <TableBody>
        {items.map(item => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default SizeSmall;
```

## Sort

Source: Fluent, adapted for CoreAI.

Using the `sortable` prop will configure all header cells to be buttons and add extra styles.
The `TableHeaderCell` component accepts a `sortDirection` prop that will indicate whether the
header is sorted. Handling the sort of data and column state is handled by `useTableFeatures`.

> 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-table--sort.tsx)

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSort } from "@coreai-ds/react-components";
import type { TableColumnId } from "@coreai-ds/react-components";
import * as React from 'react';
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const Sort = (): JSXElement => {
    const { getRows, sort: { getSortDirection, toggleColumnSort, sort }, } = useTableFeatures({
        columns,
        items,
    }, [useTableSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } })]);
    const headerSortProps = (columnId: TableColumnId) => ({
        onClick: (e: React.MouseEvent) => {
            toggleColumnSort(e, columnId);
        },
        sortDirection: getSortDirection(columnId),
    });
    const rows = sort(getRows());
    return (<Table sortable aria-label="Table with sort" style={{ minWidth: '500px' }}>
      <TableHeader>
        <TableRow>
          <TableHeaderCell {...headerSortProps('file')}>File</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('author')}>Author</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdated')}>Last updated</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdate')}>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item }) => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default Sort;
```

## Sort Controlled

Source: Fluent, adapted for CoreAI.

By default our hook is uncontrolled. However, it is possible to control sort features
with external user state.

[Download source](/coreai-design-system/source/examples/components-table--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 { TableColumnId } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSort } from "@coreai-ds/react-components";
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
        compare: (a, b) => {
            return a.file.label.localeCompare(b.file.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'author',
        compare: (a, b) => {
            return a.author.label.localeCompare(b.author.label);
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
        compare: (a, b) => {
            return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
        },
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
        compare: (a, b) => {
            return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
        },
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const SortControlled = (): JSXElement => {
    const [sortState, setSortState] = React.useState<{
        sortDirection: 'ascending' | 'descending';
        sortColumn: TableColumnId | undefined;
    }>({
        sortDirection: 'ascending' as const,
        sortColumn: 'file',
    });
    const { getRows, sort: { getSortDirection, toggleColumnSort, sort }, } = useTableFeatures({
        columns,
        items,
    }, [useTableSort({ sortState, onSortChange: (e, nextSortState) => setSortState(nextSortState) })]);
    const headerSortProps = (columnId: TableColumnId) => ({
        onClick: (e: React.MouseEvent) => toggleColumnSort(e, columnId),
        sortDirection: getSortDirection(columnId),
    });
    const rows = sort(getRows());
    return (<Table sortable aria-label="Table with controlled sort" style={{ minWidth: '500px' }}>
      <TableHeader>
        <TableRow>
          <TableHeaderCell {...headerSortProps('file')}>File</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('author')}>Author</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdated')}>Last updated</TableHeaderCell>
          <TableHeaderCell {...headerSortProps('lastUpdate')}>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item }) => (<TableRow key={item.file.label}>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default SortControlled;
```

## Subtle Selection

Source: Fluent, adapted for CoreAI.

By setting the `subtle` prop on the `TableSelectionCell` component, the selection indicator will only
appear when:
- the `TableRow` component is hovered.
- The current focused element is within the `TableRow`
- The `TableSelectionCell` is checked

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import type { TableColumnDefinition } from "@coreai-ds/react-components";
import type { PresenceBadgeStatus } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import * as React from 'react';
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } 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 columns: TableColumnDefinition<Item>[] = [
    createTableColumn<Item>({
        columnId: 'file',
    }),
    createTableColumn<Item>({
        columnId: 'author',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
    }),
];

const items: Item[] = [
    {
        file: { label: 'Meeting notes', icon: <DocumentRegular /> },
        author: { label: 'Max Mustermann', status: 'available' },
        lastUpdated: { label: '7h ago', timestamp: 3 },
        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: 1 },
        lastUpdate: {
            label: 'You shared this in a Teams chat',
            icon: <PeopleRegular />,
        },
    },
];

export const SubtleSelection = (): JSXElement => {
    const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'multiselect',
            defaultSelectedItems: new Set([0, 1]),
        }),
    ]);
    const rows = getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ') {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    });
    const toggleAllKeydown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
        if (e.key === ' ') {
            toggleAllRows(e);
            e.preventDefault();
        }
    }, [toggleAllRows]);
    return (<Table aria-label="Table with subtle selection" style={{ minWidth: '550px' }}>
      <TableHeader>
        <TableRow>
          <TableSelectionCell checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} onClick={toggleAllRows} onKeyDown={toggleAllKeydown} checkboxIndicator={{ 'aria-label': 'Select all rows ' }}/>
          <TableHeaderCell>File</TableHeaderCell>
          <TableHeaderCell>Author</TableHeaderCell>
          <TableHeaderCell>Last updated</TableHeaderCell>
          <TableHeaderCell>Last update</TableHeaderCell>
        </TableRow>
      </TableHeader>
      <TableBody>
        {rows.map(({ item, selected, onClick, onKeyDown, appearance }) => (<TableRow key={item.file.label} onClick={onClick} onKeyDown={onKeyDown} aria-selected={selected} appearance={appearance}>
            <TableSelectionCell subtle checked={selected} checkboxIndicator={{ 'aria-label': 'Select row' }}/>
            <TableCell>
              <TableCellLayout media={item.file.icon}>{item.file.label}</TableCellLayout>
            </TableCell>
            <TableCell>
              <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status }}/>}>
                {item.author.label}
              </TableCellLayout>
            </TableCell>
            <TableCell>{item.lastUpdated.label}</TableCell>
            <TableCell>
              <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
            </TableCell>
          </TableRow>))}
      </TableBody>
    </Table>);
};

export default SubtleSelection;
```

## Virtualization

Source: Fluent, adapted for CoreAI.

> Semantic `<table>` elements have are subject to strict layouting by the browser and are not suited
to virtualization in general. Use the `noNativeElements` prop to use a flexbox based layout that will
make virtualization a lot easier.

The `Table` primitive components are unopinionated with respect to virtualization. They should be compatible
with any virtualization library. Hoisting business logic to a state management
hook like `useTableFeatures`
means that features can persist between the mounting/unmounting that happens during virtualization.
The below example uses the [react-window](https://www.npmjs.com/package/react-window) library.

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

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

import type { JSXElement } from "@coreai-ds/react-components";
import { useApplyScrollbarWidth } from "@coreai-ds/react-components";
import { useTableFeatures } from "@coreai-ds/react-components";
import { createTableColumn } 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 { useTableSelection } from "@coreai-ds/react-components";
import type { TableRowData as RowStateBase } from "@coreai-ds/react-components";
import * as React from 'react';
import { Table } from "@coreai-ds/react-components";
import { TableHeader } from "@coreai-ds/react-components";
import { TableRow } from "@coreai-ds/react-components";
import { TableSelectionCell } from "@coreai-ds/react-components";
import { TableHeaderCell } from "@coreai-ds/react-components";
import { TableBody } from "@coreai-ds/react-components";
import { FixedSizeList as List } from "react-window";
import type { ListChildComponentProps } from "react-window";
import { TableCell } from "@coreai-ds/react-components";
import { TableCellLayout } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";

type Item = {
    file: {
        label: string;
        icon: JSXElement;
    };
    author: {
        label: string;
        status: PresenceBadgeStatus;
    };
    lastUpdated: {
        label: string;
        timestamp: number;
    };
    lastUpdate: {
        label: string;
        icon: JSXElement;
    };
};

const columns = [
    createTableColumn<Item>({
        columnId: 'file',
    }),
    createTableColumn<Item>({
        columnId: 'author',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdated',
    }),
    createTableColumn<Item>({
        columnId: 'lastUpdate',
    }),
];

const baseItems: 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 items = new Array(1500).fill(0).map((_, i) => baseItems[i % baseItems.length]);

interface TableRowData extends RowStateBase<Item> {
    onClick: (e: React.MouseEvent) => void;
    onKeyDown: (e: React.KeyboardEvent) => void;
    selected: boolean;
    appearance: 'brand' | 'none';
}

interface ReactWindowRenderFnProps extends ListChildComponentProps {
    data: TableRowData[];
}

const RenderRow = ({ index, style, data }: ReactWindowRenderFnProps) => {
    const { item, selected, appearance, onClick, onKeyDown } = data[index];
    return (<TableRow aria-rowindex={index + 2} style={style} key={item.file.label} onKeyDown={onKeyDown} onClick={onClick} appearance={appearance}>
      <TableSelectionCell checked={selected} checkboxIndicator={{ 'aria-label': 'Select row' }}/>
      <TableCell>
        <TableCellLayout media={item.file.icon}>
          <strong>[{index}] </strong>
          {item.file.label}
        </TableCellLayout>
      </TableCell>
      <TableCell>
        <TableCellLayout media={<Avatar aria-label={item.author.label} name={item.author.label} badge={{ status: item.author.status as PresenceBadgeStatus }}/>}>
          {item.author.label}
        </TableCellLayout>
      </TableCell>
      <TableCell>{item.lastUpdated.label}</TableCell>
      <TableCell>
        <TableCellLayout media={item.lastUpdate.icon}>{item.lastUpdate.label}</TableCellLayout>
      </TableCell>
    </TableRow>);
};

export const Virtualization = (): JSXElement => {
    const appliedScrollbarWidthRef = useApplyScrollbarWidth();
    const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, } = useTableFeatures({
        columns,
        items,
    }, [
        useTableSelection({
            selectionMode: 'multiselect',
            defaultSelectedItems: new Set([0, 1]),
        }),
    ]);
    const rows: TableRowData[] = getRows(row => {
        const selected = isRowSelected(row.rowId);
        return {
            ...row,
            onClick: (e: React.MouseEvent) => toggleRow(e, row.rowId),
            onKeyDown: (e: React.KeyboardEvent) => {
                if (e.key === ' ') {
                    e.preventDefault();
                    toggleRow(e, row.rowId);
                }
            },
            selected,
            appearance: selected ? ('brand' as const) : ('none' as const),
        };
    });
    const toggleAllKeydown = React.useCallback((e: React.KeyboardEvent<HTMLDivElement>) => {
        if (e.key === ' ') {
            toggleAllRows(e);
            e.preventDefault();
        }
    }, [toggleAllRows]);
    return (<Table noNativeElements aria-label="Table with selection" aria-rowcount={rows.length} style={{ minWidth: '650px' }}>
      <TableHeader>
        <TableRow aria-rowindex={1}>
          <TableSelectionCell checked={allRowsSelected ? true : someRowsSelected ? 'mixed' : false} onClick={toggleAllRows} onKeyDown={toggleAllKeydown} checkboxIndicator={{ 'aria-label': 'Select all rows' }}/>
          <TableHeaderCell>File</TableHeaderCell>
          <TableHeaderCell>Author</TableHeaderCell>
          <TableHeaderCell>Last updated</TableHeaderCell>
          <TableHeaderCell>Last update</TableHeaderCell>
          {/** Scrollbar alignment for the header */}
          <div role="presentation" ref={appliedScrollbarWidthRef}/>
        </TableRow>
      </TableHeader>
      <TableBody>
        <List height={400} itemCount={items.length} itemSize={45} width="100%" itemData={rows}>
          {RenderRow}
        </List>
      </TableBody>
    </Table>);
};

export default Virtualization;
```