Skip to content
This repository was archived by the owner on Mar 4, 2020. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- Added sourcemaps to the dist output to simplify debugging @miroslavstastny ([#2329](https://github.com/microsoft/fluent-ui-react/pull/2329))
- Adding 'expand', 'collapse', 'companion', 'share-to' and 'settings-audio' icons @TanelVari ([#2343](https://github.com/microsoft/fluent-ui-react/pull/2343))
- Add support for Children API in `List` component @layershifter ([#2207](https://github.com/microsoft/fluent-ui-react/pull/2207))
- Added virtualized table prototype using `react-virtualized` and `Table` components @pompomon ([#2339](https://github.com/microsoft/fluent-ui-react/pull/2339))

### Performance
- Add styles caching when there aren't inline overrides defined @mnajdova ([#2309](https://github.com/microsoft/fluent-ui-react/pull/2309))
Expand Down
1 change: 1 addition & 0 deletions docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@types/node": "^10.3.2",
"@types/react-custom-scrollbars": "^4.0.5",
"@types/react-router-dom": "^4.3.4",
"@types/react-virtualized": "^9.21.8",
"@types/webpack-env": "^1.14.1",
"gulp": "^4.0.2"
},
Expand Down
5 changes: 5 additions & 0 deletions docs/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,11 @@ class Sidebar extends React.Component<any, any> {
},
public: true,
},
{
key: 'virtualized-table',
title: { content: 'VirtualizedTable', as: NavLink, to: '/virtualized-table' },
public: true,
},
]

const componentTreeSection = {
Expand Down
74 changes: 74 additions & 0 deletions docs/src/prototypes/VirtualizedTable/VirtualizedTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import {
gridCellBehavior,
gridHeaderCellBehavior,
gridNestedBehavior,
gridRowBehavior,
Table,
} from '@fluentui/react'
import * as React from 'react'
import {
AutoSizer,
List as ReactVirtualizedList,
ListRowRenderer,
ListProps,
} from 'react-virtualized'
import getItems from './itemsGenerator'

const { rows } = getItems()
const rowGetter = ({ index }) => {
return rows[index]
}

// Overrides ARIA attributes assigned by default, which break accessibility
const accessibilityListProperties: Partial<ListProps> = {
'aria-label': '',
'aria-readonly': undefined,
containerRole: 'presentation',
role: 'presentation',
}

const rowRenderer: ListRowRenderer = ({ index, style }) => {
const row = rows[index]
return (
<Table.Row
style={style}
key={row.key}
accessibility={gridRowBehavior}
aria-rowindex={index + 1}
>
<Table.Cell {...row.items[0]} accessibility={gridCellBehavior} />
<Table.Cell {...row.items[1]} accessibility={gridCellBehavior} />
<Table.Cell {...row.items[2]} accessibility={gridCellBehavior} />
<Table.Cell {...row.items[3]} accessibility={gridCellBehavior} />
</Table.Row>
)
}

const VirtualizedTablePrototype = () => (
<AutoSizer disableHeight>
{({ width }) => (
<Table accessibility={gridNestedBehavior} aria-rowcount={rows.length}>
<Table.Row header accessibility={gridRowBehavior} style={{ width }}>
<Table.Cell content="id" accessibility={gridHeaderCellBehavior} />
<Table.Cell content="Name" accessibility={gridHeaderCellBehavior} />
<Table.Cell content="Picture" accessibility={gridHeaderCellBehavior} />
<Table.Cell content="Age" accessibility={gridHeaderCellBehavior} />
</Table.Row>

<ReactVirtualizedList
disableHeader
height={400}
rowCount={rows.length}
width={width}
rowHeight={80}
rowGetter={rowGetter}
rowRenderer={rowRenderer}
overscanRowCount={5}
{...accessibilityListProperties}
/>
</Table>
)}
</AutoSizer>
)

export default VirtualizedTablePrototype
147 changes: 147 additions & 0 deletions docs/src/prototypes/VirtualizedTable/VirtualizedTables.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
import {
Accordion,
gridCellBehavior,
gridHeaderCellBehavior,
gridNestedBehavior,
gridRowBehavior,
Table,
} from '@fluentui/react'
import * as React from 'react'
import {
AutoSizer,
List as ReactVirtualizedList,
WindowScroller,
ListProps,
ListRowRenderer,
} from 'react-virtualized'
import getItems from './itemsGenerator'

// Magic offset for native scrollbar in Edge on Mac
const scrollbarOffset = 10

function VirtualizedTablesPrototype() {
const [ref, setRef] = React.useState(null)

const tables = [
{
key: 'table1',
title: <div>Table one</div>,
content: <VirtualizedTable scrollElementRef={ref} label={'table1'} />,
},
{
key: 'table2',
title: <div>Custom table title</div>,
content: <VirtualizedTable scrollElementRef={ref} label={'table2'} />,
},
]

return (
<div
id="scrollParent"
style={{ height: '700px', overflowY: 'auto' }}
ref={setRef}
tabIndex={-1}
role="none"
>
{ref && <Accordion panels={tables} />}
</div>
)
}

interface VirtualizedTableProps {
scrollElementRef: HTMLDivElement
label: string
}

const accessibilityListProperties: Partial<ListProps> = {
'aria-label': '',
'aria-readonly': undefined,
containerRole: 'presentation',
role: 'presentation',
tabIndex: null,
}

const accessibilityWrapperProperties: React.HTMLAttributes<HTMLDivElement> = {
'aria-label': '',
'aria-readonly': undefined,
role: 'presentation',
}

function VirtualizedTable(props: VirtualizedTableProps) {
const { header, rows } = getItems(20, 50)
const renderedItems = [header, ...rows]
const itemsCount = renderedItems.length

const rowGetter = ({ index }) => {
return renderedItems[index]
}

const rowRenderer: ListRowRenderer = ({ index, style }) => {
const row = renderedItems[index]
const header = row.key === 'header'
return (
<Table.Row
style={style}
key={row.key}
accessibility={gridRowBehavior}
aria-rowindex={index + 1}
header={header}
>
<Table.Cell
{...row.items[0]}
accessibility={header ? gridHeaderCellBehavior : gridCellBehavior}
/>
<Table.Cell
{...row.items[1]}
accessibility={header ? gridHeaderCellBehavior : gridCellBehavior}
/>
<Table.Cell
{...row.items[2]}
accessibility={header ? gridHeaderCellBehavior : gridCellBehavior}
/>
<Table.Cell
{...row.items[3]}
accessibility={header ? gridHeaderCellBehavior : gridCellBehavior}
/>
</Table.Row>
)
}

return (
<WindowScroller scrollElement={props.scrollElementRef} key={`${props.scrollElementRef}`}>
{({ height, isScrolling, registerChild, onChildScroll, scrollTop }) => (
<AutoSizer disableHeight>
{({ width }) => {
return height ? (
<Table
accessibility={gridNestedBehavior}
aria-rowcount={itemsCount}
aria-label={props.label}
>
<div ref={el => registerChild(el)} {...accessibilityWrapperProperties}>
<ReactVirtualizedList
autoHeight
disableHeader={true}
height={height}
rowCount={itemsCount}
width={width - scrollbarOffset}
onScroll={onChildScroll}
scrollTop={scrollTop}
rowHeight={80}
isScrolling={isScrolling}
rowGetter={rowGetter}
rowRenderer={rowRenderer}
overscanRowCount={20}
{...accessibilityListProperties}
/>
</div>
</Table>
) : null
}}
</AutoSizer>
)}
</WindowScroller>
)
}

export default VirtualizedTablesPrototype
48 changes: 48 additions & 0 deletions docs/src/prototypes/VirtualizedTable/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import * as React from 'react'
import VirtualizedTable from './VirtualizedTable'
import VirtualizedTables from './VirtualizedTables'
import { PrototypeSection, ComponentPrototype } from '../Prototypes'

export default () => (
<PrototypeSection title="VirtualizedTable">
<ComponentPrototype
title="Virtualized Table"
description="Single table with fixed header and its content virtualized using `react-virtualized`."
>
<VirtualizedTable />
</ComponentPrototype>
<ComponentPrototype
title="Two virtualized tables in an accordion"
description={
<>
<b>Notes:</b>
<br />
<span>
Prototype is using fixed row height, for dynamic height please check{' '}
<a href="https://github.com/bvaughn/react-virtualized/tree/master/source/CellMeasurer">
CellMeasurer component.
</a>
</span>
<br />
<b>Known issues:</b>
<br />
<b>Integration with React-custom-scrollbars. </b>
<span>
React-virtualized has{' '}
<a href="https://github.com/techniq/mui-downshift/issues/34">
an opened feature request
</a>{' '}
to support React-custom-scrollbars and there are a couple of ways to add custom
scrollbars to List component (see{' '}
<a href="https://github.com/bvaughn/react-virtualized/issues/143">issue one</a> and{' '}
<a href="https://github.com/bvaughn/react-virtualized/issues/692">issue two</a>).
Unfortunately, suggested solutions do not seem to work with two lists wrapped with
WindowScroller elements.
</span>
</>
}
>
<VirtualizedTables />
</ComponentPrototype>
</PrototypeSection>
)
47 changes: 47 additions & 0 deletions docs/src/prototypes/VirtualizedTable/itemsGenerator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import * as _ from 'lodash'

function getItems(minItems = 20, maxItems = 40) {
function getRandomNumber(minItems, maxItems) {
return _.random(minItems, maxItems)
}

function getRandomName() {
const names = ['Roman', 'Alex', 'Ali', 'Bo', 'Timbuktu', 'Daria', 'E.T.']
const addLongName = Math.random() > 0.5
return (
names[Math.floor(Math.random() * names.length)] +
(addLongName ? ' van von der Longername' : '')
)
}

function generateRows() {
const header = {
key: 'header',
items: [
{ content: 'id', key: 'id' },
{ content: 'Name', key: 'name' },
{ content: 'Picture', key: 'pic' },
{ content: 'Age', key: 'action' },
],
}
const rowsPlain = _.times(getRandomNumber(minItems, maxItems), index => ({
key: `${index}`,
items: [
{ content: `${index}`, key: `${index}-1` },
{
content: getRandomName(),
truncateContent: true,
key: `${index}-2`,
},
{ content: 'None', key: `${index}-3` },
{ content: `${getRandomNumber(10, 1000)} years`, key: `${index}-4` },
],
}))

return { header, rows: rowsPlain }
}

return generateRows()
}

export default getItems
2 changes: 2 additions & 0 deletions docs/src/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import CustomScrollbarPrototype from './prototypes/customScrollbar'
import EditorToolbarPrototype from './prototypes/EditorToolbar'
import HexagonalAvatarPrototype from './prototypes/hexagonalAvatar'
import TablePrototype from './prototypes/table'
import VirtualizedTablePrototype from './prototypes/VirtualizedTable'

const Routes = () => (
<BrowserRouter basename={__BASENAME__}>
Expand Down Expand Up @@ -90,6 +91,7 @@ const Routes = () => (
component={NestedPopupsAndDialogsPrototype}
/>
<Route exact path="/virtualized-tree" component={VirtualizedTreePrototype} />
<Route exact path="/virtualized-table" component={VirtualizedTablePrototype} />
<Route exact path="/prototype-copy-to-clipboard" component={CopyToClipboardPrototype} />
<Route exact path="/faq" component={FAQ} />
<Route exact path="/accessibility" component={Accessibility} />
Expand Down
Loading