Skip to content

Bl 11194 table fixed columns drag resize improvements#172

Open
bradleyfrance wants to merge 4 commits intomainfrom
BL-11194-table-fixed-columns-drag-resize-improvements
Open

Bl 11194 table fixed columns drag resize improvements#172
bradleyfrance wants to merge 4 commits intomainfrom
BL-11194-table-fixed-columns-drag-resize-improvements

Conversation

@bradleyfrance
Copy link

Feat: Improved column resize behaviour, visual indicators, and column separator styling across the Tokens, Blogs, Blog Posts tables, SEO table, Companies under User as well as User tables - Need further help with some of the styling for this, but most of it looks good.

Another PR regarding the same table/colums for the HB/CMS

https://broadlume.atlassian.net/browse/BL-11194

bradleyfrance and others added 2 commits March 5, 2026 16:18
…o right edge

- SortableContext now uses draggableColumnIds (excludes fixedEndColIds) so fixed-end columns cannot be dragged or displaced
- Strip fixedEndColIds/fixedStartColIds from persisted column order to prevent stale localStorage state
- Resize handle line uses justifyContent flex-end so blue indicator aligns to exact column boundary
- Elevate th zIndex on resize hover/active to prevent adjacent column overlap

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bradleyfrance bradleyfrance marked this pull request as ready for review March 5, 2026 17:15
@bradleyfrance bradleyfrance self-assigned this Mar 5, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves the TanStack-based data table’s column interactions by adding resize handles/visual indicators, persisting column sizing, and refining table scroll + fixed-end column behavior.

Changes:

  • Add column resizing support (incl. localStorage persistence) and resize visual indicators.
  • Adjust header/cell rendering and styling to better support resizing + fixed-end sticky columns.
  • Add custom scrollbar styling for horizontally scrollable data table wrappers.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.

File Description
src/misc/tanstack-table/TableComponents.tsx Updates draggable header rendering and adds a dedicated resize handle + hover/resizing z-index styling.
src/misc/tanstack-table/Table.tsx Adds persisted columnSizing, enables TanStack column resizing, and refactors header/body rendering for fixed layout + sticky fixed-end columns.
src/index.css Adds data-table-scroll scrollbar styling for the table wrapper.
Comments suppressed due to low confidence (1)

src/misc/tanstack-table/Table.tsx:108

  • getInitialColumnOrder computes validFixedEnd (filtered to columns that actually exist) but the fallback return path still appends the unfiltered fixedEndColIds. This can leave unknown column IDs in columnOrder, which can lead to inconsistent ordering/state when a fixed-end column isn't present for a given table. Use the validated list (and consider similarly validating fixedStartColIds) in the final returned order.
  const colIds = [...allColIds];
  const draggable = colIds.filter(
    (id) => !fixedStartColIds.includes(id) && !fixedEndColIds.includes(id)
  );

  return [...fixedStartColIds, ...draggable, ...fixedEndColIds];
}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

className={clsx(
'py-3 text-text-pri transition-all duration-200',
'relative py-4 text-text-pri transition-all duration-200',
'last:[>td]:justify-center',
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DraggableColumnHeader no longer renders a direct td child inside the th (it now renders a div), but the class string still includes last:[>td]:justify-center. That selector will never match now, so the intended styling won’t apply. Update the selector to target the current child element (or remove it if no longer needed).

Suggested change
'last:[>td]:justify-center',
'last:[&>div]:justify-center',

Copilot uses AI. Check for mistakes.
Comment on lines +564 to +568
/* Thicker horizontal scrollbar for data tables */
.data-table-scroll {
scrollbar-width: thin;
scrollbar-color: #cbd5e1 #f1f5f9;
}
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment says this makes the horizontal scrollbar “Thicker”, but scrollbar-width: thin makes it thinner in Firefox. Either adjust the comment to match the implementation, or change the Firefox scrollbar setting if the intent is genuinely a thicker scrollbar there too.

Copilot uses AI. Check for mistakes.
Comment on lines +780 to +788
const colWidth =
h.column.columnDef.maxSize !== undefined &&
h.column.columnDef.maxSize <
Number.MAX_SAFE_INTEGER
? h.getSize()
: Math.max(
h.column.columnDef.minSize ?? 20,
80
);
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sticky right offsets are calculated using a fallback Math.max(minSize, 80) whenever columnDef.maxSize is undefined or very large. That means the sticky positioning can be wrong whenever a fixed-end column’s actual size differs from 80px (including after user resizing). Use the column’s actual computed size (e.g. getSize()) for offset accumulation so sticky columns don’t overlap/gap.

Suggested change
const colWidth =
h.column.columnDef.maxSize !== undefined &&
h.column.columnDef.maxSize <
Number.MAX_SAFE_INTEGER
? h.getSize()
: Math.max(
h.column.columnDef.minSize ?? 20,
80
);
const colWidth = h.getSize();

Copilot uses AI. Check for mistakes.
Comment on lines +939 to +943
const colWidth =
c.column.columnDef.maxSize !== undefined &&
c.column.columnDef.maxSize < Number.MAX_SAFE_INTEGER
? c.column.getSize()
: Math.max(c.column.columnDef.minSize ?? 20, 80);
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the header offset logic: sticky cell right offsets fall back to Math.max(minSize, 80) when maxSize isn’t set, which can misposition fixed-end sticky columns (especially after resize). Accumulate offsets using the column’s actual getSize() so the sticky right value matches real rendered widths.

Suggested change
const colWidth =
c.column.columnDef.maxSize !== undefined &&
c.column.columnDef.maxSize < Number.MAX_SAFE_INTEGER
? c.column.getSize()
: Math.max(c.column.columnDef.minSize ?? 20, 80);
const colWidth = c.column.getSize();

Copilot uses AI. Check for mistakes.
);
setColumnOrder([...fixedStartColIds, ...base, ...fixedEndColIds]);
}
}, [initialColumnOrder]);
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This useEffect derives columnOrder using fixedStartColIds/fixedEndColIds but those arrays are not included in the dependency list. If the pinned columns change between renders, columnOrder can become stale/misaligned. Include the fixed column ID arrays (and any other referenced values) in the deps or memoize them to stable references.

Suggested change
}, [initialColumnOrder]);
}, [initialColumnOrder, fixedStartColIds, fixedEndColIds]);

Copilot uses AI. Check for mistakes.
className={`${itemProps?.table?.className} text-text-pri`}
style={{
...(itemProps?.table?.style || {}),
minWidth: tableMinWidth,
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Table is rendered with w-full and tableLayout: 'fixed', but without setting an explicit width that matches tableMinWidth. Combined with percentage-based header widths, this can cause resized column pixel sizes (and the persisted columnSizing values) to scale with container width instead of staying at the intended pixel widths. Consider setting the table width to the computed min width (so it overflows horizontally) and/or applying column widths in px rather than percentages.

Suggested change
minWidth: tableMinWidth,
minWidth: tableMinWidth,
width: tableMinWidth,

Copilot uses AI. Check for mistakes.
Comment on lines +818 to +821
width: `${(
(header.getSize() / totalColWidth) *
100
).toFixed(4)}%`,
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header widths are being applied as percentages derived from header.getSize(). Because the table itself can expand beyond tableMinWidth (it’s w-full), the actual rendered pixel widths will scale, which undermines pixel-precise resizing and localStorage persistence. Prefer applying getSize() directly as a px width (or ensure the table width is constrained to the sum of column sizes).

Suggested change
width: `${(
(header.getSize() / totalColWidth) *
100
).toFixed(4)}%`,
width: `${header.getSize()}px`,

Copilot uses AI. Check for mistakes.
Comment on lines +797 to +799
const isBeforeFixedEnd =
!!nextHeader &&
fixedEndColIds.includes(nextHeader.column.id);
Copy link

Copilot AI Mar 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isBeforeFixedEnd is computed but never used. This adds dead code and makes the intent harder to follow—either remove it or use it to drive the styling/behavior it was introduced for.

Suggested change
const isBeforeFixedEnd =
!!nextHeader &&
fixedEndColIds.includes(nextHeader.column.id);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants