From 9d18384b2df2f16481e191457b7191c0147b3c6e Mon Sep 17 00:00:00 2001 From: jeffvli Date: Fri, 21 Jul 2023 17:53:54 -0700 Subject: [PATCH] Add stickyHeader prop to table component --- .../hooks/use-fixed-table-header.tsx | 50 +++++--- .../components/virtual-table/index.tsx | 110 ++++++++++-------- 2 files changed, 93 insertions(+), 67 deletions(-) diff --git a/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx b/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx index b2d23c09..25842e28 100644 --- a/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx +++ b/src/renderer/components/virtual-table/hooks/use-fixed-table-header.tsx @@ -1,42 +1,54 @@ -import { useEffect, useRef } from 'react'; import { useInView } from 'framer-motion'; +import { useEffect, useRef } from 'react'; import { useWindowSettings } from '/@/renderer/store/settings.store'; import { Platform } from '/@/renderer/types'; -export const useFixedTableHeader = () => { - const intersectRef = useRef(null); +export const useFixedTableHeader = ({ enabled }: { enabled: boolean }) => { + const tableHeaderRef = useRef(null); const tableContainerRef = useRef(null); const { windowBarStyle } = useWindowSettings(); - const isNotPastTableIntersection = useInView(intersectRef, { - margin: - windowBarStyle === Platform.WEB || windowBarStyle === Platform.LINUX - ? '-68px 0px 0px 0px' - : '-98px 0px 0px 0px', + const topMargin = + windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS + ? '-128px' + : '-98px'; + + const isTableHeaderInView = useInView(tableHeaderRef, { + margin: `${topMargin} 0px 0px 0px`, }); - const tableInView = useInView(tableContainerRef, { - margin: '-128px 0px 0px 0px', + const isTableInView = useInView(tableContainerRef, { + margin: `${topMargin} 0px 0px 0px`, }); useEffect(() => { + if (!enabled) { + return; + } + const header = document.querySelector('main .ag-header'); const root = document.querySelector('main .ag-root'); - if (isNotPastTableIntersection || !tableInView) { - if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) { - header?.classList.remove('window-frame'); - } - header?.classList.remove('ag-header-fixed'); - root?.classList.remove('ag-header-fixed-margin'); - } else { + if (!isTableHeaderInView && isTableInView) { if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) { header?.classList.add('window-frame'); } header?.classList.add('ag-header-fixed'); root?.classList.add('ag-header-fixed-margin'); + } else if (!isTableInView) { + if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) { + header?.classList.remove('window-frame'); + } + header?.classList.remove('ag-header-fixed'); + root?.classList.remove('ag-header-fixed-margin'); + } else if (isTableHeaderInView) { + if (windowBarStyle === Platform.WINDOWS || windowBarStyle === Platform.MACOS) { + header?.classList.remove('window-frame'); + } + header?.classList.remove('ag-header-fixed'); + root?.classList.remove('ag-header-fixed-margin'); } - }, [isNotPastTableIntersection, tableInView, windowBarStyle]); + }, [enabled, isTableHeaderInView, isTableInView, windowBarStyle]); - return { intersectRef, tableContainerRef }; + return { tableContainerRef, tableHeaderRef }; }; diff --git a/src/renderer/components/virtual-table/index.tsx b/src/renderer/components/virtual-table/index.tsx index 8f4b4736..f855ccde 100644 --- a/src/renderer/components/virtual-table/index.tsx +++ b/src/renderer/components/virtual-table/index.tsx @@ -35,6 +35,7 @@ import { RatingCell } from '/@/renderer/components/virtual-table/cells/rating-ce import { TablePagination } from '/@/renderer/components/virtual-table/table-pagination'; import { ActionsCell } from '/@/renderer/components/virtual-table/cells/actions-cell'; import { TitleCell } from '/@/renderer/components/virtual-table/cells/title-cell'; +import { useFixedTableHeader } from '/@/renderer/components/virtual-table/hooks/use-fixed-table-header'; export * from './table-config-dropdown'; export * from './table-pagination'; @@ -43,12 +44,18 @@ export * from './hooks/use-click-outside-deselect'; export * from './utils'; const TableWrapper = styled.div` + position: relative; display: flex; flex-direction: column; width: 100%; height: 100%; `; +const DummyHeader = styled.div<{ height?: number }>` + position: absolute; + height: ${({ height }) => height || 36}px}; +`; + dayjs.extend(relativeTime); const tableColumns: { [key: string]: ColDef } = { @@ -371,6 +378,7 @@ export interface VirtualTableProps extends AgGridReactProps { pagination: TablePaginationType; setPagination: any; }; + stickyHeader?: boolean; transparentHeader?: boolean; } @@ -380,6 +388,7 @@ export const VirtualTable = forwardRef( autoFitColumns, deselectOnClickOutside, autoHeight, + stickyHeader, transparentHeader, onColumnMoved, onNewColumnsLoaded, @@ -467,55 +476,60 @@ export const VirtualTable = forwardRef( [autoFitColumns], ); + const { tableHeaderRef, tableContainerRef } = useFixedTableHeader({ + enabled: stickyHeader || false, + }); + + const mergedWrapperRef = useMergedRef(deselectRef, tableContainerRef); + return ( - <> - - - {paginationProps && ( - - - - )} - - + + + + {paginationProps && ( + + + + )} + ); }, );