Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds open, onOpenChange, and anchorRef props to DropdownMenu #1372

Merged
merged 5 commits into from
Aug 10, 2021

Conversation

jfuchs
Copy link
Contributor

@jfuchs jfuchs commented Aug 9, 2021

This extends DropdownMenu to allow:

  1. externally controlling the open state (via open and onOpenChange props
  2. setting an anchorRef prop to control the positioning of the overlay.

Closes #1369.

Screenshots

Screen Shot 2021-08-09 at 3 41 01 PM

Merge checklist

  • Added/updated tests
  • Added/updated documentation
  • Tested in Chrome
  • Tested in Firefox
  • Tested in Safari
  • Tested in Edge

Take a look at the What we look for in reviews section of the contributing guidelines for more information on how we review PRs.

@jfuchs jfuchs requested review from dgreif and colebemis August 9, 2021 22:55
@changeset-bot
Copy link

changeset-bot bot commented Aug 9, 2021

🦋 Changeset detected

Latest commit: 8f67fe8

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

This PR includes changesets to release 1 package
Name Type
@primer/components 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 Aug 9, 2021

size-limit report 📦

Path Size
dist/browser.esm.js 48.5 KB (+0.07% 🔺)
dist/browser.umd.js 48.78 KB (+0.07% 🔺)

@jfuchs
Copy link
Contributor Author

jfuchs commented Aug 9, 2021

Let me know if yall think this merits a test!

const renderMenuAnchor = useCallback(
<T extends React.HTMLAttributes<HTMLElement>>(props: T) => {
return renderAnchor({
const renderMenuAnchor = useMemo(() => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just curious, what happens if both renderAnchor and anchorRef are passed to DropdownMenu?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If they're both passed, the renderAnchor function is called with anchorRef as a prop (which would mean putting the same ref in two DOM nodes, which seems wrong but I don't know how it'd break. It's almost certainly not an intended usage, but I'm aiming to mirror what I saw elsewhere.

I spoke with @dgreif about this yesterday, and it sounds like the prop types in AnchoredOverlay could have been narrowed (specifically in AnchoredOverlayPropsWithAnchor such that anchorRef did not exist), except it made destructuring props messier.

</Box>
</Box>
<DropdownMenu
renderAnchor={null}
Copy link
Contributor

Choose a reason for hiding this comment

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

Is explicitly setting renderAnchor to null required in order to use anchorRef? If so, I can see that being a confusing API for consumers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep. I tried to mirror SelectPanel, where null and undefined have two distinct uses:

  • Passing undefined means that the component should provide a default renderAnchor method
  • null means that the component should not provide a default, and instead pass the null through to AnchoredOverlay (in the case where you wanted AnchoredOverlay to just use the anchorRef for anchoring).

It's a little wonky, but my inclination is to try to clean all of these up in a future PR. I'd like to hear your thoughts though!

@jfuchs jfuchs requested a review from colebemis August 10, 2021 16:13
Copy link
Contributor

@colebemis colebemis left a comment

Choose a reason for hiding this comment

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

These changes look good 👍

I'm looking forward to your follow up PR to clean up the renderAnchor + anchorRef API across all the overlay components 😄

src/DropdownMenu/DropdownMenu.tsx Outdated Show resolved Hide resolved
@@ -33,35 +29,53 @@ export interface DropdownMenuProps extends Partial<Omit<GroupedListProps, keyof
* Props to be spread on the internal `Overlay` component.
*/
overlayProps?: Partial<OverlayProps>

/**
* If defined, will control the open/closed state of the overlay. Must be used in conjuction with `onOpenChange`.
Copy link
Contributor

@colebemis colebemis Aug 10, 2021

Choose a reason for hiding this comment

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

Should we be explicit here about how the open state is managed if open is not defined? (i.e. it becomes an uncontrolled component)

Co-authored-by: Cole Bemis <colebemis@github.com>
@jfuchs jfuchs merged commit 23be0ed into main Aug 10, 2021
@jfuchs jfuchs deleted the jfuchs-anchorRef-for-DropdownMenu branch August 10, 2021 20:21
@primer-css primer-css mentioned this pull request Aug 11, 2021
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.

Allow external anchorRef for DropdownMenu
2 participants