Skip to content

Conversation

@francinelucca
Copy link
Member

@francinelucca francinelucca commented Apr 3, 2025

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

Adds logic to SelectPanel to automatically sort items, displaying the selected items first. The sorted list gets rearranged on:

  • Filter value is cleared
  • Items have changed
  • Panel is reopened

Also adds capabilities for custom sorting, providing a sorting key, sort by ascending or descending and opt-out of "selected on top" functionality.

by default, selected items will be displayed at the top when primer_react_select_panel_order_selected_at_top FF is on

Changelog

New

  • Added sorting logic to SelectPanel
  • sortKey, sortFn, sortDirection and orderSelectedFirst props in SelectPanel
  • New Jest tests for sorting
  • New stories for sorting
  • Added "sortKey" to all SelectPanel stories so that they're sorted alphabetically

Changed

  • Update VRT tests
  • Update Jest tests to account for new sorting logic
  • Update ItemProps interface to extend from HtmlElement

Removed

  • Custom sorting logic from SelectPanel stories as it is no longer needed

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

SelectPanel stories

  • Ensure to turn on modern_action_list FF, as well with primer_react_select_panel_fullscreen_on_narrow and primer_react_select_panel_order_selected_at_top FF

Merge checklist

@changeset-bot
Copy link

changeset-bot bot commented Apr 3, 2025

🦋 Changeset detected

Latest commit: ead6002

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@primer/react Minor

Not sure what this means? Click here to learn what changesets are.

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

@github-actions github-actions bot added the staff Author is a staff member label Apr 3, 2025
@github-actions
Copy link
Contributor

github-actions bot commented Apr 3, 2025

👋 Hi, this pull request contains changes to the source code that github/github depends on. If you are GitHub staff, we recommend testing these changes with github/github using the integration workflow. Thanks!

@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 Apr 3, 2025
Comment on lines 407 to 414
const itemASelected = selectedOnSort.some(item =>
Object.entries(item).every(([key, value]) => {
if (key === 'selected') {
return true
}
return itemA[key as keyof ItemProps] === value
}),
)
Copy link
Member Author

Choose a reason for hiding this comment

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

this seems expensive :(

Copy link
Member

Choose a reason for hiding this comment

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

Wanted to ask if it would be possible for the sort order to be maintained as a stateful value and compute it onClose or onOpen instead of having to run the sort every render?

It seemed like the logic that we have for this is something like:

  • When open, keep the ordering of items constant
  • When closing (or when re-opening), sort the items by:
    • selected items come first
      • sort selected items by group, if applicable
      • otherwise, sort by alphanumeric
    • otherwise, sort by alphanumeric

Does that track with what you're seeing?

Comment on lines 433 to 438
// Then order by text
if ((itemA.text ?? '') < (itemB.text ?? '')) {
return -1
} else if ((itemA.text ?? '') > (itemB.text ?? '')) {
return 1
}
Copy link
Member Author

Choose a reason for hiding this comment

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

I baked in alphabetically ordering through text but now that I'm looking at the issue it doesn't really look like a requirement 🤔
I can remove and do selection-at-top only if this is not wanted/needed 👀
CC: @emilybrick

Copy link
Contributor

Choose a reason for hiding this comment

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

Consumers could want to sub-sort based on something besides alphabetical order. For example: sort most frequently used labels to the top.

I think we should remove this default alphanumeric sort.

Copy link
Member

Choose a reason for hiding this comment

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

Feel free to steal the alphanumeric stuff from data table btw if it's helpful! We have some sort helpers over there

@github-actions
Copy link
Contributor

github-actions bot commented Apr 3, 2025

size-limit report 📦

Path Size
packages/react/dist/browser.esm.js 103.95 KB (+0.35% 🔺)
packages/react/dist/browser.umd.js 104.21 KB (+0.24% 🔺)

@github-actions github-actions bot requested a deployment to storybook-preview-5867 April 3, 2025 04:09 Abandoned
},
} as ItemProps
})
.sort((itemA, itemB) => {
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm coding this as the default behavior. Wondering if we should allow consumer to opt-out of this behavior or provide their custom sort function 👀
cc: @emilybrick

Copy link
Contributor

Choose a reason for hiding this comment

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

I feel strongly that we should let consumers opt-out by providing their own sort function. I think DataTable has a nice API for handling this: https://github.com/primer/react/blob/main/packages/react/src/DataTable/column.ts#L59

@github-actions github-actions bot requested a deployment to storybook-preview-5867 April 3, 2025 04:17 Abandoned
@github-actions github-actions bot requested a deployment to storybook-preview-5867 April 3, 2025 04:22 Abandoned
@github-actions github-actions bot temporarily deployed to storybook-preview-5867 April 3, 2025 04:36 Inactive
@francinelucca francinelucca added the update snapshots 🤖 Command that updates VRT snapshots on the pull request label Apr 3, 2025
@github-actions github-actions bot removed the update snapshots 🤖 Command that updates VRT snapshots on the pull request label Apr 3, 2025
@github-actions github-actions bot temporarily deployed to storybook-preview-5867 April 3, 2025 05:24 Inactive
Copy link
Member Author

Choose a reason for hiding this comment

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

visual updates are due to items being sorted now

@github-actions github-actions bot requested a deployment to storybook-preview-5867 April 7, 2025 20:53 Abandoned
@francinelucca francinelucca added the update snapshots 🤖 Command that updates VRT snapshots on the pull request label Apr 11, 2025
@github-actions github-actions bot requested a deployment to storybook-preview-5867 April 11, 2025 03:00 Abandoned
@github-actions github-actions bot removed the update snapshots 🤖 Command that updates VRT snapshots on the pull request label Apr 11, 2025
@github-actions github-actions bot requested a deployment to storybook-preview-5867 April 11, 2025 03:11 Abandoned
@github-actions github-actions bot temporarily deployed to storybook-preview-5867 April 11, 2025 03:24 Inactive
Copy link
Contributor

@emilybrick emilybrick left a comment

Choose a reason for hiding this comment

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

This looks good to me, selected items move to top/appear at top + in the same order as they appear in the button. WIth border removed. Thank you!

@primer-integration
Copy link

👋 Hi from github/github! Your integration PR is ready: https://github.com/github/github/pull/371812

Copy link
Member

@joshblack joshblack left a comment

Choose a reason for hiding this comment

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

Left some comments around the effect stuff, feel free to ignore me if this is getting annoying 😅 lol

Comment on lines +419 to +424
useEffect(() => {
if (open) {
resetSort()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [open])
Copy link
Member

Choose a reason for hiding this comment

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

We could potentially handled this this like in: https://react.dev/learn/you-might-not-need-an-effect#adjusting-some-state-when-a-prop-changes to avoid having to use an effect here. Another idea is to call resetSort() when onClose() is called (or whatever appropriate prop it would be for when it open/closes)

@@ -385,8 +463,56 @@ export function SelectPanel({
},
} as ItemProps
})

setItemsToRender(itemsToRender)
Copy link
Member

Choose a reason for hiding this comment

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

Could this and the effect below potentially move into just the render function instead of effects or are we experiencing some perf problems when that happens?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah we can, I put it in a useEffect as a response to your comment here #5867 (comment), (also see #5867 (comment)) so we didn't have to sort on every render 👀

Comment on lines +97 to +99
sortKey?: keyof ItemInput
sortDirection?: 'asc' | 'desc'
sortFn?: (a: ItemInput, b: ItemInput) => number
Copy link
Member

Choose a reason for hiding this comment

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

Could you share more about baking these directly into select panel? Put another way, folks could just sort the array however they wanted to before but now they would need to hook into SelectPanel's API to do that.

This might be a preference for folks downstream or on the team, totally understand if so 👍 It wasn't immediately clear to me why we would do this and just wanted to ask.

Copy link
Member Author

Choose a reason for hiding this comment

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

my logic was we're already sorting in order to display selected at the top so I was thinking instead of doing (potentially) a double sort, one at consumer-side and one on our side, we could just do it all together, so that's where sortKey and sortDirection come in sortFn comes from @mperrotti suggestion that we should allow for custom sort functions.
I also thought providing these could offload work from the consumer and make it "easier", I could be wrong though 👀

Put another way, folks could just sort the array however they wanted to before but now they would need to hook into SelectPanel's API to do that

these are all opt-in, folks could totally still do their own sorting before hand and everything should work as expected.

All that being said, these three props can totally be removed and this PRs purpose will still be served.

@primer-integration
Copy link

🔴 golden-jobs completed with status failure.

@francinelucca
Copy link
Member Author

closing in favor of #5971

@francinelucca francinelucca deleted the fix/select-panel-ordering branch May 7, 2025 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: failing Changes in this PR cause breaking changes in gh/gh staff Author is a staff member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants