在顶部粘性 thead > th's 和左侧粘性 tbody> td's 中使用工具提示组件

问题描述 投票:0回答:1

我有一个使用

@tanstack/react-table
的表格,并使用 ShadCN Table Component 进行样式设置,并对粘性功能和 ShadCN Tooltip Component

进行了一些调整

我将

Thead
(
th
) 中的所有
TableHeader
(
thead
) 组件粘在顶部。因此,当用户垂直滚动表格时,
Thead
(
th
) 会粘在顶部。

我将第一列

TableCell
的 (
td
) 粘在左侧。因此,当用户水平滚动表格时,该列的数据会粘在左侧。

问题是,为了使这项工作有效,我需要在各个元素上添加

z-index
,因此工具提示要么卡在
Thead
或其他
TableCell
后面。所以,不太确定如何同时拥有粘性的
Thead
TableCell
以及
Tooltips

如果您想尝试一下,这里有一个 StackBlitz 环境 可以重现问题?

Screenshot 2023-12-09 213945 Screenshot 2023-12-09 213911

Tanstack 柱

const Header: React.FC<{ title: string }> = ({ title }) => (
  <div className="font-bold min-w-[300px] bg-slate-300 h-16 flex justify-center items-center">
    {title}
  </div>
);

//////
{
  accessorFn: (row) => `${row.firstName} ${row.lastName}`,
  id: 'fullName',
  header: () => <Header title="Name" />,
  cell: (info) => {
    return (
      <div className="font-bold min-w-[300px]">
        <TooltipProvider>
          <Tooltip defaultOpen={info.row.index === 0}>
            <TooltipTrigger asChild>
              <span>{info.getValue()}</span>
            </TooltipTrigger>
            <TooltipContent className="max-w-[200px] w-full min-w-[150px]">
              <p>This</p>
              <p>Is</p>
              <p>A</p>
              <p>Tooltip</p>
              <p>Test</p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>
      </div>
    );
  },
  footer: (props) => props.column.id,
  meta: {
    sticky: true,
    stickyLeft: true,
  },
},

表.tsx

import { cn } from '@/lib/utils';
import { type ColumnMeta } from '@tanstack/react-table';
import * as React from 'react';

export interface TableProps extends React.HTMLAttributes<HTMLTableElement> {
  tableClassName?: string;
}

const Table = React.forwardRef<HTMLTableElement, TableProps>(({ className, tableClassName, ...props }, ref) => (
  <div className={cn('w-full overflow-x-auto data-table-container border rounded-md', className)}>
    <table ref={ref} className={cn('w-full caption-bottom text-sm relative data-table', tableClassName)} {...props} />
  </div>
));
Table.displayName = 'Table';

const TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(({ className, ...props }, ref) => (
  <thead ref={ref} className={cn(className)} {...props} />
));
TableHeader.displayName = 'TableHeader';

const TableBody = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(({ className, ...props }, ref) => (
  <tbody ref={ref} className={cn(className)} {...props} />
));
TableBody.displayName = 'TableBody';

const TableFooter = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(({ className, ...props }, ref) => (
  <tfoot ref={ref} className={cn('bg-primary font-medium text-primary-foreground', className)} {...props} />
));
TableFooter.displayName = 'TableFooter';

export interface TableRowProps extends React.HTMLAttributes<HTMLTableRowElement> {
  isLoading?: boolean;
  noHover?: boolean;
}

const TableRow = React.forwardRef<HTMLTableRowElement, TableRowProps>(({ className, isLoading, noHover, ...props }, ref) => (
  <tr
    ref={ref}
    className={cn('transition-colors', !isLoading && '[&>*]:data-[state=selected]:bg-muted', !noHover && !isLoading && '[&>*]:hover:bg-muted', className)}
    {...props}
  />
));
TableRow.displayName = 'TableRow';

export interface TableHeadProps<TData, TValue> extends React.ThHTMLAttributes<HTMLTableCellElement>, ColumnMeta<TData, TValue> {
  isLoading?: boolean;
  last?: boolean;
}

const TableHead = React.forwardRef<HTMLTableCellElement, TableHeadProps<any, any>>(
  ({ className, sticky, stickyLeft, stickyRight, isLoading, last, ...props }, ref) => {
    return (
      <th
        ref={ref}
        className={cn(
          'h-10 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] relative',
          sticky && 'sticky -top-[1px] z-[7] bg-background',
          stickyLeft && 'sticky -left-[1px] z-[9] bg-background',
          stickyRight && 'sticky -right-[1px] z-[9] bg-background',
          stickyRight && last && 'z-[8]',
          isLoading && 'min-w-[100px]',
          className,
        )}
        {...props}
      />
    );
  },
);
TableHead.displayName = 'TableHead';

export interface TableCellProps<TData, TValue> extends React.TdHTMLAttributes<HTMLTableCellElement>, ColumnMeta<TData, TValue> {}

const TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps<any, any>>(({ className, sticky, stickyLeft, stickyRight, ...props }, ref) => (
  <td
    ref={ref}
    className={cn(
      'table-cell px-4 py-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px] relative',
      sticky && 'sticky -right-[1px] z-[5] bg-background',
      stickyLeft && 'sticky -left-[1px] z-[6] bg-background',
      stickyRight && 'sticky -right-[1px] z-[5] bg-background',
      className,
    )}
    {...props}
  />
));
TableCell.displayName = 'TableCell';

const TableCaption = React.forwardRef<HTMLTableCaptionElement, React.HTMLAttributes<HTMLTableCaptionElement>>(({ className, ...props }, ref) => (
  <caption ref={ref} className={cn('mt-4 text-sm text-muted-foreground', className)} {...props} />
));
TableCaption.displayName = 'TableCaption';

export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };

任何帮助将不胜感激!

css tailwind-css react-table tanstack radix-ui
1个回答
0
投票

您可以考虑在悬停时增加单元格的

z-index
,因为这可能是工具提示显示时:

<TableCell
  …
  hasTooltip={cell.getContext().column.columnDef.id === 'fullName'}
>
const TableCell = React.forwardRef<HTMLTableCellElement, TableCellProps<any, any>>(({ …, hasTooltip, … }, ref) => (
  <td
    ref={ref}
    className={cn(
      …
      hasTooltip && 'hover:z-10',
      …
    )}
    {...props}
  />
));

尽管您仍然会遇到一些卡顿行为,例如当悬停的单元格部分位于应位于顶部的不同单元格后面时:

查看此解决方案的 Stackblitz 分支

否则,您可以考虑使用 Portals 在表格外渲染工具提示元素,这样在 z 堆栈中组织元素会更容易,尽管我不确定 Shadcn/Radix Tooltip 组件与这种方法。

© www.soinside.com 2019 - 2024. All rights reserved.