Skip to content

fix(resize): enforce configured column minWidth - #1378

Merged
jbetancur merged 1 commit into
jbetancur:masterfrom
kitiho:fix/resizable-column-min-width
Aug 29, 2026
Merged

jbetancur merged 1 commit into
jbetancur:masterfrom
kitiho:fix/resizable-column-min-width

Conversation

@kitiho

@kitiho kitiho commented Aug 24, 2026 •

Copy link
Copy Markdown
Contributor

Bug fix

The resizable-column documentation states that column.minWidth clamps how small a user can drag a column. However, the resize handler currently only applies its fixed 40 px floor and ignores the configured minWidth. As a result, a column configured with minWidth: "120px" can still be dragged to 40 px.

This PR makes the implementation match the documented behavior.

Changes

  • clamp resize drags to an explicitly configured column.minWidth
  • retain the existing 40 px hard minimum when no column minimum is configured
  • add a regression test for dragging below a configured minimum width

Verification

  • npm test
  • npm run typecheck
  • npm run lint
  • npm run build

Relates to #1377

@netlify

netlify Bot commented Aug 24, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for react-data-table-component ready!

Name Link
🔨 Latest commit a318b9d
🔍 Latest deploy log https://app.netlify.com/projects/react-data-table-component/deploys/6a9125bb24f1460008aaf2ae
😎 Deploy Preview https://deploy-preview-1378--react-data-table-component.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@kitiho

kitiho commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Closing this pull request for now.

@kitiho kitiho closed this Aug 24, 2026
@kitiho kitiho reopened this Aug 24, 2026
@kitiho kitiho changed the title fix(resize): respect column minWidth fix(resize): enforce configured column minWidth Aug 24, 2026
@jbetancur jbetancur assigned jbetancur and unassigned jbetancur Aug 24, 2026
Comment thread src/components/TableCol.tsx Resolved
@jbetancur

Copy link
Copy Markdown
Owner

Hey @kitiho good catch on the bug. Definitely a bug.

The fix doesn't hold up though when I verified this in the browser.

I think this would be the simpler change, and the tests would need updating for
that scenario:

  1. Parse configuredMinWidth directly instead of going through the DOM

    const configuredMin = configuredMinWidth != null ? Number.parseFloat(configuredMinWidth) : Number.NaN;
    resizeRef.current = {
        columnId,
        startX: e.clientX,
        startWidth,
        minWidth: Math.max(40, Number.isFinite(configuredMin) ? configuredMin : 0),
    };

I see you commented that you were closing this but it's still open, so if you
want to take a stab at it I'll check back. Otherwise I'll fix this this week.

@kitiho

kitiho commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Updated — thanks for the review.

  • removed all changes to TableCol.tsx
  • the resize hook now looks up the configured column minWidth directly, parses it with Number.parseFloat, and keeps the existing 40px fallback
  • updated the regression test for a 120px configured minimum

Verified with npm test (645 passing), npm run typecheck, npm run lint, and npm run build.

@kitiho
kitiho force-pushed the fix/resizable-column-min-width branch 3 times, most recently from 38b3f52 to 41b64c2 Compare August 26, 2026 06:09
@kitiho

kitiho commented Aug 26, 2026 •

Copy link
Copy Markdown
Contributor Author

Documentation cleanup

I also removed the duplicate “Drag the right edge of any column header to resize it.” helper text from the Resizable Demo. The Demo wrapper already renders this description, so the example now shows it once.

image

Comment thread src/__tests__/DataTable.test.tsx Resolved
Comment thread src/__tests__/DataTable.test.tsx Resolved
Comment thread src/components/DataTable.tsx Outdated
defaultSortAsc,
);

// ── Column resize state ────────────────────────────────────────────────────

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Do we need to move this?

Comment thread src/hooks/useColumnResize.ts Outdated
onColumnResizeRef.current = onColumnResize;
isRTLRef.current = isRTL;
});
useIsomorphicLayoutEffect(() => {

@jbetancur jbetancur Aug 27, 2026 •

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

useLayoutEffect gains nothing over useEffect here, but more importantly the effect is unnecessary

Comment thread src/hooks/useColumnResize.ts Resolved
@kitiho

kitiho commented Aug 27, 2026

Copy link
Copy Markdown
Contributor Author

@jbetancur

Thanks for your review ~

But actually I still think the best approach is to pass column.minWidth from TableCol when a resize gesture starts, and parse that value directly in useColumnResize.

For example:

// TableCol.tsx
onResizeStart(column.id!, e, column.minWidth);
// useColumnResize.ts
const configuredMin =
  configuredMinWidth != null ? Number.parseFloat(configuredMinWidth) : Number.NaN;

resizeRef.current = {
  columnId,
  startX: e.clientX,
  startWidth,
  minWidth: Math.max(40, Number.isFinite(configuredMin) ? configuredMin : 0),
};

I think this is preferable because column.minWidth is already the source of truth for the column’s configured constraint. Passing it at the point where the resize begins keeps the value associated with the specific column being resized, without needing to pass all columns into the hook and build a separate lookup map.
It also avoids reading minWidth from the DOM with getComputedStyle, which can be less predictable across browser environments and is particularly awkward in JSDOM-based tests.
This keeps the responsibilities clear:

  • TableCol owns the column configuration and supplies its configured minWidth.
  • useColumnResize owns the resize interaction, parses the configured value, and applies the numeric floor.
  • The existing 40px minimum remains the fallback when no valid minWidth is configured.
    Compared with maintaining column minimums in a ref through an effect, this is a more direct data flow and removes the extra columns option, Map, ref, and effect from useColumnResize.

@jbetancur

jbetancur commented Aug 27, 2026 •

Copy link
Copy Markdown
Owner

Fair point on TableCol @kitiho, let's go with your version. Passing column.minWidth at the
start of the gesture is cleaner and it drops the columns option,
the map, the ref and the effect. That also means the useColumnResize call in
DataTable.tsx can move back where it was.

Ignore my two comments on the layout effect then, that code goes away with this.

Tests still need work though. Sorry, I swapped the snippets in my earlier comment. The
40px floor one should use a column with no minWidth:

const mock = dataMock();
Object.defineProperty(headerCell, 'offsetWidth', { value: 300, configurable: true });

// 300 - 300 = 0, so the 40px floor applies.
fireEvent.pointerDown(handle, { clientX: 300 });
fireEvent.pointerMove(document, { clientX: 0 });
fireEvent.pointerUp(document);

expect(headerCell.style.maxWidth).toBe('40px');

// And the one that shouldn't clamp:


const mock = dataMock({ minWidth: '120px' });
Object.defineProperty(headerCell, 'offsetWidth', { value: 300, configurable: true });

// 300 - 50 = 250, above the minimum, left alone.
fireEvent.pointerDown(handle, { clientX: 300 });
fireEvent.pointerMove(document, { clientX: 250 });
fireEvent.pointerUp(document);

expect(headerCell.style.maxWidth).toBe('250px');

@kitiho
kitiho force-pushed the fix/resizable-column-min-width branch from 41b64c2 to 97b18f6 Compare August 28, 2026 06:02
@kitiho
kitiho force-pushed the fix/resizable-column-min-width branch from 97b18f6 to a318b9d Compare August 28, 2026 06:07
@kitiho

kitiho commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review and for clarifying the test cases. @jbetancur

I updated the implementation to pass column.minWidth from TableCol when the resize gesture starts, then parse and clamp that value directly in useColumnResize. This removes the columns option, the minimum-width map/ref/effect, and lets the resize setup in DataTable return to its original position.

I also updated the tests to cover:

  • clamping to a configured minWidth
  • preserving the existing 40px floor when no minWidth is configured
  • allowing resize values that remain above the configured minimum

All checks pass locally: npm test (647 passing), npm run typecheck, npm run lint, and npm run build.

Thanks again for the guidance — it made the implementation much simpler and more focused.

@jbetancur
jbetancur merged commit bfa0d3f into jbetancur:master Aug 29, 2026
5 checks passed
@jbetancur

Copy link
Copy Markdown
Owner

Thank you @kitiho 8.8.2 should be available shortly!

@jbetancur jbetancur assigned kitiho and jbetancur and unassigned kitiho Sep 5, 2026
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