Skip to content

Change algorithm for column widths#197

Merged
severo merged 24 commits intomasterfrom
change-algorithm-for-width
Jun 4, 2025
Merged

Change algorithm for column widths#197
severo merged 24 commits intomasterfrom
change-algorithm-for-width

Conversation

@severo
Copy link
Copy Markdown
Contributor

@severo severo commented May 28, 2025

fixes #159

Some rules:

  • no column can be narrower than minWidth (hardcoded to 50px).
  • a column resized manually (with mouse or keyboard or ... localStorage) has a fixed size. It's highlighted visually with a blue dot
  • the other columns are adjusted to fit the remaining space in the table:
    • until all the columns fit within the space, the widest one(s) is (are) shrunk to equal the second widest one(s). Worst case: all the columns take the narrowest width
    • exception: a column cannot be shrinked under a minimum width, that depends on the number of columns:
      • 100% for 1 column
      • 50% for 2 columns
      • 33.3% for 3 columns
      • 25% for 4 columns or more

A demo:

Screencast.From.2025-05-28.17-02-15.mp4

@severo severo changed the title Change algorithm for width Change algorithm for column widths May 28, 2025
@severo severo requested review from bleakley, Copilot and platypii May 28, 2025 15:09
@severo severo marked this pull request as ready for review May 28, 2025 15:09
@severo
Copy link
Copy Markdown
Contributor Author

severo commented May 28, 2025

I'll add unit tests to this PR if the global logic is OK for you @bleakley @platypii

This comment was marked as outdated.

@platypii
Copy link
Copy Markdown
Contributor

Very nice!! 👏 Some minor comments:

  • I propose changing the max width for 4+ columns to something that is not an exact multiple of the width. This has the nice feature of "hinting" to the user that there are more columns offscreen to the right. Eg-
    30% for 4 columns or more will make it so that 4+ wide columns will look like:
    | col1 | col2 | col3 | co... |
    which hints to the user that there is more data.

  • The user-resizing feels a little weird the way the other columns react by expand/contracting. I'm not sure of a better option but just mentioning that it felt a little weird in case you have ideas.

@severo
Copy link
Copy Markdown
Contributor Author

severo commented May 28, 2025

The user-resizing feels a little weird the way the other columns react by expand/contracting. I'm not sure of a better option but just mentioning that it felt a little weird in case you have ideas.

Sure, I feel the same. An alternative is to adjust the widths only on init and table resizing. I think it would be good enough and less weird.

@severo
Copy link
Copy Markdown
Contributor Author

severo commented May 28, 2025

I propose changing the max width for 4+ columns to something that is not an exact multiple of the width. This has the nice feature of "hinting" to the user that there are more columns offscreen to the right. Eg-
30% for 4 columns or more will make it so that 4+ wide columns will look like:
| col1 | col2 | col3 | co... |
which hints to the user that there is more data.

OK!

A slightly more elaborate solution (too much maybe) would be to avoid the right border if there are more columns. ie if there are 10 columns, and 7 are within the viewport, the 7th column cannot end exactly on the table border, but we would have at least 20px shift right or left.

@bleakley
Copy link
Copy Markdown
Contributor

I experimented with the sizing a bit and overall I think this behavior is pretty good. One thing that would be nice would be smart fitting column width on double click, similar to how it works in sheets/excel. If it could be reduced to the minimum needed to contain the values, which would be especially useful for columns like ids or numbers.

@severo
Copy link
Copy Markdown
Contributor Author

severo commented Jun 2, 2025

I experimented with the sizing a bit and overall I think this behavior is pretty good. One thing that would be nice would be smart fitting column width on double click, similar to how it works in sheets/excel. If it could be reduced to the minimum needed to contain the values, which would be especially useful for columns like ids or numbers.

Do you think we should do it at init?

When the total width of all columns is less than the available space, I currently add space evenly to all the columns. An alternative, which I don't like because it's less balanced, is to add all the space to the largest column.

@severo
Copy link
Copy Markdown
Contributor Author

severo commented Jun 2, 2025

I'll try to change the rules as follows:

  • no column can be narrower than minWidth (hardcoded to 50px).
  • a column resized manually (with mouse or keyboard or ... localStorage) has a fixed size. It's highlighted visually with a blue dot
  • added (4093ae6,8abf6e6): a column auto-resized (double click or space/enter on the resizer) has a fixed size, as the manually resized columns (same blue dot). The maxWidth is set in CSS (40rem in .styled class). If it is pressed (auto-resized) again, it's resized automatically, as a way to let the column flow again.
  • added (4093ae6, 8abf6e6): when resizing or autoresizing a column, the other columns are unchanged
  • the other columns are adjusted to fit the remaining space in the table:
    • until all the columns fit within the space, the widest one(s) is (are) shrunk to equal the second widest one(s). Worst case: all the columns take the narrowest width
    • exception: a column cannot be shrinked under a minimum width, that depends on the number of columns:
      • 100% for 1 column
      • 50% for 2 columns
      • 33.3% for 3 columns
      • changed 25% 30% for 4 columns or more

@severo
Copy link
Copy Markdown
Contributor Author

severo commented Jun 4, 2025

Could you review again @platypii @bleakley? Thanks!

Screencast.From.2025-06-04.11-04-20.mp4

@severo severo requested a review from Copilot June 4, 2025 09:06

This comment was marked as outdated.

it fixes the types. Also: it removes the need to fix the value on the
first load (isInitialized state)
@severo severo force-pushed the change-algorithm-for-width branch from 4b850f6 to e6f4486 Compare June 4, 2025 14:54
Copy link
Copy Markdown
Contributor

@bleakley bleakley left a comment

Choose a reason for hiding this comment

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

Very nice 👍

@severo severo requested review from bleakley and Copilot June 4, 2025 20:02
Copy link
Copy Markdown
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

This PR replaces the previous fixed‐width hook with a more flexible useColumnStates solution, updates how column widths are measured, persisted, and adjusted to fit available space, and refactors related components to use the new API.

  • Introduces useColumnStates and generic parse/stringify in useLocalStorageState
  • Implements dynamic width adjustment algorithm in helpers/width.ts and connects it to HighTable via setAvailableWidth
  • Updates ColumnHeader, ColumnResizer, TableCorner, and tests to use the new state shape and show fixed-width indicators

Reviewed Changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/hooks/useLocalStorageState.ts Added generic parse/stringify options and simplified save logic
src/hooks/useColumnStates.tsx New hook managing measured vs. fixed widths and storage
src/helpers/width.ts New measurement helpers and adjustMeasuredWidths logic
src/components/HighTable/HighTable.tsx Wired in useColumnStates, report available width
src/components/ColumnHeader Switched to useColumnStates, toggling fixed/auto resize
src/components/ColumnResizer Updated to use forceWidth/autoResize and new pointer state
src/components/TableCorner Added forwarded ref for measurement
src/components/HighTable/*.test.tsx Updated tests to expect new storage suffix and state shape
Comments suppressed due to low confidence (3)

src/components/ColumnResizer/ColumnResizer.tsx:102

  • The handling for the 'Escape' key has been removed, so users can't cancel a resize operation via keyboard. Reintroduce if (e.key === 'Escape') { setActiveKeyboard(false); navigateToCell?.(); return; }.
const onKeyDown = useCallback((e: KeyboardEvent) => {

src/components/ColumnResizer/ColumnResizer.tsx:134

  • For better ARIA slider semantics, add aria-valuemin={minWidth} and aria-valuemax={/* some max */} so assistive tech knows the allowed range.
aria-valuenow={width}

src/components/ColumnResizer/ColumnResizer.tsx:102

  • No existing tests cover 'Escape' key behavior in the resizer. Consider adding a unit test to verify that ESC cancels resizing and returns focus to the parent cell.
const onKeyDown = useCallback((e: KeyboardEvent) => {

Comment thread src/helpers/width.ts
@severo
Copy link
Copy Markdown
Contributor Author

severo commented Jun 4, 2025

re low confidence Copilot comment about aria-valuemin, see: #202

the two other comments are wrong

@severo
Copy link
Copy Markdown
Contributor Author

severo commented Jun 4, 2025

Merging. We can fix things later if needed. Thanks for the comments, it's better now!

@severo severo merged commit 54fa7b0 into master Jun 4, 2025
10 checks passed
@severo severo deleted the change-algorithm-for-width branch June 4, 2025 20:44
@platypii
Copy link
Copy Markdown
Contributor

platypii commented Jun 4, 2025

Awesome great work @severo!! It was really annoying me having to resize columns all the time, this is a huge improvement!

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.

Better algorithm for column width

4 participants