Table Column Resizing#
Keep's UI has two distinct column-resizing mechanisms: TanStack React Table column resizing (for data tables like the alerts table) and panel-level layout splitting (the ResizableColumns component). These serve different purposes and should not be confused.
TanStack React Table Column Resizing (Alerts Table)#
Table Setup#
Both AlertTableServerSide and the deprecated AlertTable configure TanStack React Table with:
columnResizeMode: "onChange"— column width updates in real time while dragging.onColumnSizingChange: setColumnSizing— writes updated sizes back to state.- Column sizing state is persisted via
useLocalStorageunder the key"table-sizes". This key is shared across all presets, not scoped per preset name.
Resize Handle#
The resize handle is rendered inside DraggableHeaderCell at the right edge of each non-pinned column header:
- It is a
divwithposition: absolute; top: 0; right: 0. - Invisible by default (
opacity-0), visible only on parentgroup-hover(group-hover:opacity-100). - At rest:
w-0.5width,bg-blue-100— a thin, light handle. - Expanded on hover:
hover:w-2— grows to0.5rem. - While resizing:
w-2 bg-blue-400— wider and darker blue. - Pinned columns do not get a resize handle; the handle is gated by
column.getIsPinned() === false. - The handler is wired via TanStack's
getResizeHandler()from theheaderobject .
Per-Column Width Constraints#
Default sizes and constraints are defined in alert-table-utils.tsx:
| Column | size | minSize | maxSize | enableResizing |
|---|---|---|---|---|
| checkbox | — | 16 | 16 | (default) |
| status | 16 | 16 | 16 | false |
| source | 24 | 24 | 24 | false |
| name | 180 | 150 | 200 | true |
| description | — | 200 | — | (default) |
| last received | — | 80 | 80 | (default) |
| assignee | — | 100 | — | (default) |
| extra payload | — | 200 | — | (default) |
| dynamic columns | — | 100 | — | (default) |
Fixed-size columns (status, source) use enableResizing: false. Note that DraggableHeaderCell also hard-codes override widths for checkbox (32px), source (40px), and status (24px) in the drag style, which can diverge from TanStack-reported sizes .
Column Visibility Gate#
The getOnlyVisibleCols utility filters the stored visibility state against the actual column IDs present in the current table instance before passing it to TanStack . This prevents stale visibility keys from affecting the table.
ResizableColumns — Panel Layout Splitter#
This is a separate component that splits a page into two resizable panes (e.g., sidebar + main content). It does not use TanStack Table at all.
Two versions exist:
| Location | Key Differences |
|---|---|
keep-ui/components/ui/ResizableColumns.tsx | Older; uses leftChild/rightChild props; divider turns orange on hover. |
keep-ui/shared/ui/ResizableColumns/ui/ResizableColumns.tsx | Newer (memo-wrapped); uses children pattern (exactly 2 required); divider turns blue on hover; memoizes child panes. |
Both share the same core behavior:
- Left pane width is stored as a percentage (
leftWidthstate, default 50%). - Clamped to
[20%, 80%]during drag . - Drag start/stop wires
mouseupandmouseleavelisteners ondocument. - The divider is
w-1(0.25rem) and styledcursor-col-resize.
The shared version additionally enforces a strict two-children contract and adds min-w-0 to prevent flex overflow .
Key Files#
| File | Role |
|---|---|
alert-table-headers.tsx | Resize handle UI in DraggableHeaderCell |
alert-table.tsx | columnResizeMode, columnSizing LocalStorage setup (deprecated AlertTable) |
alert-table-server-side.tsx | Same config for the current AlertTableServerSide |
alert-table-utils.tsx | Per-column size/minSize/maxSize/enableResizing defaults |
shared/ui/ResizableColumns | Panel splitter (not TanStack) |
components/ui/ResizableColumns.tsx | Older panel splitter (legacy) |