Skip to content

Conversation

@hectahertz
Copy link
Contributor

@hectahertz hectahertz commented Feb 2, 2026

Closes https://github.com/github/primer/issues/5788

This PR improves the performance of SelectPanel by optimizing how selected items are looked up during rendering and sorting.

The previous implementation used O(n) or O(n*m) array lookups when:

  • Checking if an item is currently selected (isItemCurrentlySelected)
  • Sorting selected items to the top (shouldOrderSelectedFirst)
  • Filtering selected items not in the current view (handleSelectAllChange)
  • For panels with many items or selections, this caused noticeable performance degradation.

Changelog

First, the sorting algorithm in itemsToRender was slow. For each comparison during sorting, it was calling selectedOnSort.some with Object.entries and every, checking all properties of all selected items. I replaced this with a pre-computed Set of selected item IDs that allows instant lookups.

Second, the isItemCurrentlySelected function was iterating through all selected items every time it was called. Since it gets called for every item during the map operation, this was doing a lot of redundant work. I added a memoized selectedItemsSet that gets computed once when the selected prop changes, making each lookup instant.

Third, the handleSelectAllChange function had the same problem. It was using items.some inside a filter, iterating through all visible items for each selected item. I added a memoized itemsInViewSet to make those lookups instant as well.

Rollout strategy

  • Patch release
  • Minor release
  • Major release; if selected, include a written rollout or migration plan
  • None; if selected, include a brief description as to why

Testing & Reviewing

Merge checklist

@hectahertz hectahertz requested a review from a team as a code owner February 2, 2026 18:06
@changeset-bot
Copy link

changeset-bot bot commented Feb 2, 2026

⚠️ No Changeset found

Latest commit: 6042555

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions github-actions bot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Feb 2, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Feb 2, 2026

👋 Hi, this pull request contains changes to the source code that github/github-ui depends on. If you are GitHub staff, test these changes with github/github-ui using the integration workflow. Or, apply the integration-tests: skipped manually label to skip these checks.

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

This PR focuses on improving the performance of SelectPanel by replacing repeated linear scans over the items/selected arrays with precomputed Set-based lookups.

Changes:

  • Added itemsInViewSet to speed up “Select all” handling, especially when filtering, by doing O(1) membership checks instead of items.some(...).
  • Added selectedItemsSet to make isItemCurrentlySelected O(1) for multi-select panels.
  • Updated itemsToRender sorting to precompute a selectedOnSortSet and use it for determining whether items should be ordered first when shouldOrderSelectedFirst is enabled.

Comment on lines +322 to +329
const set = new Set<string | number | ItemInput>()
for (const item of items) {
if (item.id !== undefined) {
set.add(item.id)
} else {
set.add(item)
}
}
Copy link

Copilot AI Feb 2, 2026

Choose a reason for hiding this comment

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

The logic for computing a key from an item (if (item.id !== undefined) { set.add(item.id) } else { set.add(item) }) is duplicated here and again in the selectedItemsSet and selectedOnSortSet constructions, as well as mirrored in the has(...) checks. To keep the equality semantics centralized and reduce the risk of these code paths diverging in the future, consider extracting a small helper (e.g., a getItemKey function) and reusing it in all Set add/has sites.

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

integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants