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

fix(blade): chipgroup grid alignment #2536

Open
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

tewarig
Copy link
Contributor

@tewarig tewarig commented Feb 9, 2025

Description

ref - https://razorpay.slack.com/archives/CMQ3RBHEU/p1738752395317139

Changes

Additional Information

Component Checklist

  • Update Component Status Page
  • Perform Manual Testing in Other Browsers
  • Add KitchenSink Story
  • Add Interaction Tests (if applicable)
  • Add changeset

Copy link

changeset-bot bot commented Feb 9, 2025

🦋 Changeset detected

Latest commit: a1f66f9

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

This PR includes changesets to release 1 package
Name Type
@razorpay/blade 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

Copy link
Contributor

github-actions bot commented Feb 9, 2025

✅ PR title follows Conventional Commits specification.

Copy link

codesandbox-ci bot commented Feb 9, 2025

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit a1f66f9:

Sandbox Source
razorpay/blade: basic Configuration

@rzpcibot
Copy link
Collaborator

rzpcibot commented Feb 9, 2025

Bundle Size Report

Updated Components
Status Component Base Size (kb) Current Size (kb) Diff
Chip, ChipGroup 8.486 8.530 +0.044 KB
DatePicker 87.068 87.119 +0.051 KB
Indicator 1.087 1.089 +0.002 KB

Generated by 🚫 dangerJS against a1f66f9

@anuraghazra
Copy link
Member

anuraghazra commented Feb 10, 2025

We should ideally do this, and let consumer handle the layout.

      <ChipGroupComponent
        selectionType="single"
        label="Select a gift card with value (custom chipGroupContainerLayout)"
      >
        <Box display="grid" gridTemplateColumns="1fr 1fr 1fr">
          {chipArray.map((chip, index) => (
            <ChipComponent key={index} value={chip.value}>
              {chip.label}
            </ChipComponent>
          ))}
        </Box>
      </ChipGroupComponent>

Only challenge is internally we are applying some default margins to each Chip component, we need to somehow make it work with the above example + keep the existing behaviour intact.

Maybe we could do something like:

            <BaseBox
              display="flex"
              flexDirection="row"
              flexWrap="wrap"
              rowGap={chipGroupGapTokens[size].bottom}
              columnGap={chipGroupGapTokens[size].right}
              marginBottom={chipGroupGapTokens[size].bottom}
            >
              {React.Children.map(children, (child, index) => {
                return <BaseBox key={index}>{child}</BaseBox>; // maybe we can remove the box if needed
              })}
            </BaseBox>

@tewarig
Copy link
Contributor Author

tewarig commented Feb 10, 2025

We should ideally do this, and let consumer handle the layout.

      <ChipGroupComponent
        selectionType="single"
        label="Select a gift card with value (custom chipGroupContainerLayout)"
      >
        <Box display="grid" gridTemplateColumns="1fr 1fr 1fr">
          {chipArray.map((chip, index) => (
            <ChipComponent key={index} value={chip.value}>
              {chip.label}
            </ChipComponent>
          ))}
        </Box>
      </ChipGroupComponent>

Only challenge is internally we are applying some default margins to each Chip component, we need to somehow make it work with the above example + keep the existing behaviour intact.

Maybe we could do something like:

            <BaseBox
              display="flex"
              flexDirection="row"
              flexWrap="wrap"
              rowGap={chipGroupGapTokens[size].bottom}
              columnGap={chipGroupGapTokens[size].right}
              marginBottom={chipGroupGapTokens[size].bottom}
            >
              {React.Children.map(children, (child, index) => {
                return <BaseBox key={index}>{child}</BaseBox>; // maybe we can remove the box if needed
              })}
            </BaseBox>

thanks for suggesting this... i have implemented this... the api looks like

  <ChipGroupComponent
        selectionType="single"
        label="Select a gift card with value (custom chipGroupContainerLayout)"
      >
        <Box
          display="grid"
          gridTemplateColumns="repeat(3, minmax(0,120px))"
          gridTemplateRows="repeat(3, minmax(0,30px))"
          gap="spacing.3"
        >
          {chipArray.map((chip, index) => (
            <ChipComponent key={index} value={chip.value} width="120px">
              {chip.label}
            </ChipComponent>
          ))}
        </Box>
      </ChipGroupComponent>

also regarding that margin ... i think we don't need to do anything .. we can get children's from wrapper and render them.

   {React.Children.map(getChipWrapperChildren(), (child, index) => {
                return (
                  <BaseBox
                    key={index}
                    marginBottom={chipGroupGapTokens[size].bottom}
                    marginRight={chipGroupGapTokens[size].right}
                  >
                    {child}
                  </BaseBox>
                );
              })}

@@ -68,6 +70,24 @@ const _ChipGroup = (
});
}
}
const isWrapperLayoutControlled =
typeof children === 'object' && getComponentId(children) === 'Box';
Copy link
Member

Choose a reason for hiding this comment

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

            <BaseBox
              display="flex"
              flexDirection="row"
              flexWrap="wrap"
              rowGap={chipGroupGapTokens[size].bottom}
              columnGap={chipGroupGapTokens[size].right}
              marginBottom={chipGroupGapTokens[size].bottom}
            >
              {React.Children.map(children, (child, index) => {
                return <BaseBox key={index}>{child}</BaseBox>; // maybe we can remove the box if needed
              })}
            </BaseBox>

This code i shared, should just work without doing any of these checks/conditionals.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, but I think we should add a wrapper and check for styles since consumers can pass props like background color or margin and padding, which should not be supported.

Copy link
Member

Choose a reason for hiding this comment

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

We should not do arbitrary checks if it's absolutely not necessary. If they add background etc anyways it will look odd.

Your above code will fail in many cases like so:

const SomeCustomWrapperBox = styled(Box)``

<ChipGroup>
  <SomeCustomWrapperBox>
    ...
  </SomeCustomWrapperBox>
</ChipGroup>
``

@tewarig tewarig force-pushed the fix/chipgroup-grid-alignment branch from 177d4f9 to 72efaeb Compare February 10, 2025 11:48
Comment on lines 99 to 100
<BaseBox display="flex" flexDirection="row" flexWrap="wrap">
{React.Children.map(children, (child, index) => {
return (
<BaseBox
key={index}
marginBottom={chipGroupGapTokens[size].bottom}
marginRight={chipGroupGapTokens[size].right}
>
{child}
</BaseBox>
);
})}
{React.Children.map(children, (child) => child)}
Copy link
Member

Choose a reason for hiding this comment

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

Again, we need to keep the row gap etc props to make sure we are not changing the existing spacing that was there PLUS we let consumers handle the layout if they want.

            <BaseBox
              display="flex"
              flexDirection="row"
              flexWrap="wrap"
              // Keep existing spacing that was there
              rowGap={chipGroupGapTokens[size].bottom}
              columnGap={chipGroupGapTokens[size].right}
              marginBottom={chipGroupGapTokens[size].bottom}
            >
              {React.Children.map(children, (child, index) => {
                return <BaseBox key={index}>{child}</BaseBox>;
              })}
            </BaseBox>

Copy link
Contributor Author

@tewarig tewarig Feb 11, 2025

Choose a reason for hiding this comment

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

https://github.com/razorpay/blade/blob/98296fb7f8da7dfbb9a9db44e5b7e0fa957ddf51/packages/blade/src/components/Chip/Chip.tsx
Moved that to Chip, consumers can modify it from there.
Adding spacing on the wrapper won't work since this spacing needs to be applied to Chip.

Copy link
Member

@anuraghazra anuraghazra Feb 11, 2025

Choose a reason for hiding this comment

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

@tewarig reusable components should not have margins, they are bit harmful. If in future we want to expose Chip as a standalone component (eg: Clickable only chip) then it will break component encapsulation.

Adding spacing on the wrapper won't work since this spacing needs to be applied to Chip.

Thus the BaseBox i've added on my example.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense

columnGap={chipGroupGapTokens[size].right}
marginBottom={chipGroupGapTokens[size].bottom}
>
{React.Children.map(children, (child) => child)}
Copy link
Member

Choose a reason for hiding this comment

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

Probably can just be {children}

Comment on lines 793 to 798
gridTemplateColumns="repeat(3, minmax(0,120px))"
gridTemplateRows="repeat(3, minmax(0,30px))"
gap="spacing.3"
>
{chipArray.map((chip, index) => (
<ChipComponent key={index} value={chip.value} width="120px">
Copy link
Member

@anuraghazra anuraghazra Feb 11, 2025

Choose a reason for hiding this comment

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

🤔 We shouldn't need to add explicit pixel values in ChipComponent.

ideally width=100% or flex={1} should work, instead of hard coding 120px like so:

<ChipComponent key={index} value={chip.value} width="100%" />

I would assume this would work and the chip should automatically stretch/flex to available space.

Not to mention explicit pixel values will break the layout if there is no space:

image

@@ -144,5 +144,5 @@ const getStyledProps = (props: Record<string, any>): StyledPropsBlade => {
return removeUndefinedStyledProps(makeStyledProps(props));
};

export type { StyledPropsBlade };
export type { StyledPropsBlade, StyledPropsInputType };
Copy link
Member

Choose a reason for hiding this comment

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

where is this used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

@@ -332,5 +332,5 @@ type BoxRefType = Platform.Select<{
native: View;
}>;

export type { BaseBoxProps, BoxProps, BoxRefType, StyledPropsBlade, FlexboxProps };
export type { BaseBoxProps, BoxProps, BoxRefType, StyledPropsBlade, FlexboxProps, GridProps };
Copy link
Member

Choose a reason for hiding this comment

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

where is this used?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

removed

@@ -39,7 +39,7 @@ type OnChange = ({
}) => void;

const _Chip: React.ForwardRefRenderFunction<BladeElementRef, ChipProps> = (
{ isDisabled, value, children, icon: Icon, color, testID, _motionMeta, ...rest },
{ isDisabled, value, children, icon: Icon, color, testID, _motionMeta, width, ...rest },
Copy link
Member

Choose a reason for hiding this comment

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

we should expose minWidth, maxWidth as well right if we're exposing width?

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.

4 participants