diff --git a/packages/react-components/react-table/stories/DataGrid/KeyboardNavigation.stories.tsx b/packages/react-components/react-table/stories/DataGrid/KeyboardNavigation.stories.tsx
new file mode 100644
index 00000000000000..71fcead973928e
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/KeyboardNavigation.stories.tsx
@@ -0,0 +1,169 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+} from '@fluentui/react-table';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const KeyboardNavigation = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/MultipleSelect.stories.tsx b/packages/react-components/react-table/stories/DataGrid/MultipleSelect.stories.tsx
new file mode 100644
index 00000000000000..a266a08035e8dc
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/MultipleSelect.stories.tsx
@@ -0,0 +1,177 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+} from '@fluentui/react-table';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const MultipleSelect = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/MultipleSelectControlled.stories.tsx b/packages/react-components/react-table/stories/DataGrid/MultipleSelectControlled.stories.tsx
new file mode 100644
index 00000000000000..a5160328cc8bcb
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/MultipleSelectControlled.stories.tsx
@@ -0,0 +1,185 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+ RowId,
+ DataGridProps,
+} from '@fluentui/react-table';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const MultipleSelectControlled = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const [selectedRows, setSelectedRows] = React.useState(
+ new Set([1]),
+ );
+ const onSelectionChange: DataGridProps['onSelectionChange'] = (e, data) => {
+ setSelectedRows(data.selectedItems);
+ };
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/SelectionAppearance.stories.tsx b/packages/react-components/react-table/stories/DataGrid/SelectionAppearance.stories.tsx
new file mode 100644
index 00000000000000..461413367aeae9
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/SelectionAppearance.stories.tsx
@@ -0,0 +1,178 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+} from '@fluentui/react-table';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const SelectionAppearance = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/SingleSelect.stories.tsx b/packages/react-components/react-table/stories/DataGrid/SingleSelect.stories.tsx
new file mode 100644
index 00000000000000..2f8c90ed667963
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/SingleSelect.stories.tsx
@@ -0,0 +1,177 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+} from '@fluentui/react-table';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const SingleSelect = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/SingleSelectControlled.stories.tsx b/packages/react-components/react-table/stories/DataGrid/SingleSelectControlled.stories.tsx
new file mode 100644
index 00000000000000..f556b697106f01
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/SingleSelectControlled.stories.tsx
@@ -0,0 +1,185 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+ RowId,
+ DataGridProps,
+} from '@fluentui/react-table';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const SingleSelectControlled = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const [selectedRows, setSelectedRows] = React.useState(
+ new Set([1]),
+ );
+ const onSelectionChange: DataGridProps['onSelectionChange'] = (e, data) => {
+ setSelectedRows(data.selectedItems);
+ };
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/Sort.stories.tsx b/packages/react-components/react-table/stories/DataGrid/Sort.stories.tsx
new file mode 100644
index 00000000000000..2b3423cda5d7c0
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/Sort.stories.tsx
@@ -0,0 +1,172 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+} from '@fluentui/react-table';
+import { SortState } from '../../src/hooks/types';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const Sort = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const defaultSortState = React.useMemo(() => ({ sortColumn: 'file', sortDirection: 'ascending' }), []);
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/SortControlled.stories.tsx b/packages/react-components/react-table/stories/DataGrid/SortControlled.stories.tsx
new file mode 100644
index 00000000000000..d4d53508ef1dd8
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/SortControlled.stories.tsx
@@ -0,0 +1,183 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+ DataGridProps,
+} from '@fluentui/react-table';
+import { SortState } from '../../src/hooks/types';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const SortControlled = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const [sortState, setSortState] = React.useState({ sortColumn: 'file', sortDirection: 'ascending' });
+ const onSortChange: DataGridProps['onSortChange'] = (e, nextSortState) => {
+ setSortState(nextSortState);
+ };
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/SubtleSelection.stories.tsx b/packages/react-components/react-table/stories/DataGrid/SubtleSelection.stories.tsx
new file mode 100644
index 00000000000000..045ab6d60cd57d
--- /dev/null
+++ b/packages/react-components/react-table/stories/DataGrid/SubtleSelection.stories.tsx
@@ -0,0 +1,178 @@
+import * as React from 'react';
+import {
+ FolderRegular,
+ EditRegular,
+ OpenRegular,
+ DocumentRegular,
+ PeopleRegular,
+ DocumentPdfRegular,
+ VideoRegular,
+} from '@fluentui/react-icons';
+import { PresenceBadgeStatus, Avatar } from '@fluentui/react-components';
+import { TableCellLayout } from '@fluentui/react-components/unstable';
+import {
+ DataGridBody,
+ DataGridRow,
+ DataGrid,
+ DataGridHeader,
+ DataGridHeaderCell,
+ DataGridCell,
+ ColumnDefinition,
+ RowState,
+ createColumn,
+} from '@fluentui/react-table';
+
+type FileCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type LastUpdatedCell = {
+ label: string;
+ timestamp: number;
+};
+
+type LastUpdateCell = {
+ label: string;
+ icon: JSX.Element;
+};
+
+type AuthorCell = {
+ label: string;
+ status: PresenceBadgeStatus;
+};
+
+type Item = {
+ file: FileCell;
+ author: AuthorCell;
+ lastUpdated: LastUpdatedCell;
+ lastUpdate: LastUpdateCell;
+};
+
+const items: Item[] = [
+ {
+ file: { label: 'Meeting notes', icon: },
+ author: { label: 'Max Mustermann', status: 'available' },
+ lastUpdated: { label: '7h ago', timestamp: 1 },
+ lastUpdate: {
+ label: 'You edited this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Thursday presentation', icon: },
+ author: { label: 'Erika Mustermann', status: 'busy' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Training recording', icon: },
+ author: { label: 'John Doe', status: 'away' },
+ lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 },
+ lastUpdate: {
+ label: 'You recently opened this',
+ icon: ,
+ },
+ },
+ {
+ file: { label: 'Purchase order', icon: },
+ 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: ,
+ },
+ },
+];
+
+export const SubtleSelection = () => {
+ const columns: ColumnDefinition- [] = React.useMemo(
+ () => [
+ createColumn
- ({
+ columnId: 'file',
+ compare: (a, b) => {
+ return a.file.label.localeCompare(b.file.label);
+ },
+ renderHeaderCell: () => {
+ return 'File';
+ },
+ renderCell: item => {
+ return {item.file.label};
+ },
+ }),
+ createColumn
- ({
+ columnId: 'author',
+ compare: (a, b) => {
+ return a.author.label.localeCompare(b.author.label);
+ },
+ renderHeaderCell: () => {
+ return 'Author';
+ },
+ renderCell: item => {
+ return (
+ }>
+ {item.author.label}
+
+ );
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdated',
+ compare: (a, b) => {
+ return a.lastUpdated.timestamp - b.lastUpdated.timestamp;
+ },
+ renderHeaderCell: () => {
+ return 'Last updated';
+ },
+
+ renderCell: item => {
+ return item.lastUpdated.label;
+ },
+ }),
+ createColumn
- ({
+ columnId: 'lastUpdate',
+ compare: (a, b) => {
+ return a.lastUpdate.label.localeCompare(b.lastUpdate.label);
+ },
+ renderHeaderCell: () => {
+ return 'Last update';
+ },
+ renderCell: item => {
+ return {item.lastUpdate.label};
+ },
+ }),
+ ],
+ [],
+ );
+
+ const defaultSelectedItems = React.useMemo(() => new Set([1]), []);
+
+ return (
+
+
+
+ {({ renderHeaderCell }: ColumnDefinition
- ) => (
+ {renderHeaderCell()}
+ )}
+
+
+
+ {({ item, rowId }: RowState- ) => (
+
+ {({ renderCell }: ColumnDefinition
- ) => {renderCell(item)}}
+
+ )}
+
+
+ );
+};
diff --git a/packages/react-components/react-table/stories/DataGrid/index.stories.tsx b/packages/react-components/react-table/stories/DataGrid/index.stories.tsx
index f9a915dec8dfb4..28479914e313ff 100644
--- a/packages/react-components/react-table/stories/DataGrid/index.stories.tsx
+++ b/packages/react-components/react-table/stories/DataGrid/index.stories.tsx
@@ -1,6 +1,15 @@
import { DataGrid } from '../../src/components/DataGrid/DataGrid';
export { Default } from './Default.stories';
+export { KeyboardNavigation } from './KeyboardNavigation.stories';
+export { Sort } from './Sort.stories';
+export { SortControlled } from './SortControlled.stories';
+export { MultipleSelect } from './MultipleSelect.stories';
+export { MultipleSelectControlled } from './MultipleSelectControlled.stories';
+export { SingleSelect } from './SingleSelect.stories';
+export { SingleSelectControlled } from './SingleSelectControlled.stories';
+export { SubtleSelection } from './SubtleSelection.stories';
+export { SelectionAppearance } from './SelectionAppearance.stories';
export default {
title: 'Preview Components/DataGrid',
component: DataGrid,