Skip to content

chore(site): add custom popover component #10319

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

Merged
merged 20 commits into from
Oct 19, 2023
Merged

Conversation

BrunoQuaresma
Copy link
Collaborator

@BrunoQuaresma BrunoQuaresma commented Oct 17, 2023

Usage:

<Popover>
  <PopoverTrigger>
    <button>Open</button>
  </PopoverTrigger>
  <PopoverContent>
    Some content here!
  </PopoverContent>
</Popover>

or

<Popover>
  {(popover) => (
    <>
      <PopoverTrigger>
        <button>Open</button>
      </PopoverTrigger>
      <PopoverContent>
        Some content here!
      </PopoverContent>
    </>
  )}
</Popover>

@BrunoQuaresma BrunoQuaresma self-assigned this Oct 17, 2023
@BrunoQuaresma
Copy link
Collaborator Author

@Parkreiner about using ref inside the render phase, I think it is ok for now since it is how MUI works and we are using it. I would guess they are going to update it if it becomes a problem since they have a huge user base.

@BrunoQuaresma
Copy link
Collaborator Author

@Parkreiner it is done. The only place I didn't change was the HelpTooltip because I wanted to refactor it later. I think its usage is kinda bad and needs some deep refactoring.

Copy link
Member

@Parkreiner Parkreiner left a comment

Choose a reason for hiding this comment

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

Looks really good to me overall, and it's good to hear that the swapping process wasn't a nightmare.

Going to approve to avoid blocking you, but still left some comments for the new implementation


type TriggerMode = "hover" | "click";

type TriggerRef = React.RefObject<HTMLElement>;
Copy link
Member

Choose a reason for hiding this comment

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

Do you think it's worth genericizing this? Something like:

type TriggerRef <Ele extends HTMLELement = HTMLElement> = React.RefObject<Ele>;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Hm... I don't think so. I think HTMLElement is generic enough. Do you have any use case in mind?

Copy link
Member

@Parkreiner Parkreiner Oct 18, 2023

Choose a reason for hiding this comment

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

Well, genericizing might be the wrong word, but basically, adding type parameters. We're not exporting TriggerRef, but we are exporting the hook that contains it, and I'm worried that someone might try to reuse the ref from the hook for some other logic, and in some cases, HTMLElement might cause type mismatches because it isn't specific enough

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think it is okay for now, I would not think too much about all possible use cases right now but only on the use cases that we have. We can change it in the future if it is needed.


type TriggerElement = ReactElement<{
onClick?: () => void;
ref: TriggerRef;
Copy link
Member

Choose a reason for hiding this comment

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

Does this work with the intrinsic elements only (div, h1, etc.), or does it also work with any component that works with forwardRef?

I know Radix uses React's ForwardRefExoticComponent type under the hood, but I don't really know what it does, or if it's necessary here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I know it works with any other elements like <Button> that supports forwardRef. ForwardRefExoticComponent looks dark magic 😆

Copy link
Member

Choose a reason for hiding this comment

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

Yeah...it scares me, too

);

export const Popover = (props: {
children: ReactNode | ((popover: PopoverContextValue) => ReactNode); // Allows inline usage
Copy link
Member

Choose a reason for hiding this comment

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

Do you feel like this should support arrays, too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I'm quite sure ReactNode does support it already but if not, I think we can add it when we need it.

@@ -0,0 +1,163 @@
import {
Copy link
Member

Choose a reason for hiding this comment

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

I really like this new implementation! Definitely less chaotic than what I had lol

},
};

return cloneElement(props.children, {
Copy link
Member

@Parkreiner Parkreiner Oct 18, 2023

Choose a reason for hiding this comment

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

Actually, I thought of one more suggestion for the trigger: is there a way for you to merge in the aria-haspopup and aria-owns props in as well, just to make sure that the trigger is getting picked up properly by screen readers?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sure, I will take a look and see how to add them.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you have good material about that? I'm not sure how to make this happen 🤔

Copy link
Member

Choose a reason for hiding this comment

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

I actually saw it in MUI's documentation – it's in the source code for the hover popover example:
https://mui.com/material-ui/react-popover/

I'm not sure how the React.clone operation would need to be changed, but two properties would need to be added in:

{
  "aria-owns": isOpen ? "some-id-value" : undefined,
  "aria-haspopup": true
}

But I can also take a look into this later today

@BrunoQuaresma BrunoQuaresma merged commit f677c44 into main Oct 19, 2023
@BrunoQuaresma BrunoQuaresma deleted the bq/custom-popover-component branch October 19, 2023 12:13
@github-actions github-actions bot locked and limited conversation to collaborators Oct 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants