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

feat(components): update Chip.Prefix to accept more than Icon and Avatar #2020

Merged
merged 5 commits into from
Sep 18, 2024

Conversation

demoraesgui
Copy link
Contributor

@demoraesgui demoraesgui commented Sep 10, 2024

Motivations

It would be nice to be able to add like a logo or a custom image to the prefix

Changes

Chip.Prefix now accepts anything, but if you provide either an Avatar or an Icon you get the fallback behavior

Changes can be
tested via Pre-release


In Atlantis we use Github's built in pull request reviews.

Random photo of Atlantis

Copy link

cloudflare-workers-and-pages bot commented Sep 10, 2024

Deploying atlantis with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0ae367e
Status: ✅  Deploy successful!
Preview URL: https://d1695116.atlantis.pages.dev
Branch Preview URL: https://feat-update-chip-to-allow-mo.atlantis.pages.dev

View logs

@demoraesgui demoraesgui marked this pull request as ready for review September 11, 2024 20:26
@demoraesgui demoraesgui requested a review from a team as a code owner September 11, 2024 20:26
@demoraesgui demoraesgui self-assigned this Sep 11, 2024
@taylorvnoj taylorvnoj self-requested a review September 17, 2024 14:27
children,
d => d.type === Avatar || d.type === Icon,
);

return (
<span className={classNames(styles.prefix, !singleChild && styles.empty)}>
Copy link
Contributor

@ZakaryH ZakaryH Sep 17, 2024

Choose a reason for hiding this comment

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

I think we still need the behavior from the styles.empty

what the empty style is doing is setting display: none on the span in the event that we didn't receive a valid child

without that, if you do <Chip.Prefix/> we are rendering an inline-block span that doesn't really need to be there at all

image

if I'm understanding this correctly, the reason it was done like this previously was that we might have children, but we had to check what type they were before we could know if they were valid.

typically if you don't want something showing up, you should just not render it at all one level rather than hiding it or returning null inside the component itself.

I think now though, we can know that up in Chip if prefix.props.children is nothing, then we have nothing to render as a Prefix, and we shouldn't render it at all which skips us having to add the display: none style altogether.

const prefixHasContent = prefix?.props.children

...

{prefixHasContent && prefix}

the variable assignment might be overkill. prefix?.props.children is pretty easy to understand, and might not need a descriptive name.

that should also remove the need for any of the avatarOrIcon logic too. we don't care what you gave us, we'll just render the children. keeps the Prefix dumb, and Chip is now responsible for making sure we're using Prefix when it makes sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the feedback @ZakaryH I'm going to update the PR in a couple hours.

Copy link
Contributor

@ZakaryH ZakaryH Sep 17, 2024

Choose a reason for hiding this comment

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

oh, actually around my comment about not needing avatarOrIcon - I might have misunderstood the purpose

is that so that we only apply the styles.prefix to that type of children? everything else, the consumer is responsible for the layout styles and encapsulating markup?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@ZakaryH avatarOrIcon was also added because there is some styling being added to ensure the Avatar or Icon gets border-radius: var(--radius-circle);

Copy link
Contributor Author

@demoraesgui demoraesgui Sep 17, 2024

Choose a reason for hiding this comment

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

This style shouldn't be enforced to a custom prefix. How you want me to handle this?

Copy link
Contributor

Choose a reason for hiding this comment

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

interesting. ok yeah then we might still need that after all.

though I don't really love the idea of different compositions behaving differently.

if I do

<Chip>
  <Chip.Prefix><Icon name="whatever"/></Chip.Prefix>
</Chip>

this renders markup that I don't have control over

whereas

<Chip>
  <Chip.Prefix><StatusLabel variation="whatever"/></Chip.Prefix>
</Chip>

this will render exactly what I gave it

in a weird way, we're making Icon/Avatar compositions more restricted. though we do have to consider all the existing uses that do expect us to be taking care of the layout. that's tricky.

we want a consistent API, with equal freedom regardless of what it is given, but also we don't want to break all current uses 😅

Copy link
Contributor Author

@demoraesgui demoraesgui Sep 17, 2024

Choose a reason for hiding this comment

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

yeah, that's tricky. But regardless of how we deal with this styling, the prefixHasContent guard feels like something we would still want.

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed. the conditional rendering avoids the empty style, and I like it better overall.

I'm thinking about how to handle this other problem and if there's a way for us to get everything we want...

@ZakaryH
Copy link
Contributor

ZakaryH commented Sep 17, 2024

couple other thoughts:

Chips/Chip - it has similar restrictions on the Prefix. I wonder if we should do something similar there.

Suffix - same idea. should we apply this freedom there too, and on both implementations?

I know that's quite a bit more scope, and if this Chip.Prefix is all you need - then that's fair. I don't want to sign you up for a bunch of other work. however I do want to make sure we're keeping track of inconsistencies, and things that we should follow up on if we think this is the direction we want to go with Prefix/Suffix on Chip

@demoraesgui
Copy link
Contributor Author

demoraesgui commented Sep 17, 2024

couple other thoughts:

Chips/Chip - it has similar restrictions on the Prefix. I wonder if we should do something similar there.

Suffix - same idea. should we apply this freedom there too, and on both implementations?

I know that's quite a bit more scope, and if this Chip.Prefix is all you need - then that's fair. I don't want to sign you up for a bunch of other work. however I do want to make sure we're keeping track of inconsistencies, and things that we should follow up on if we think this is the direction we want to go with Prefix/Suffix on Chip

That's fair, I brought up some of this on the last office hours. I think I'm going to join office hours again if I get blocked.
We only need the prefix change, but I'm going to take a look at the suffix as well if the changes aren't that bad we can add on this PR. Not sure about Chips though, if the changes aren't that crazy I'm going to add them as well.

@demoraesgui
Copy link
Contributor Author

demoraesgui commented Sep 17, 2024

@ZakaryH looking at the amount of conditional logic in Chip.Suffix I feel like including its changes on this PR will increase a lot the complexity. Can this be something we track in Atlantis backlog instead?

There are keyboard/mouse events, allowed children (subset of icons) and accessibility as well. 😅

@ZakaryH
Copy link
Contributor

ZakaryH commented Sep 17, 2024

@ZakaryH looking at the amount of conditional logic in Chip.Suffix I feel like including its changes on this PR will increase a lot the complexity. Can this be something we track in Atlantis backlog instead?

There are keyboard/mouse events, allowed children (subset of icons) and accessibility as well. 😅

yeah that's fair. I kind of thought that would be the case. we can make a note of that and track the work for later.

thanks for looking/trying!

@demoraesgui demoraesgui force-pushed the feat/update-chip-to-allow-more-than-icon-and-avatar branch from e86679b to 9c0b589 Compare September 17, 2024 17:22
@ZakaryH
Copy link
Contributor

ZakaryH commented Sep 17, 2024

@demoraesgui alright, after thinking about this more and talking with a teammate I think it's fine to have the conditional extra span and styles.prefix

existing usages will continue to work and be simple. new usages will have the freedom to build whatever layout they need.

then, if for some reason you want a custom layout with an Avatar or Icon, you can simply wrap it in a fragment or div or span or anything really, and that will avoid the Icon and Avatar type check

the only thing I'd suggest is that we document this behavior and say something like

When Chip.Prefix is provided an Icon or Avatar as the immediate child or children, some extra markup and styles will automatically be added. If these styles and markup are not desired, you may wrap the Avatar(s) or Icon(s) in any other element and provide your own layout.

@@ -33,6 +33,8 @@ export const Chip = ({
const prefix = useChildComponent(children, d => d.type === Chip.Prefix);
const suffix = useChildComponent(children, d => d.type === Chip.Suffix);

const prefixHasContent = !!prefix?.props?.children;
Copy link
Contributor

@ZakaryH ZakaryH Sep 17, 2024

Choose a reason for hiding this comment

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

@demoraesgui

whoops, I was looking at the wrong span this whole time. the one you can see in my first screenshot is the labelRef span which is always there.

the prefix span will not be rendered anyway because if you pass nothing as a child to Chip.Prefix then children is undefined and we do

if (!avatarOrIcon) return children as React.ReactElement;

so what you had originally did work for not rendering the span. my bad! we can get rid of this prefixHasContent and conditional rendering.

though that does make me question the as React.ReactElement. we're overriding TypeScript and I'm not sure we should be. without this casting, it is correctly going to complain that Chip.Prefix could be undefined which is not a valid JSX Element.

instead of casting it as React.ReactElement which might not be true, inside Chip.Prefix let's do

if (!avatarOrIcon) return <>{children}</>;

that ensures we're always returning valid JSX, and if it's empty then it won't render anything

also, this will make sure that passing multiple elements is valid. I don't exactly know what you'd be doing, but this isn't valid right now because it has no surrounding element

image

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh I see, I had that before, and the as React.ReactElement was something we added in an office hours. I'll update the PR in a bit. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

@demoraesgui ah sorry I wasn't there for office hours

do you remember why we didn't want to use a fragment?

if there's a good reason and we've already decided to use the casting I would be open to doing it this way, I just don't like casting things in general - and I know there's at least 1 React error that this casting will suppress

Copy link
Contributor Author

Choose a reason for hiding this comment

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

TBH I prefer not casting as well. I don't recall if there was a particular reason. It was more like, typescript is breaking and this could be an option to fix it.

@ZakaryH
Copy link
Contributor

ZakaryH commented Sep 18, 2024

tried it out with a bunch of different prefix content
image

no TS errors even with multiple elements passed in as immediate children, nor when no content passed - also for the latter the extra span for the prefix is not being rendered

image

Copy link
Contributor

@ZakaryH ZakaryH left a comment

Choose a reason for hiding this comment

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

LGTM thanks for making this PR and dealing with all the back and forth!

@ZakaryH ZakaryH merged commit 1a6c72c into master Sep 18, 2024
11 checks passed
@ZakaryH ZakaryH deleted the feat/update-chip-to-allow-more-than-icon-and-avatar branch September 18, 2024 18:33
@demoraesgui
Copy link
Contributor Author

No worries, thanks for great feedback and QA :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

2 participants