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(SubBlocks): add possibility to position controls within cards at footer #823

Merged
merged 6 commits into from
Mar 1, 2024

Conversation

DC-RomanKarpov
Copy link
Contributor

@DC-RomanKarpov DC-RomanKarpov commented Feb 20, 2024

No description provided.

@DC-RomanKarpov DC-RomanKarpov self-assigned this Feb 20, 2024
@DC-RomanKarpov DC-RomanKarpov changed the title feat(SubBlocks): add possibility to position controls within cards at… feat(SubBlocks): add possibility to position controls within cards at footer Feb 20, 2024
@gravity-ui-bot
Copy link
Contributor

Preview is ready.

@@ -6,6 +6,7 @@ export {default as BackLink} from './BackLink/BackLink';
export {default as BalancedMasonry} from './BalancedMasonry/BalancedMasonry';
export {default as BlockBase} from './BlockBase/BlockBase';
export {default as Button} from './Button/Button';
export {Buttons} from './Buttons/Buttons';
Copy link
Collaborator

Choose a reason for hiding this comment

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

could we make it consistent with other exports?

colSizes={{all: 12, md: 12}}
/>
</CardBase.Content>
<CardBase.Footer className={b('footer')}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

{ controlPosition === 'footer' && <CardBase.Footer className={b('footer')}>...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That does not work that way =)
The CardBase component requires that children type will ReactElement | ReactElement[] I thought about separate child creation but it looks quite ugly.

@@ -140,6 +140,7 @@ export interface BackgroundCardProps
background?: ThemeSupporting<ImageObjectProps>;
paddingBottom?: 's' | 'm' | 'l' | 'xl';
backgroundColor?: string;
controlPosition?: 'content' | 'footer';
}

export interface BasicCardProps
Copy link
Collaborator

Choose a reason for hiding this comment

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

`interface CardLayoutProps = {
controlPosition?: 'content' | 'footer';
}

...

export interface BannerCardProps extends CardLayoutProps
`

@@ -46,16 +51,30 @@ const BackgroundCard = (props: BackgroundCardProps) => {
style={{backgroundColor}}
/>
<Content
titleId={titleId}
Copy link
Collaborator

Choose a reason for hiding this comment

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

const controlPositionFooter = controlPosition === 'footer'
...
links={controlPositionFooter ? undefined : links}

size="s"
colSizes={{all: 12, md: 12}}
/>
</IconWrapper>
</CardBase.Content>
<CardBase.Footer className={b('footer')}>
Copy link
Collaborator

Choose a reason for hiding this comment

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

confused a littler that we should copy-paster this 3 times, could we create component for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The main problem that no, we can't move it to a separate component without CardBase refactoring. The component checks types of its children. However we can try to create a helper util... But I'm not sure that will be more readable or more convenient in future.

@DC-RomanKarpov DC-RomanKarpov force-pushed the feat-option-to-place-card-controls-in-footer branch from f074402 to 75c36fd Compare February 27, 2024 12:11
size="s"
colSizes={{all: 12, md: 12}}
/>
</IconWrapper>
</CardBase.Content>
{areControlsInFooter && (links || buttons) && (
Copy link
Collaborator

Choose a reason for hiding this comment

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

this code repeats 3 times in pr, could we create kinda component?

Copy link
Contributor Author

@DC-RomanKarpov DC-RomanKarpov Feb 28, 2024

Choose a reason for hiding this comment

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

As I wrote earlier, it's impossible to wrap CardBase.Footer in other components. Because the CardBase component uses its children's types within itself. Therefore I think that we should not update code here.

Wrote helper functions to implement the required changes

HTMLAttributeAnchorTarget,
PropsWithChildren,
ReactElement,
isValidElement,
Copy link
Collaborator

Choose a reason for hiding this comment

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

what is the purpose of isValidElement? didn't find any usage examples in pr

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please have a look at line 96. It used to handle children elements correctly.

<BlockBase>
<CardLayout
title="With controlPosition = footer"
description="Please note that the controlPosition prop manages the position of buttons and links only when paddingBottom = default."
Copy link
Collaborator

Choose a reason for hiding this comment

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

We don't store texts in .tsx story files, but keep them in data.json. In case we want to translate stories it would be a problem to pick all of the texts form code


return (
<CardBase
className={b()}
{...cardParams}
extraProps={{'aria-describedby': descriptionId, 'aria-labelledby': titleId}}
>
<CardBase.Content>
<CardBase.Content key="content">
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do we need to add a constant key?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is no necessity. Will remove.
In the process of development, before CardBase refactoring, it must be added to a child because I passed CardBase children as array of elements. Thanks for the notice.

@@ -135,3 +171,19 @@ WithUrl.args = {
WithContentList.args = {
...DefaultArgs,
} as BasicCardProps;

ControlPosition.argTypes = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

is it necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can omit controls' hiding, but I think that these controls are unnecessary.

@DC-RomanKarpov DC-RomanKarpov force-pushed the feat-option-to-place-card-controls-in-footer branch from ddcbe4c to 09dad73 Compare February 28, 2024 21:17
size?: ContentSize;
qa?: Record<string, string>;
};
const renderContentControls = (
Copy link
Collaborator

Choose a reason for hiding this comment

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

type ContentControlsProps = {
    links?: LinkProps[];
    buttons?: ButtonProps[];
    titleId?: string;
    size?: ContentSize;
    qa?: Record<string, string>;
   children: (children: React.ReactElement) => React.ReactElement;
};

export const ContentControls = (props: ContentControls) => {
 const {links, buttons, titleId, size = 's', qa = {}, children} = props;
  const {links: linksQa, link: linkQa, buttons: buttonsQa, button: buttonQa} = qa;

  return links || buttons
        ? children(
              <Fragment>
                  <Links
                      className={b('links', {size})}
                      size={size}
                      links={links}
                      titleId={titleId}
                      qa={linksQa}
                      linkQa={linkQa}
                  />
                  <Buttons
                      className={b('buttons', {size})}
                      size={size}
                      buttons={buttons}
                      titleId={titleId}
                      qa={buttonsQa}
                      buttonQa={buttonQa}
                  />
              </Fragment>,
          )
        : null;

}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The suggested code would be treated as a React Component. Thus it won't work within CardBase. Please, have a look at

colSizes={{all: 12, md: 12}}
/>
</CardBase.Content>
{footerControls}
Copy link
Collaborator

Choose a reason for hiding this comment

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

<ContentControls ...>
  {(children) => renderCardFooterControlsContainer(children)}
</ContentControls>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, this won't work within CardBase.

@DC-RomanKarpov DC-RomanKarpov merged commit 7e3dc0b into main Mar 1, 2024
3 checks passed
@DC-RomanKarpov DC-RomanKarpov deleted the feat-option-to-place-card-controls-in-footer branch March 1, 2024 08:34
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.

Add possibility to place card controls (links & buttons) in a card footer
3 participants