Skip to content

Roman86/tanstack-table-header-rowspan

Repository files navigation

What

Rowspan thing for headless React Table from Tanstack. See the discussion TanStack/table#5051.

Works for both header and footer: demo

How

Just call it when you render your header (or footer) <th> elements, pass the header object there and get attributes to apply on your <th> element.

It handles nested groups and columns automatically.

❤️ Enjoying this package? Consider buying me a coffee as a token of appreciation!

Buy Me A Coffee

Usage with standard "display: table" approach for header

<table>
  <thead>
  {table.getHeaderGroups().map((headerGroup) => (
    <tr key={headerGroup.id}>
      {headerGroup.headers.map((header) => {
        // notice the function name we pick here
        const rowSpan = tableHeaderRowSpan(header);
        if (!rowSpan) {
          // it's necessary to skip redundant cells
          return null;
        }
        return (
          <th
            className={'border border-black/20 bg-gray-100 px-2'}
            colSpan={header.colSpan}
            rowSpan={rowSpan}
            style={{
              width: header.getSize(),
            }}
          >
            {flexRender(header.column.columnDef.header, header.getContext())}
          </th>);
      })}
    </tr>
  ))}
  </thead>
  <!-- ... -->

Usage with standard "display: table" approach for footer

<table>
  <!-- ... -->
  <tfoot>
  {table.getFooterGroups().map((footerGroup) => (
    <tr key={footerGroup.id}>
      {footerGroup.headers.map((header) => {
        // notice the function name we pick here
        const rowSpan = tableFooterRowSpan(header);
        if (!rowSpan) {
          // it's also necessary to skip redundant cells
          return null;
        }
        return (
          <th
            colSpan={header.colSpan}
            rowSpan={rowSpan}
            className={'border border-black/20 bg-gray-100'}
          >
            {flexRender(header.column.columnDef.header, header.getContext())}
          </th>
        );
      })}
    </tr>
  ))}
  </tfoot>

Usage with "display: flex" (or block or grid, whatever non-table) approach for header

<table>
  <thead>
  {table.getHeaderGroups().map((headerGroup) => (
    <tr key={headerGroup.id} className={'group/row flex'}>
      {headerGroup.headers.map((header) => {
        const rowSpan = flexTableHeaderRowSpan(header);
        return (
          <th
            className={clsx(
              'group-first/row:border-t border-b border-e first:border-s border-black/20 bg-gray-100 px-2',
              'flex items-center justify-center',
              rowSpan.topBorderMightBeNeeded && 'border-t',
            )}
            style={{
              ...rowSpan.styles('2rem'), // you have to put the height of single header row here
              width: header.getSize(),
            }}
          >
            {flexRender(header.column.columnDef.header, header.getContext())}
          </th>
        );
      })}
    </tr>
  ))}
  </thead>
<!-- ... -->

Usage with "display: flex" (or block or grid, whatever non-table) approach for footer

<table>
  <!-- ... -->
  <tfoot>
  {table.getFooterGroups().map((footerGroup) => (
    <tr key={footerGroup.id} className={'group/row flex'}>
      {footerGroup.headers.map((header) => {
        // notice the function name we pick here
        const rowSpan = flexTableFooterRowSpan(header);
        return (
          <th
            data-test-rowspan={header.column.columnDef.meta?.testRowSpan}
            className={clsx(
              'border-t group-last/row:border-b border-e first:border-s border-black/20 bg-gray-100',
              'flex items-center justify-center',
              rowSpan.bottomBorderMightBeNeeded && 'border-b',
            )}
            style={{
              ...rowSpan.styles('2rem'),
              width: header.getSize(),
            }}
          >
            {flexRender(header.column.columnDef.header, header.getContext())}
          </th>
        );
      })}
    </tr>
  ))}
  </tfoot>

About

Rowspan for TanStack Table headers

Resources

License

Security policy

Stars

Watchers

Forks

Packages

No packages published