Skip to content

Conversation

mattrunyon
Copy link
Collaborator

@mattrunyon mattrunyon commented Oct 8, 2025

Adds column order and visibilty overflow menu with show hidden columns (for the visibility menu only) and undo/redo.

Moves in the menu or on the grid add to the undo/redo stack.
Hiding/unhiding adds to the undo/redo stack.
Creating a new group will add to the stack as a whole action when it is named (moving columns + naming the group)

Unchecking the "Show hidden columns" option will hide the hidden column/group entries in the menu. The setting is reset on menu open.

@mattrunyon mattrunyon requested a review from a team October 8, 2025 04:59
@mattrunyon mattrunyon self-assigned this Oct 8, 2025
@mattrunyon mattrunyon requested review from bmingles and removed request for a team October 8, 2025 04:59
Copy link

codecov bot commented Oct 8, 2025

Codecov Report

❌ Patch coverage is 94.59459% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.01%. Comparing base (b369a51) to head (3421c16).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
packages/iris-grid/src/IrisGrid.tsx 16.66% 5 Missing ⚠️
packages/iris-grid/src/ColumnHeaderGroup.ts 0.00% 2 Missing ⚠️
...d/src/mouse-handlers/GridColumnMoveMouseHandler.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2546      +/-   ##
==========================================
+ Coverage   43.91%   44.01%   +0.09%     
==========================================
  Files         763      764       +1     
  Lines       42874    43016     +142     
  Branches    11005    11040      +35     
==========================================
+ Hits        18827    18932     +105     
- Misses      24032    24038       +6     
- Partials       15       46      +31     
Flag Coverage Δ
unit 44.01% <94.59%> (+0.09%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mattrunyon mattrunyon marked this pull request as ready for review October 9, 2025 17:15
[class*='spectrum-Menu'] {
kbd {
// Unsetting bootstrap overrides
padding: unset;
Copy link
Contributor

Choose a reason for hiding this comment

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

what's the reason for this one being unset vs the rest all being revert?

* @returns The new reordered items
*/
static moveItem(
static moveItem<T extends readonly MoveOperation[]>(
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the use case for T extending MoveOperation[]?

Copy link
Contributor

@bmingles bmingles Oct 10, 2025

Choose a reason for hiding this comment

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

Looking at this, I think these will be cleaner if you do

static moveItem<T extends MoveOperation>(
    from: VisibleIndex,
    to: VisibleIndex,
    oldMovedItems: readonly T[]
  ): readonly T[] {
)

Then you don't need any as unknown as T assertions. You'd only need to assert new item creation e.g. movedItems.push({ from, to } as T);. I also think this is more accurate, since it's the array items that might be subtypes and not the entire readonly array. It will require updating all 3 moveXXX functions, but seemed to work with what I tried.


const undoBtn = screen.getByLabelText('Undo');
await user.click(undoBtn);
expect(mockGroupHandler).toHaveBeenCalledWith([]);
Copy link
Contributor

Choose a reason for hiding this comment

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

If I'm understanding correctly, this test proves it results in an empty array if only 1 action had occurred. I'm assuming if the stack had multiple items, it would show an array containing all but the last one? If so, might be good to test this just to prove the undo doesn't always undo everything in the stack. Same for the keyboard tests.

const hiddenColumns = [1, 3, 5, 7, 9];
render(<BuilderWithStateManagement hiddenColumns={hiddenColumns} />);

expect(screen.getAllByText(COLUMN_PREFIX, { exact: false }).length).toBe(10);
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious why there are 10 items before showing and 5 after?


const { columnHeaderGroups, onColumnHeaderGroupChanged } = this.props;
// Clean up unnamed groups on unmount
const newGroups = columnHeaderGroups.filter(group => !group.isNew);
Copy link
Contributor

@bmingles bmingles Oct 10, 2025

Choose a reason for hiding this comment

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

Is this actually newGroups? Seems it should be oldGroups or something based on the !group.isNew filter.

}

onColumnHeaderGroupChanged(newGroups);
endUndoGroup();
Copy link
Contributor

Choose a reason for hiding this comment

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

Are there any edge cases where handleGroupNameChange might not get called after startUndoGroup has been called resutling in endUndoGroup not being called?

}
}

// The forwardRef is for a hacky unit test to check the
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't see forwardRef apis used here. I assume this is conceptually referring to __testRef ?

* @returns The new reordered items
*/
static moveRange(
static moveRange<T extends readonly MoveOperation[]>(
Copy link
Contributor

Choose a reason for hiding this comment

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

See comment on moveItem

}

static moveItemOrRange(
static moveItemOrRange<T extends readonly MoveOperation[]>(
Copy link
Contributor

Choose a reason for hiding this comment

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

See comment on moveItem

// undo/redo will pass already parsed groups
// Parsing them again causes a loop with undo/redo that makes it unusable
columnHeaderGroups:
columnHeaderGroups.every(isColumnHeaderGroup) &&
Copy link
Contributor

Choose a reason for hiding this comment

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

micro optimization would be for both checks to happen in the predicate instead of 2 every calls.

@@ -0,0 +1,87 @@
import { renderHook, act } from '@testing-library/react';
Copy link
Contributor

@bmingles bmingles Oct 10, 2025

Choose a reason for hiding this comment

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

Kind of confused why this wouldn't fail the tests.

suggestion
import { renderHook, act } from '@testing-library/react-hooks';

Copy link
Contributor

@bmingles bmingles Oct 10, 2025

Choose a reason for hiding this comment

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

oh, after npm install this works. Wonder if this was a recent addition to @testing-library/react exports


return {
state: newState,
undoStack,
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any risk using a mutated undoStack instead of undoStack: [...undoStack]?

Copy link
Contributor

@bmingles bmingles left a comment

Choose a reason for hiding this comment

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

General logic seems solid. I left a few questions / suggestions.

Copy link
Contributor

@bmingles bmingles left a comment

Choose a reason for hiding this comment

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

General logic looks good. Left a few questions / suggestions.

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