Skip to content

Conversation

@siddharthkp
Copy link
Member

@siddharthkp siddharthkp commented Mar 15, 2024

The problem:

When an html <dialog> is not "open", it has the dimensions of 0px by 0px, which means the anchored position is not able to calculate if the dialog is going beyond the window boundary.

1.problem.mov

Solution

We need to update position after dialog.showModal() has "opened" the dialog and given it dimensions. This, however, creates a new problem of visible layout shift which can look janky.

In Safari, you see the dialog move but it's done before you can tell what happened:

2.position.shift.mov

In Chrome, you can really see the page glitching because for a tiny moment, Chrome tries to horizontally scroll the page to make sure the dialog is visible:

2.position.shift.chrome.mov

Polish

We can solve this by adding a minuscule delay to the animating-in, this gives us just enough time to set the correct position (one tick)

3.gefixed.mov

@changeset-bot
Copy link

changeset-bot bot commented Mar 15, 2024

🦋 Changeset detected

Latest commit: 15c0853

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 Patch

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
Copy link
Contributor

github-actions bot commented Mar 15, 2024

size-limit report 📦

Path Size
packages/react/dist/browser.esm.js 88.65 KB (+0.06% 🔺)
packages/react/dist/browser.umd.js 88.81 KB (+0.02% 🔺)

@github-actions github-actions bot temporarily deployed to storybook-preview-4396 March 15, 2024 16:13 Inactive
sx={{
// to avoid a visible position shift, we delay the overlay animating-in
// to wait until the correct position is set (see useAnchoredPosition above for more)
animationDelay: '16ms',
Copy link
Member Author

Choose a reason for hiding this comment

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

Note for reviewer: This isn't scientific at all, but we need to pick a number, so based it off a 60Hz refresh rate 😅

From https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame,

The frequency of calls to the callback function will generally match the display refresh rate. The most common refresh rate is 60hz, (60 cycles/frames per second), though 75hz, 120hz, and 144hz are also widely used. requestAnimationFrame() calls are paused in most browsers when running in background tabs or hidden iframes, in order to improve performance and battery life.

Copy link
Member Author

Choose a reason for hiding this comment

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

An alternative approach would be to "watch" for dialog open. Either in a recursive timeout or intersection observer, but that felt overkill!

/* Dialog */
const dialogRef = React.useRef<HTMLDialogElement>(null)

/* Anchored position */
Copy link
Member Author

Choose a reason for hiding this comment

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

Note for reviewer: This function already existed, just moved it above

animation: overlay-appear ${animationDuration}ms ${get('animation.easeOutCubic')};
animation-fill-mode: forwards;
opacity: 0;
Copy link
Member Author

Choose a reason for hiding this comment

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

Note for reviewer: Need to add this if we want to delay animation

@siddharthkp siddharthkp self-assigned this Mar 15, 2024
@github-actions github-actions bot temporarily deployed to storybook-preview-4396 March 15, 2024 16:30 Inactive
@siddharthkp siddharthkp removed the request for review from iansan5653 March 18, 2024 10:32
@siddharthkp siddharthkp changed the title exerimental/SelectPanel: Update anchored position after showModal experimental/SelectPanel: Update anchored position after showModal Mar 18, 2024
Copy link
Member

@broccolinisoup broccolinisoup left a comment

Choose a reason for hiding this comment

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

Same problem as we had on tooltip! I think delaying it with an animation makes sense to me.

if (internalOpen) {
dialogRef.current?.showModal()
updatePosition() // update the position once the dialog is open
} else if (dialogRef.current?.open) dialogRef.current.close()
Copy link
Contributor

@keithamus keithamus Mar 21, 2024

Choose a reason for hiding this comment

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

This could be inlined

Suggested change
} else if (dialogRef.current?.open) dialogRef.current.close()
} else dialogRef.current?.close()

@siddharthkp siddharthkp added the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Mar 21, 2024
@siddharthkp
Copy link
Member Author

Note for self: This change seems to break tests (both in this repo and dotcom) where we instantly check if Overlay contents are visible (while they are animating)

Need to reduce the surface area of this change just to SelectPanel

@github-actions
Copy link
Contributor

Hi! This pull request has been marked as stale because it has been open with no activity for 60 days. You can comment on the pull request or remove the stale label to keep it open. If you do nothing, this pull request will be closed in 7 days.

@github-actions github-actions bot added the Stale label May 20, 2024
@github-actions github-actions bot closed this May 27, 2024
@github-actions github-actions bot deleted the drafts-selectpanel-anchored-position-fix branch May 27, 2024 14:04
@siddharthkp siddharthkp removed the integration-tests: recommended This change needs to be tested for breaking changes. See https://arc.net/l/quote/tdmpakpm label Aug 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants