Published on

Using Tooltips with Sticky Table Headers and Cells in React

Authors
  • Name
    Ripal & Zalak
    Twitter

Using Tooltips with Sticky Table Headers and Cells in React

When building tables with sticky headers and columns, integrating interactive elements like tooltips can lead to layout challenges, particularly with z-index management. This guide walks through the steps to seamlessly integrate tooltips in sticky table headers and cells using ShadCN, Radix UI, and @tanstack/react-table.

Common Challenges

  1. Z-Index Conflicts: Sticky headers (thead > th) and cells (tbody > td) often overlap tooltip content.
  2. Tooltip Visibility: Tooltips can appear behind sticky elements or other cells.
  3. Compatibility Issues: Ensuring ShadCN and Radix Tooltip components work within complex table layouts.

Solution Overview

We’ll cover:

  • Structuring the table with @tanstack/react-table.
  • Styling sticky headers and cells with Tailwind CSS.
  • Solving z-index conflicts using Radix UI Portals and conditional styling.

Implementation

Table Setup with Sticky Headers and Cells

Here’s a simplified setup using ShadCN components and Tailwind CSS for styling.

import React from 'react'
import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from './table' // ShadCN Table Components
import { Tooltip, TooltipProvider, TooltipTrigger, TooltipContent } from './tooltip'

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

const columns = [
  {
    accessorKey: 'name',
    header: () => <Header title="Name" />,
    cell: (info) => (
      <div className="min-w-[300px] font-bold">
        <TooltipProvider>
          <Tooltip>
            <TooltipTrigger asChild>
              <span>{info.getValue()}</span>
            </TooltipTrigger>
            <TooltipContent className="w-full min-w-[150px] max-w-[200px]">
              <p>Tooltip Content</p>
            </TooltipContent>
          </Tooltip>
        </TooltipProvider>
      </div>
    ),
    meta: { sticky: true, stickyLeft: true },
  },
]

const MyTable = ({ data }) => (
  <Table>
    <TableHeader>
      <TableRow>
        {columns.map((col, index) => (
          <TableHead key={index} sticky stickyLeft={col.meta?.stickyLeft}>
            {col.header()}
          </TableHead>
        ))}
      </TableRow>
    </TableHeader>
    <TableBody>
      {data.map((row, rowIndex) => (
        <TableRow key={rowIndex}>
          {columns.map((col, colIndex) => (
            <TableCell key={colIndex} stickyLeft={col.meta?.stickyLeft}>
              {col.cell({ getValue: () => row[col.accessorKey] })}
            </TableCell>
          ))}
        </TableRow>
      ))}
    </TableBody>
  </Table>
)

export default MyTable

Solving Z-Index Issues with Radix UI Portals

Radix UI’s Tooltip.Portal helps ensure tooltips render outside the table’s DOM hierarchy, avoiding z-index conflicts.

import * as TooltipPrimitive from '@radix-ui/react-tooltip'

const Tooltip = ({ children, content }) => (
  <TooltipPrimitive.Root>
    <TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>
    <TooltipPrimitive.Portal>
      <TooltipPrimitive.Content className="z-50 rounded-md bg-black p-2 text-white">
        {content}
      </TooltipPrimitive.Content>
    </TooltipPrimitive.Portal>
  </TooltipPrimitive.Root>
)

Additional Tips

  1. Hover Z-Index Adjustment: Adjust z-index on hover to temporarily elevate the sticky cell.

    const TableCell = React.forwardRef((props, ref) => (
      <td ref={ref} className="relative hover:z-10" {...props} />
    ))
    
  2. Portal Customization: Use TooltipContent's sideOffset and align properties for precise positioning.

FAQs

Why use Radix UI Portals?

Portals allow tooltip content to render outside restrictive parent containers, avoiding z-index issues common with sticky elements.

Can I use this with other table libraries?

Yes! While this example uses @tanstack/react-table, the principles apply universally.

How to test for z-index issues?

Use browser developer tools to inspect z-index stacking contexts during hover and scrolling interactions.

Conclusion

Integrating tooltips in sticky table headers and cells can be challenging, but with ShadCN components, Radix UI Portals, and strategic z-index management, you can create a seamless user experience. Try the provided code snippets to enhance your table interactions.