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

[popover2] feat: new prop targetProps #5802

Merged
merged 13 commits into from
Jan 23, 2023

Conversation

bvandercar-vt
Copy link
Contributor

@bvandercar-vt bvandercar-vt commented Dec 13, 2022

Fixes #0000

Checklist

  • Includes tests
  • Update documentation

Changes proposed in this pull request:

Allow targetProps to be passed to popover2 that get passed to the span wrapper of the popover target.

Mutually exclusive with renderTarget , since renderTarget doesn't get wrapped.

With existing functionality, this could still be accomplished by specifying a custom renderTarget that wraps their child in a span, ie before:

 <Popover2 {...popoverProps}>
    <Button  {...buttonProps} />
  </Popover2>

after:

<Popover2
    {...popoverProps}
    renderTarget={(props) => (
      <span {...props} {...targetProps}>
            <Button  {...buttonProps} />
      </span>
    )}
  />

But with this proposed change, one could do:

 <Popover2 {...popoverProps} targetProps={targetProps}>
    <Button  {...buttonProps} />
  </Popover2>

So, for us, this isn't an "essential" change, since we can accomplish the same with renderTarget-- but I wanted to propose it to the Blueprint team.

let target: JSX.Element | undefined;

if (renderTarget !== undefined) {
target = renderTarget({
...targetProps,
className: classNames(targetProps.className, targetModifierClasses),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

since we apply the fill class to the child target when renderTarget isn't defined, I figured we should apply this class to the custom target as well

Copy link
Contributor

@adidahiya adidahiya left a comment

Choose a reason for hiding this comment

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

Thanks for the PR @bvandercar-vt. This enhancement makes sense to me, especially after doing a bunch of Popover2 migrations of our internal code. When I initially designed Popover2, I figured most target customizations should happen via renderTarget, and that would be sufficient, but I now realize that it's a lot better from a developer experience perspective if we allow minor modifications to target element attributes through a new prop like this.

One use case I imagine this will be useful for is something like:

<Popover2 targetProps={{ style: { /* absolute positioning */ } }}>

On naming... to avoid potential confusion/conflation with "wrapper" terminology from Popover "v1", and because the existing prop which customizes the .bp4-popover-target element is named targetTagName (rather than targetWrapperTagName), I think this should be called targetProps.

*
* This prop is mutually exclusive with the `renderTarget` API.
*/
targetWrapperProps?: React.HTMLProps<HTMLSpanElement> | React.HTMLProps<HTMLDivElement>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
targetWrapperProps?: React.HTMLProps<HTMLSpanElement> | React.HTMLProps<HTMLDivElement>;
targetProps?: TProps;

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK done, please review.

In the case of a renderTarget, targetProps props will also be appliedto the renderTarget, so I made the warning basically say that they will be applied, but that it doesn't really make sense to do it that way vs. just applying them in your renderTarget.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@adidahiya I'm not sure why CI is failing, is TProps not the best type for targetProps here maybe?

Copy link
Contributor

Choose a reason for hiding this comment

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

TProps is the correct type to use here, but adding this constraint exposed some type issues with the way I had designed Popover2. It required adding a stricter typedef to validateProps, which further exposed some complex issues with the renderTarget API and the inferred value of TProps. I think I've solved those issues in the commits I just pushed to this branch.

@adidahiya adidahiya changed the title feat: new prop targetWrapperProps in popover2 [popover2] feat: new prop targetWrapperProps Jan 10, 2023
@bvandercar-vt bvandercar-vt changed the title [popover2] feat: new prop targetWrapperProps [popover2] feat: new prop targetProps Jan 11, 2023
@adidahiya
Copy link
Contributor

I've updated your PR to no longer inject props.targetProps into props.renderTarget -- it was causing type issues and it's not necessary to support. I've also updated the error message to reflect this change.

@adidahiya
Copy link
Contributor

@bvandercar-vt this is nearly good to go, I just need to test it out locally to see if it breaks anything downstream... stay tuned, I'll try to get this in for the release I'm cutting today

@adidahiya
Copy link
Contributor

This change seems to work well downstream for the renderTarget API... it allows us to clean up some code, too, for example:

class MyComponent extends React.PureComponent {
    public render() {
        return (
-           <Popover2<React.HTMLProps<HTMLDivElement>>
+           <Popover2
                renderTarget={this.renderTarget}
                content="content"
            />
        );
    }

    private renderTarget = ({
        isOpen,
        ref,
        ...targetProps
-    }: Popover2TargetProps & React.HTMLProps<HTMLDivElement>) => {
+    }: Popover2TargetProps & Popover2ClickTargetHandlers) => {
        return (
            <div
                ref={ref}
                {...targetProps}
            />
        );
    };
}

@adidahiya adidahiya merged commit 8d793f6 into palantir:develop Jan 23, 2023
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.

None yet

2 participants