-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Experiment: stress test Table vs DetailsList
- Loading branch information
Showing
7 changed files
with
335 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>v9: Stress Tree</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import * as React from 'react'; | ||
import * as ReactDOM from 'react-dom'; | ||
|
||
import { FluentProvider, webLightTheme } from '@fluentui/react-components'; | ||
import { ReactTest } from '../../../shared/react/ReactTest'; | ||
import { getTestOptions } from '../../../shared/utils/testOptions'; | ||
|
||
const { fixtureName, rendererName, r } = getTestOptions(); | ||
document.title += ' | ' + r ?? rendererName; | ||
ReactDOM.render( | ||
<FluentProvider theme={webLightTheme}> | ||
<ReactTest target="v9" fixtureName={fixtureName} rendererName={rendererName ?? r} /> | ||
</FluentProvider>, | ||
document.getElementById('root'), | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import * as React from 'react'; | ||
import { DetailsList, DetailsListLayoutMode, Selection, IColumn } from '@fluentui/react/lib/DetailsList'; | ||
import { ReactSelectorTreeComponentRenderer } from '../../shared/react/types'; | ||
|
||
interface DetailsListBasicExampleItem { | ||
file: string; | ||
author: string; | ||
lastUpdated: string; | ||
lastUpdate: string; | ||
} | ||
|
||
interface DetailsListBasicExampleState { | ||
items: DetailsListBasicExampleItem[]; | ||
} | ||
|
||
class DetailsListDataGridExample extends React.Component<{}, DetailsListBasicExampleState> { | ||
private _selection: Selection; | ||
private _allItems: DetailsListBasicExampleItem[]; | ||
private _columns: IColumn[]; | ||
|
||
constructor(props: {}) { | ||
super(props); | ||
|
||
this._selection = new Selection({}); | ||
const items = [ | ||
{ | ||
file: 'Meeting notes', | ||
author: 'Max Mustermann', | ||
lastUpdated: '7h ago', | ||
lastUpdate: 'You edited this', | ||
}, | ||
{ | ||
file: 'Thursday presentation', | ||
author: 'Erika Mustermann', | ||
lastUpdated: 'Yesterday at 1:45 PM', | ||
lastUpdate: 'You recently opened this', | ||
}, | ||
{ | ||
file: 'Training recording', | ||
author: 'John Doe', | ||
lastUpdated: 'Yesterday at 1:45 PM', | ||
lastUpdate: 'You recently opened this', | ||
}, | ||
{ | ||
file: 'Purchase order', | ||
author: 'Jane Doe', | ||
lastUpdated: 'Tue at 9:30 AM', | ||
lastUpdate: 'You shared this in a Teams chat', | ||
}, | ||
]; | ||
|
||
// Populate with items for demos. | ||
this._allItems = new Array(1).fill(0).map((_, i) => items[i % items.length]); | ||
|
||
this._columns = [ | ||
{ key: 'file', name: 'File', fieldName: 'file', minWidth: 150, maxWidth: 200 }, | ||
{ key: 'author', name: 'Author', fieldName: 'author', minWidth: 150, maxWidth: 200 }, | ||
{ key: 'lastUpdated', name: 'Last updated', fieldName: 'lastUpdated', minWidth: 150, maxWidth: 200 }, | ||
{ key: 'lastUpdate', name: 'Last update', fieldName: 'lastUpdate', minWidth: 150, maxWidth: 200 }, | ||
]; | ||
|
||
this.state = { | ||
items: this._allItems, | ||
}; | ||
} | ||
|
||
public render(): JSX.Element { | ||
const { items } = this.state; | ||
|
||
return ( | ||
<DetailsList | ||
items={items} | ||
columns={this._columns} | ||
setKey="set" | ||
layoutMode={DetailsListLayoutMode.justified} | ||
selection={this._selection} | ||
selectionPreservedOnEmptyClick={true} | ||
ariaLabelForSelectionColumn="Toggle selection" | ||
ariaLabelForSelectAllCheckbox="Toggle selection for all items" | ||
checkButtonAriaLabel="select row" | ||
/> | ||
); | ||
} | ||
} | ||
|
||
const componentRenderer: ReactSelectorTreeComponentRenderer = (node, depth, index) => { | ||
return <DetailsListDataGridExample />; | ||
}; | ||
|
||
export default componentRenderer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
import * as React from 'react'; | ||
import { ReactSelectorTreeComponentRenderer } from '../../shared/react/types'; | ||
import { useArrowNavigationGroup } from '@fluentui/react-components'; | ||
import { | ||
TableBody, | ||
TableCell, | ||
TableRow, | ||
Table, | ||
TableHeader, | ||
TableHeaderCell, | ||
TableSelectionCell, | ||
TableCellLayout, | ||
useTableFeatures, | ||
ColumnDefinition, | ||
useTableSelection, | ||
useTableSort, | ||
createColumn, | ||
ColumnId, | ||
} from '@fluentui/react-components/unstable'; | ||
|
||
const componentRenderer: ReactSelectorTreeComponentRenderer = (node, depth, index) => { | ||
return <DataGrid />; | ||
}; | ||
|
||
export default componentRenderer; | ||
|
||
type FileCell = { | ||
label: string; | ||
}; | ||
|
||
type LastUpdatedCell = { | ||
label: string; | ||
timestamp: number; | ||
}; | ||
|
||
type LastUpdateCell = { | ||
label: string; | ||
}; | ||
|
||
type AuthorCell = { | ||
label: string; | ||
}; | ||
|
||
type Item = { | ||
file: FileCell; | ||
author: AuthorCell; | ||
lastUpdated: LastUpdatedCell; | ||
lastUpdate: LastUpdateCell; | ||
}; | ||
|
||
const DataGrid = () => { | ||
const items = React.useMemo(() => { | ||
const baseItems: Item[] = [ | ||
{ | ||
file: { label: 'Meeting notes' }, | ||
author: { label: 'Max Mustermann' }, | ||
lastUpdated: { label: '7h ago', timestamp: 3 }, | ||
lastUpdate: { | ||
label: 'You edited this', | ||
}, | ||
}, | ||
{ | ||
file: { label: 'Thursday presentation' }, | ||
author: { label: 'Erika Mustermann' }, | ||
lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 }, | ||
lastUpdate: { | ||
label: 'You recently opened this', | ||
}, | ||
}, | ||
{ | ||
file: { label: 'Training recording' }, | ||
author: { label: 'John Doe' }, | ||
lastUpdated: { label: 'Yesterday at 1:45 PM', timestamp: 2 }, | ||
lastUpdate: { | ||
label: 'You recently opened this', | ||
}, | ||
}, | ||
{ | ||
file: { label: 'Purchase order' }, | ||
author: { label: 'Jane Doe' }, | ||
lastUpdated: { label: 'Tue at 9:30 AM', timestamp: 1 }, | ||
lastUpdate: { | ||
label: 'You shared this in a Teams chat', | ||
}, | ||
}, | ||
]; | ||
|
||
return new Array(15).fill(0).map((_, i) => baseItems[i % baseItems.length]); | ||
}, []); | ||
|
||
const columns: ColumnDefinition<Item>[] = React.useMemo( | ||
() => [ | ||
createColumn<Item>({ | ||
columnId: 'file', | ||
compare: (a, b) => { | ||
return a.file.label.localeCompare(b.file.label); | ||
}, | ||
}), | ||
createColumn<Item>({ | ||
columnId: 'author', | ||
compare: (a, b) => { | ||
return a.author.label.localeCompare(b.author.label); | ||
}, | ||
}), | ||
createColumn<Item>({ | ||
columnId: 'lastUpdated', | ||
compare: (a, b) => { | ||
return a.lastUpdated.timestamp - b.lastUpdated.timestamp; | ||
}, | ||
}), | ||
createColumn<Item>({ | ||
columnId: 'lastUpdate', | ||
compare: (a, b) => { | ||
return a.lastUpdate.label.localeCompare(b.lastUpdate.label); | ||
}, | ||
}), | ||
], | ||
[], | ||
); | ||
|
||
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: ColumnId) => ({ | ||
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"> | ||
<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>{item.file.label}</TableCellLayout> | ||
</TableCell> | ||
<TableCell tabIndex={0} role="gridcell"> | ||
<TableCellLayout>{item.author.label}</TableCellLayout> | ||
</TableCell> | ||
<TableCell tabIndex={0} role="gridcell"> | ||
{item.lastUpdated.label} | ||
</TableCell> | ||
<TableCell tabIndex={0} role="gridcell"> | ||
<TableCellLayout>{item.lastUpdate.label}</TableCellLayout> | ||
</TableCell> | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
); | ||
}; |