Skip to content

fix(SelectPanel): Correctly recalculate position on overflow - #5562

Merged
camertron merged 32 commits into
mainfrom
francinelucca/select-panel-overflow
Feb 14, 2025
Merged

fix(SelectPanel): Correctly recalculate position on overflow#5562
camertron merged 32 commits into
mainfrom
francinelucca/select-panel-overflow

Conversation

@francinelucca

@francineluccafrancinelucca commented Jan 17, 2025

Copy link
Copy Markdown
Member

Closeshttps://github.com/github/primer/issues/4027

Continuation of #5207.

When the selectPanel grows after opening (example: open in loading state, data is fetched, items are rendered), the position is not recalculated and may cause content to go off screen (See for more context https://github.com/github/primer/issues/4027). This PR corrects that undesired behavior by recalculating the position of the overlay on size change. Additionally, bake in logic so that the overlay retains it's size on filtering when anchored to the top (to prevent the panel from repositioning itself too many times).

before

Screen.Recording.2025-02-05.at.6.18.57.PM.mov
Screen.Recording.2025-02-05.at.6.19.47.PM.mov

after

Screen.Recording.2025-02-05.at.6.26.39.PM.mov
Screen.Recording.2025-02-05.at.6.21.45.PM.mov

Changelog

New

  • AnchoredOverlay dev stories for content resizing within page and dialog.
  • Support for pinPosition prop in AnchoredOverlay to prevent position shifting when sitting at the top of the anchor.
  • Support 'anchorSide' prop through 'overlayProps' in AnchoredOverlay
  • Adds max-height: 100vh default to AnchoredOverlay.
  • SelectPanel example stories for content resizing within page and dialog.
  • Support for width overlay prop in SelectPanel
  • Set pinPosition to true in SelectPanel if height hasn't been set by user
  • Added resizeObserver to useAnchoredPosition to watch for changes within the floating element (i.e., the overlay)

Changed

  • Add logic to useAnchoredPosition's updatePosition function to prevent anchored element to unpin from the top when possible (dependent on pinPosition) prop
  • Slight refactor in useResizeObserver hook
  • VRT updates (couldn't determine the source of these)

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

Test new functionality in https://primer-88a2e13e51-13348165.drafts.github.io/storybook/?path=/story/components-selectpanel-examples--reposition-after-loading, https://primer-88a2e13e51-13348165.drafts.github.io/storybook/?path=/story/components-selectpanel-examples--select-panel-reposition-inside-dialog

Ensure default functionality still works as expected: https://primer-88a2e13e51-13348165.drafts.github.io/storybook/?path=/story/components-selectpanel--default

Merge checklist

@changeset-bot

changeset-botBot commented Jan 17, 2025

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c874e45

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

This PR includes changesets to release 1 package
NameType
@primer/reactPatch

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-actionsgithub-actionsBot added the staff Author is a staff member label Jan 17, 2025
@github-actions

Copy link
Copy Markdown
Contributor

👋 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-actionsgithub-actionsBot added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Jan 17, 2025
@github-actions
github-actionsBottemporarily deployed to storybook-preview-5562 January 17, 2025 05:04 Inactive
@github-actions

github-actionsBot commented Jan 17, 2025

Copy link
Copy Markdown
Contributor

size-limit report 📦

PathSize
packages/react/dist/browser.esm.js105.84 KB (+0.14% 🔺)
packages/react/dist/browser.umd.js106.26 KB (+0.24% 🔺)

Comment threadpackages/react/src/hooks/useAnchoredPosition.ts Outdated
const floatingElementRef = useProvidedRefOrCreate(settings?.floatingElementRef)
const anchorElementRef = useProvidedRefOrCreate(settings?.anchorElementRef)
const [position, setPosition] = React.useState<AnchorPosition | undefined>(undefined)
const [_, setPrevHeight] = React.useState<number | undefined>(undefined)

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

used to force the height of the selectPanel when filtered and it wants to shrink but it's anchored at the top (we want it to stay at the top and lock the height)

Comment on lines +41 to +45
if (
settings?.pinPosition &&
prev &&
['outside-top', 'inside-top'].includes(prev.anchorSide) &&
(prev.anchorSide !== newPosition.anchorSide || prev.top < newPosition.top)

@francineluccafrancineluccaFeb 4, 2025

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

if the selectPanel is anchored to the top and it used to sit higher on the page....

(prev.anchorSide !== newPosition.anchorSide || prev.top < newPosition.top)
) {
const anchorTop = anchorElementRef.current?.getBoundingClientRect().top ?? 0
if (anchorTop > (floatingElementRef.current?.clientHeight ?? 0)) {

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

if the anchorTop is bigger than the selectPanel's height, that means there is plenty of space for the selectPanel to stay at the top

if (anchorTop > (floatingElementRef.current?.clientHeight ?? 0)) {
setPrevHeight(prevHeight => {
if (prevHeight && prevHeight > (floatingElementRef.current?.clientHeight ?? 0)) {
requestAnimationFrame(() => {

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

using requestAnimationFrame here to prevent a resizeObserver loop here due to us changing the element's height, but the observer listening for changes in the element...

const anchorTop = anchorElementRef.current?.getBoundingClientRect().top ?? 0
if (anchorTop > (floatingElementRef.current?.clientHeight ?? 0)) {
setPrevHeight(prevHeight => {
if (prevHeight && prevHeight > (floatingElementRef.current?.clientHeight ?? 0)) {

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

re-establish the height if it used to be bigger and is now attempting to shrink

Comment on lines +54 to +55
} else {
prev = newPosition

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

edgecase where the selectPanel is actually growing instead of shrinking, in this case we do want to allow it to recalculate/reposition

@francineluccafrancinelucca changed the title wip: SelectPanel overflowfix: SelectPanel overflowFeb 4, 2025
@francineluccafrancinelucca changed the title fix: SelectPanel overflowfix(SelectPanel): Correctly recalculate position on overflowFeb 4, 2025

@camertroncamertron left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Wow, this is really good stuff, nice work! 🎉

I noticed a flicker in one of the after videos where the panel shrinks but then immediately grows again. What do you think it would take to remove the flicker?

Comment on lines +43 to +46
settings?.pinPosition &&
prev &&
['outside-top', 'inside-top'].includes(prev.anchorSide) &&
(prev.anchorSide !== newPosition.anchorSide || prev.top < newPosition.top)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we wrap this in a function and give it some comments so we know what's going on when we come back to the code in a few months?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Done!

Comment on lines +48 to +49
const anchorTop = anchorElementRef.current?.getBoundingClientRect().top ?? 0
if (anchorTop > (floatingElementRef.current?.clientHeight ?? 0)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same question: maybe wrap in a function with a nice, intention-revealing name and some comments?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Done!

@emilybrickemilybrick left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Reviewing on behalf on design here - 👍

@github-actionsgithub-actionsBot added integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm and removed integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm labels Feb 10, 2025
@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

alignmentOffset,
anchorOffset,
className,
pinPosition,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we add this to AnchoredOverlay.docs.json?

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

Yes! Done!!

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@primer-integration

Copy link
Copy Markdown

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

@primer-integration

Copy link
Copy Markdown

🟢 golden-jobs completed with status success.

@github-actions

Copy link
Copy Markdown
Contributor

👋 Hi, there are new commits since the last successful integration test. We recommend running the integration workflow once more, unless you are sure the new changes do not affect github/github. Thanks!

@francinelucca

Copy link
Copy Markdown
MemberAuthor

@camertron cleaned up the useAnchoredPosition logic and split into functions, lmk how that looks.
As for the flashing, I tried a couple things with the visibility like you suggested but couldn't get it to bypass it. I think visibility won't help in this case because the flashing happens when the SelectPanel is already in view, user filter so SelectPanel shrinks, and then we re-establish the height when the useAnchoredPosition hooks runs again as a response to the element resizing

@primerprimerBot mentioned this pull request Feb 14, 2025
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

integration-tests: passingChanges in this PR do NOT cause breaking changes in gh/ghstaffAuthor is a staff memberstatus: review needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@francinelucca@camertron@emilybrick@TylerJDev