Skip to content

Commit

Permalink
feat: Restore column auto-sizing for Tables when not scrolling (#546)
Browse files Browse the repository at this point in the history
  • Loading branch information
dogmar authored Dec 5, 2023
1 parent 44603f9 commit b00948e
Show file tree
Hide file tree
Showing 4 changed files with 969 additions and 1,184 deletions.
26 changes: 13 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
"@react-stately/utils": "3.9.0",
"@react-types/shared": "3.22.0",
"@tanstack/match-sorter-utils": "8.8.4",
"@tanstack/react-table": "8.9.3",
"@tanstack/react-virtual": "3.0.0-beta.68",
"@tanstack/react-table": "8.10.7",
"@tanstack/react-virtual": "3.0.1",
"@types/chroma-js": "2.4.0",
"@types/lodash-es": "4.17.8",
"babel-plugin-styled-components": "2.1.4",
Expand Down Expand Up @@ -74,16 +74,16 @@
"@emotion/react": "11.11.1",
"@emotion/styled": "11.11.0",
"@pluralsh/eslint-config-typescript": "2.5.112",
"@storybook/addon-actions": "7.4.0",
"@storybook/addon-docs": "7.4.0",
"@storybook/addon-essentials": "7.4.0",
"@storybook/addon-interactions": "7.4.0",
"@storybook/addon-links": "7.4.0",
"@storybook/builder-vite": "7.4.0",
"@storybook/node-logger": "7.4.0",
"@storybook/react": "7.4.0",
"@storybook/react-vite": "7.4.0",
"@storybook/testing-library": "0.2.0",
"@storybook/addon-actions": "7.6.3",
"@storybook/addon-docs": "7.6.3",
"@storybook/addon-essentials": "7.6.3",
"@storybook/addon-interactions": "7.6.3",
"@storybook/addon-links": "7.6.3",
"@storybook/builder-vite": "7.6.3",
"@storybook/node-logger": "7.6.3",
"@storybook/react": "7.6.3",
"@storybook/react-vite": "7.6.3",
"@storybook/testing-library": "0.2.2",
"@testing-library/jest-dom": "5.17.0",
"@types/react-dom": "18.2.15",
"@types/react-transition-group": "4.4.9",
Expand Down Expand Up @@ -117,7 +117,7 @@
"react-dom": "18.2.0",
"react-transition-group": "4.4.5",
"rimraf": "5.0.1",
"storybook": "7.5.1",
"storybook": "7.6.3",
"styled-components": "5.3.11",
"typescript": "5.2.2",
"vite": "4.5.0",
Expand Down
84 changes: 49 additions & 35 deletions src/components/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export type TableProps = Omit<
stickyColumn?: boolean
scrollTopMargin?: number
virtualizeRows?: boolean
lockColumnsOnFirstScroll?: boolean
lockColumnsOnScroll?: boolean
reactVirtualOptions?: Partial<
Omit<Parameters<typeof useVirtualizer>[0], 'count' | 'getScrollElement'>
>
Expand All @@ -83,11 +83,16 @@ export type TableProps = Omit<
fetchNextPage?: () => void
isFetchingNextPage?: boolean
onVirtualSliceChange?: (slice: {
start: VirtualItem
end: VirtualItem
start: VirtualItem | undefined
end: VirtualItem | undefined
}) => void
}

type VirtualSlice = {
start: VirtualItem | undefined
end: VirtualItem | undefined
}

const propTypes = {}

function getGridTemplateCols(columnDefs: ColumnDef<unknown>[] = []): string {
Expand Down Expand Up @@ -444,20 +449,30 @@ function FillerRows({
)
}

function useOnFirstScroll(
function useIsScrolling(
ref: MutableRefObject<HTMLElement>,
onFirstScroll: () => void
{
onIsScrollingChange: onScrollingChange,
restDelay = 350,
}: { onIsScrollingChange: (isScrolling: boolean) => void; restDelay?: number }
) {
const [hasScrolled, setHasScrolled] = useState(false)
const [isScrolling, setIsScrolling] = useState(false)
const timeout = useRef<number | null>(null)

useEffect(() => {
if (!hasScrolled && ref.current) {
onScrollingChange?.(isScrolling)
}, [isScrolling, onScrollingChange])

useEffect(() => {
if (ref.current) {
const el = ref.current

const scrollHandler = () => {
setHasScrolled(true)

onFirstScroll()
setIsScrolling(true)
window.clearTimeout(timeout.current)
timeout.current = window.setTimeout(() => {
setIsScrolling(false)
}, restDelay)
}

el.addEventListener('scroll', scrollHandler, { passive: true })
Expand All @@ -466,7 +481,7 @@ function useOnFirstScroll(
el.removeEventListener('scroll', scrollHandler)
}
}
}, [hasScrolled, onFirstScroll, ref])
}, [ref, restDelay])
}

function useOnVirtualSliceChange({
Expand All @@ -476,13 +491,10 @@ function useOnVirtualSliceChange({
}: {
virtualRows: VirtualItem[]
virtualizeRows: boolean
onVirtualSliceChange: (slice: {
start: VirtualItem
end: VirtualItem
}) => void
onVirtualSliceChange: (slice: VirtualSlice) => void
}) {
const sliceStartRow = virtualRows[0]
const sliceEndRow = virtualRows[virtualRows.length - 1]
const sliceEndRow: VirtualItem = virtualRows[virtualRows.length - 1]
const prevSliceStartRow = usePrevious(virtualRows[0])
const prevSliceEndRow = usePrevious(virtualRows[virtualRows.length - 1])

Expand Down Expand Up @@ -514,7 +526,7 @@ function TableRef(
scrollTopMargin = 500,
width,
virtualizeRows = false,
lockColumnsOnFirstScroll,
lockColumnsOnScroll,
reactVirtualOptions,
reactTableOptions,
onRowClick,
Expand Down Expand Up @@ -591,30 +603,32 @@ function TableRef(

useOnVirtualSliceChange({ virtualRows, virtualizeRows, onVirtualSliceChange })

lockColumnsOnFirstScroll = lockColumnsOnFirstScroll ?? virtualizeRows
useOnFirstScroll(
tableContainerRef,
useCallback(() => {
if (lockColumnsOnFirstScroll) {
const thCells = tableContainerRef.current?.querySelectorAll('th')
lockColumnsOnScroll = lockColumnsOnScroll ?? virtualizeRows
useIsScrolling(tableContainerRef, {
onIsScrollingChange: useCallback(
(isScrolling) => {
if (lockColumnsOnScroll) {
const thCells = tableContainerRef.current?.querySelectorAll('th')

const columns = Array.from(thCells)
.map((th) => {
const { width } = th.getBoundingClientRect()
const columns = Array.from(thCells)
.map((th) => {
const { width } = th.getBoundingClientRect()

return `${width}px`
})
.join(' ')
return `${width}px`
})
.join(' ')

setFixedGridTemplateColumns(columns)
}
}, [lockColumnsOnFirstScroll])
)
setFixedGridTemplateColumns(isScrolling ? columns : null)
}
},
[lockColumnsOnScroll]
),
})
useEffect(() => {
if (!lockColumnsOnFirstScroll) {
if (!lockColumnsOnScroll) {
setFixedGridTemplateColumns(null)
}
}, [lockColumnsOnFirstScroll])
}, [lockColumnsOnScroll])

const { paddingTop, paddingBottom } = useMemo(
() => ({
Expand Down
6 changes: 4 additions & 2 deletions src/stories/Table.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,10 @@ const columns = [
}),
columnHelper.accessor((row) => row.returnedValue, {
id: 'returnedValue',
cell: (info: any) => <span>{info.getValue()}</span>,
header: () => <span>Returned value</span>,
cell: (info) => (
<span>{info.row.index % 30 === 0 ? info.getValue() : null}</span>
),
header: () => <span>Type</span>,
}),
columnHelper.accessor((row) => row.description, {
id: 'description',
Expand Down
Loading

0 comments on commit b00948e

Please sign in to comment.