Browse Source

update: table表头增加sticky

xyh 2 năm trước cách đây
mục cha
commit
6a26668d61

+ 1 - 1
packages/app/src/components/table/HeaderTh.tsx

@@ -24,7 +24,7 @@ const HeaderTh: FC<Props> = function({header, useDiv, isSecondLevel}) {
   const isResizing = header.column.getIsResizing();
 
   const style: CSSProperties = {
-    width: `${header.getSize()}px !important`,
+    width: `${header.column.getSize()}px`,
     cursor: isResizing ? 'col-resize' : disabledSort ? 'auto' : 'move',
     boxShadow: useDiv
       ? '0.5px 0.6px 12.3px rgba(0, 0, 0, 0.059),4px 5px 80px rgba(0, 0, 0, 0.1)'

+ 15 - 3
packages/app/src/components/table/hooks.tsx

@@ -5,7 +5,14 @@ import {
   Header,
   RowSelectionState,
 } from '@tanstack/react-table';
-import {Dispatch, SetStateAction, useEffect, useMemo, useState} from 'react';
+import {
+  Dispatch,
+  SetStateAction,
+  useEffect,
+  useMemo,
+  useRef,
+  useState,
+} from 'react';
 import {DragStartEvent, DragEndEvent} from '@dnd-kit/core';
 import {arrayMove} from '@dnd-kit/sortable';
 import {createTableSettingContext, useContextSection} from '@hooks';
@@ -198,16 +205,20 @@ export function useTable<T extends Record<string, any>>(
 
 export function useTableShadow(tableSize: number, id?: string) {
   const [isEnd, setIsEnd] = useState(false);
+  const scrollTableRef = useRef<HTMLDivElement>(null);
+  const headerTableRef = useRef<HTMLDivElement>(null);
 
   useEffect(
     function() {
-      const el = document.querySelector(`#${id ?? 'ld_table_wrapper'}`);
+      const el = scrollTableRef.current;
 
       function listener() {
         const elWidth = el?.getBoundingClientRect().width ?? 0,
               scrollWidth = el?.scrollWidth ?? 0,
               scrollLeft = el?.scrollLeft ?? 0;
 
+        headerTableRef.current!.scrollLeft = el?.scrollLeft ?? 0;
+
         setIsEnd(scrollLeft + elWidth >= scrollWidth);
       }
 
@@ -224,5 +235,6 @@ export function useTableShadow(tableSize: number, id?: string) {
     [id, tableSize],
   );
 
-  return isEnd;
+  return {isEnd, scrollTableRef, headerTableRef};
 }
+

+ 17 - 1
packages/app/src/components/table/index.css

@@ -1,6 +1,5 @@
 .ld-table-wrapper {
   width: 100%;
-  overflow: auto;
   border-inline-start: 1px solid var(--border-color-light);
   border-start-start-radius: var(--border-radius);
   border-start-end-radius: var(--border-radius);
@@ -43,6 +42,23 @@
   }
 }
 
+.ld-table-header-sticky {
+  position: sticky;
+  top: 0;
+  z-index: 1;
+  width: 100%;
+  overflow: hidden;
+}
+
+.ld-table-body-wrapper {
+  width: 100%;
+  overflow: auto;
+
+  & .ld-table {
+    border-top: 0;
+  }
+}
+
 .ld-table-enabled-fixed-shadow {
   & .ld-table-fixed-shadow {
     &::before {

+ 86 - 69
packages/app/src/components/table/index.tsx

@@ -75,8 +75,11 @@ function LDTable<T extends Record<string, any>>(props: Props<T>): ReactElement {
   });
 
   const sensor = useSensor(PointerSensor);
-
-  const isEnd = useTableShadow(getCenterTotalSize());
+  const {
+    isEnd,
+    scrollTableRef,
+    headerTableRef,
+  } = useTableShadow(getCenterTotalSize());
 
   return (
     <Spin spinning={isSearching}>
@@ -95,78 +98,92 @@ function LDTable<T extends Record<string, any>>(props: Props<T>): ReactElement {
             items={(columns).map(val => val.dataIndex.toString())}
             strategy={horizontalListSortingStrategy}
           >
-            <table
-              className={classNames('ld-table', {
-                'ld-table-enabled-fixed-shadow': !isEnd,
-              })}
-              style={{width: getCenterTotalSize()}}
-            >
-              <thead className="ld-table-head">
-                {getHeaderGroups().map(function({id, headers}) {
-                  return (
-                    <tr key={id}>
-                      {headers.map(header => (
-                        <HeaderTh key={header.id} header={header} />
-                      ))}
-                    </tr>
-                  );
+            <div className="ld-table-header-sticky" ref={headerTableRef}>
+              <table
+                className={classNames('ld-table', {
+                  'ld-table-enabled-fixed-shadow': !isEnd,
                 })}
-              </thead>
-              <tbody className="ld-table-body">
-                {getRowModel().rows.length > 0 ? (
-                  getRowModel().rows.map(function({id, getVisibleCells}) {
+                style={{width: getCenterTotalSize()}}
+              >
+                <thead className="ld-table-head">
+                  {getHeaderGroups().map(function({id, headers}) {
                     return (
                       <tr key={id}>
-                        {getVisibleCells().map(function({
-                          id,
-                          column,
-                          getContext,
-                        }) {
-                          const {align, fixed} = column.columnDef.meta as {
-                            align?: 'left' | 'center' | 'right';
-                            fixed: boolean;
-                          };
-                          return (
-                            <td
-                              key={id}
-                              className={classNames({
-                                'ld-table-fixed-right ld-table-fixed-shadow': fixed,
-                              })}
-                              style={{
-                                width: column.getSize(),
-                                textAlign: align ?? 'left',
-                              }}
-                            >
-                              {flexRender(column.columnDef.cell, getContext())}
-                            </td>
-                          );
-                        })}
+                        {headers.map(header => (
+                          <HeaderTh key={header.id} header={header} />
+                        ))}
                       </tr>
                     );
-                  })
-                ) : (
-                  <tr>
-                    <td
-                      colSpan={getHeaderGroups()[0].headers.length}
-                      style={{padding: 0}}
-                    >
-                      <Empty
-                        image={Empty.PRESENTED_IMAGE_SIMPLE}
-                        style={{
-                          width: '400px',
-                          position: 'sticky',
-                          left: '50%',
-                          transform: 'translateX(-50%)',
-                          overflow: 'hidden',
-                          margin: 0,
-                          padding: '50px 10px',
-                        }}
-                      />
-                    </td>
-                  </tr>
-                )}
-              </tbody>
-            </table>
+                  })}
+                </thead>
+              </table>
+            </div>
+            <div className="ld-table-body-wrapper" ref={scrollTableRef}>
+              <table
+                className={classNames('ld-table', {
+                  'ld-table-enabled-fixed-shadow': !isEnd,
+                })}
+                style={{width: getCenterTotalSize()}}
+              >
+                <tbody className="ld-table-body">
+                  {getRowModel().rows.length > 0 ? (
+                    getRowModel().rows.map(function({id, getVisibleCells}) {
+                      return (
+                        <tr key={id}>
+                          {getVisibleCells().map(function({
+                            id,
+                            column,
+                            getContext,
+                          }) {
+                            const {align, fixed} = column.columnDef.meta as {
+                              align?: 'left' | 'center' | 'right';
+                              fixed: boolean;
+                            };
+                            return (
+                              <td
+                                key={id}
+                                className={classNames({
+                                  'ld-table-fixed-right ld-table-fixed-shadow': fixed,
+                                })}
+                                style={{
+                                  width: column.getSize(),
+                                  textAlign: align ?? 'left',
+                                }}
+                              >
+                                {flexRender(
+                                  column.columnDef.cell,
+                                  getContext(),
+                                )}
+                              </td>
+                            );
+                          })}
+                        </tr>
+                      );
+                    })
+                  ) : (
+                    <tr>
+                      <td
+                        colSpan={getHeaderGroups()[0].headers.length}
+                        style={{padding: 0}}
+                      >
+                        <Empty
+                          image={Empty.PRESENTED_IMAGE_SIMPLE}
+                          style={{
+                            width: '400px',
+                            position: 'sticky',
+                            left: '50%',
+                            transform: 'translateX(-50%)',
+                            overflow: 'hidden',
+                            margin: 0,
+                            padding: '50px 10px',
+                          }}
+                        />
+                      </td>
+                    </tr>
+                  )}
+                </tbody>
+              </table>
+            </div>
             <DragOverlay>
               {active ? (
                 <HeaderTh