refactor(dev-only): table deferred loading and aria improvements

This commit is contained in:
Aman Harwara
2022-12-26 12:34:06 +05:30
parent 0f7b1539e0
commit 6bf6924a8b
3 changed files with 29 additions and 3 deletions

View File

@@ -43,6 +43,7 @@ export type Table<Data> = {
handleRowDoubleClick: (id: string) => MouseEventHandler<HTMLTableRowElement>
handleRowContextMenu: (id: string) => MouseEventHandler<HTMLTableRowElement>
canSelectRows: boolean
canSelectMultipleRows: boolean
selectedRows: string[]
selectionActions: ReactNode | undefined
showSelectionActions: boolean

View File

@@ -1,5 +1,5 @@
import { classNames } from '@standardnotes/snjs'
import { useState } from 'react'
import { useCallback, useState } from 'react'
import Icon from '../Icon/Icon'
import { Table, TableRow } from './CommonTypes'
@@ -26,6 +26,7 @@ function TableRow<Data>({
<div
role="row"
aria-rowindex={rowIndex + 2}
{...(canSelectRows ? { 'aria-selected': row.isSelected } : {})}
className="group relative contents"
onMouseEnter={() => {
setIsHovered(true)
@@ -75,7 +76,27 @@ function TableRow<Data>({
)
}
const MinTableRowHeight = 41
const MinRowsToDisplay = 20
const PageSize = Math.ceil(document.documentElement.clientHeight / MinTableRowHeight) || MinRowsToDisplay
const PageScrollThreshold = 200
function Table<Data>({ table }: { table: Table<Data> }) {
const [rowsToDisplay, setRowsToDisplay] = useState<number>(PageSize)
const paginate = useCallback(() => {
setRowsToDisplay((cellsToDisplay) => cellsToDisplay + PageSize)
}, [])
const onScroll = useCallback(
(event: React.UIEvent<HTMLDivElement, UIEvent>) => {
const offset = PageScrollThreshold
const element = event.target as HTMLElement
if (element.scrollTop + element.offsetHeight >= element.scrollHeight - offset) {
paginate()
}
},
[paginate],
)
const {
headers,
rows,
@@ -87,11 +108,12 @@ function Table<Data>({ table }: { table: Table<Data> }) {
selectedRows,
selectionActions,
canSelectRows,
canSelectMultipleRows,
showSelectionActions,
} = table
return (
<div className="block min-h-0 overflow-auto">
<div className="block min-h-0 overflow-auto" onScroll={onScroll}>
{showSelectionActions && selectedRows.length >= 2 && (
<div className="flex items-center justify-between border-b border-border px-3 py-2">
<span className="text-info-0 text-sm font-medium">{selectedRows.length} selected</span>
@@ -103,6 +125,7 @@ function Table<Data>({ table }: { table: Table<Data> }) {
role="grid"
aria-colcount={colCount}
aria-rowcount={rowCount}
aria-multiselectable={canSelectMultipleRows}
>
<div role="row" aria-rowindex={1} className="contents">
{headers
@@ -139,7 +162,7 @@ function Table<Data>({ table }: { table: Table<Data> }) {
})}
</div>
<div className="contents whitespace-nowrap">
{rows.map((row, index) => (
{rows.slice(0, rowsToDisplay).map((row, index) => (
<TableRow
row={row}
key={row.id}

View File

@@ -195,11 +195,13 @@ export function useTable<Data>({
handleRowContextMenu,
selectedRows,
canSelectRows: enableRowSelection || false,
canSelectMultipleRows: enableMultipleRowSelection || false,
selectionActions: selectionActions ? selectionActions(selectedRows) : undefined,
showSelectionActions: showSelectionActions || false,
}),
[
colCount,
enableMultipleRowSelection,
enableRowSelection,
handleRowClick,
handleRowContextMenu,