table icon indicating copy to clipboard operation
table copied to clipboard

There is space between adjacent pinned columns

Open pintuiitbhi opened this issue 1 year ago • 11 comments

TanStack Table version

v8.13.2

Framework/Library version

React 18

Describe the bug and the steps to reproduce it

Image

There is space between the first two pinned column.

This is the common pinning style code

`import { Column } from "@tanstack/react-table" import { ListingType } from "./columns" import { CSSProperties } from "react"

export const getCommonPinningStyles = (column: Column<ListingType>): CSSProperties => { const isPinned = column.getIsPinned() const isLastLeftPinnedColumn = isPinned === 'left' && column.getIsLastColumn('left') const isFirstRightPinnedColumn = isPinned === 'right' && column.getIsFirstColumn('right')

return {
    boxShadow: isLastLeftPinnedColumn
        ? '-2px 0 2px -2px gray inset'
        : isFirstRightPinnedColumn
            ? '2px 0 2px -2px gray inset'
            : undefined,
    left: isPinned === 'left' ? `${column.getStart('left')}px` : undefined,
    right: isPinned === 'right' ? `${column.getAfter('right')}px` : undefined,
    opacity: isPinned ? 0.95 : 1,
    position: isPinned ? 'sticky' : 'relative',
    width: `${column.getSize()}rem`,
    zIndex: isPinned ? 1 : 0,
    padding: '5px 20px',
    border: "1px solid red",
}

} `

This is column def { id: "select", header: ({ table }) => ( <IndeterminateCheckbox checked={table.getIsAllRowsSelected()} indeterminate={table.getIsSomeRowsSelected()} onChange={table.getToggleAllRowsSelectedHandler()} /> ), cell: ({ row }) => ( <IndeterminateCheckbox checked={row.getIsSelected()} disabled={!row.getCanSelect()} indeterminate={row.getIsSomeSelected()} onChange={row.getToggleSelectedHandler()} /> ), enableSorting: false, enableHiding: false, }, { accessorKey: "state", id: "state", header: "State", cell: (info) => info.getValue() || "-", },

This is table defintion

const table: TanstackTable<TData> = useReactTable({ data, columns: columns as any, // @TODO: fix typescript defaultColumn: { size: 100, //starting column size // minSize: 50, //enforced during column resizing // maxSize: 200, //enforced during column resizing }, onRowSelectionChange: setRowSelection, pageCount: pageCount ?? -1, enableRowSelection: true, getCoreRowModel: getCoreRowModel(), getFilteredRowModel: getFilteredRowModel(), onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, onColumnVisibilityChange: setColumnVisibility, getSortedRowModel: getSortedRowModel(), state: { pagination: { pageIndex, pageSize }, rowSelection, sorting, columnVisibility, columnFilters, }, initialState: { columnPinning: { left: ['select', 'state'], right: ['status', 'actions'], }, }, columnResizeMode: 'onChange', onPaginationChange: setPagination, getPaginationRowModel: getPaginationRowModel(), manualPagination: true, manualFiltering: true, meta: { // removeRow: (rowIndex: number) => { // deleteRow(data[rowIndex].id); // }, // removeSelectedRows: (selectedRows: number[]) => { // selectedRows.forEach((rowIndex) => { // deleteRow(data[rowIndex].id); // }); // }, } });

This is css for table

table { border-collapse: separate; border-spacing: 0; }

th { border: 0.5px solid #f2f2f2; font-weight: bold; text-transform: uppercase; background-color: white; }

td { background-color: white; border: 0.5px solid #f2f2f2; }

Your Minimal, Reproducible Example - (Sandbox Highly Recommended)

NA

Screenshots or Videos (Optional)

No response

Do you intend to try to help solve this bug with your own PR?

None

Terms & Code of Conduct

  • [x] I agree to follow this project's Code of Conduct
  • [x] I understand that if my bug cannot be reliable reproduced in a debuggable environment, it will probably not be fixed and this issue may even be closed.

pintuiitbhi avatar Oct 28 '24 05:10 pintuiitbhi

I'm facing the same issue. Also, have you tried adding the CSS hover property to make it work across the entire row? For some reason, I can't get it to work.

CarlosSousa2001 avatar Jan 16 '25 15:01 CarlosSousa2001

@pintuiitbhi Please make sure your formatted code renders properly in the issue description, it's currently very hard to read.

From what I understand the default column size is 150px if you don't give the column a size, the 2 issues here:

  • The column itself (th and td) get the default width, but by default they are not blocks so width doesn't work on them, however positioning does work, so you get an auto size column but the table thinks the next non-pinned column starts at 150px, even though your cell is using less space, the standard now days is to define the width on the child of the cell (child of the th or td) to define size of the cell (usually a div).
  • One way to fix it I've seen is to set the size of the column explicitly in the column definition, both the size of the cell content and the definition should match, that way the table will add enough space for the pinned columns, the issue here is that this disables or breaks the behavior for auto sized columns.

Any thoughts?

luchillo17 avatar Jan 16 '25 22:01 luchillo17

I have the same issue, 1 or 2 px between 2 pinned columns. I'm using Shadcn for table component

Image

ThomasBnf avatar Jan 16 '25 22:01 ThomasBnf

@ThomasBnf I'm also using ShadCN, what I do is set the checkbox column def size exactly the same as the size of the checkbox cell, in my case 32px, so the cell size and the table state for that column size matches:

export const checkboxColumn = columnHelper.display({
  id: 'select',
  size: 32,
  header: ({ table }) => (
    <Checkbox
      checked={
        table.getIsAllPageRowsSelected() ||
        (table.getIsSomePageRowsSelected() && 'indeterminate')
      }
      onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
      aria-label="Select all"
    />
  ),
  cell: ({ row }) => (
    <Checkbox
      checked={row.getIsSelected()}
      onCheckedChange={(value) => row.toggleSelected(!!value)}
      aria-label="Select row"
    />
  ),
  enableSorting: false,
  enableHiding: false,
});

Image

Otherwise if I don't set it to size: 32, this is what I get:

Image

luchillo17 avatar Jan 16 '25 23:01 luchillo17

I still have the gap when I put 32px. I tried less, and 26px is working, no more gap

ThomasBnf avatar Jan 17 '25 08:01 ThomasBnf

@ThomasBnf That's why I said you have to measure the size of your cell with devtools.

luchillo17 avatar Jan 17 '25 18:01 luchillo17

@ThomasBnf

Setting a Fixed Column Width

You can use the size property to define a fixed width for a column. Additionally, you can set the width directly inside the cell. This approach is compatible with Tailwind CSS.

{
  accessorKey: "state",
  id: "state",
  header: "State",
  size: 150, // Sets a fixed width in pixels
  cell: (info) => (
    <div style={{ width: "150px", overflow: "hidden", textOverflow: "ellipsis" }}>
      {info.getValue() || "-"}
    </div>
  ),
},

CarlosSousa2001 avatar Jan 18 '25 20:01 CarlosSousa2001

Image this is the gap in my project, if I use position: 'sticky', the border moves

LiMao00 avatar Mar 03 '25 02:03 LiMao00

Image this is the gap in my project, if I use position: 'sticky', the border moves

The border is not the issue, the cell you have is spanning 2 rows, so it's covering the border, honestly not sure how to fix that if you want to maintain that cell as is, maybe doing a custom CSS on the sticky cell to have a bit of negative margin bottom, and adding bottom border to it that matches the original border in position and color...

luchillo17 avatar Jun 16 '25 07:06 luchillo17