diff --git a/src/sub-blocks/BackgroundCard/BackgroundCard.scss b/src/sub-blocks/BackgroundCard/BackgroundCard.scss index 6f45ee0c9..62862fab5 100644 --- a/src/sub-blocks/BackgroundCard/BackgroundCard.scss +++ b/src/sub-blocks/BackgroundCard/BackgroundCard.scss @@ -55,14 +55,6 @@ $block: '.#{$ns}background-card'; object-position: left; } } - - &__footer { - margin-top: 0px; - } - &__links, - &__buttons { - margin-top: $indentXS; - } } a#{$block} { diff --git a/src/sub-blocks/BackgroundCard/BackgroundCard.tsx b/src/sub-blocks/BackgroundCard/BackgroundCard.tsx index d22416631..66dc63467 100644 --- a/src/sub-blocks/BackgroundCard/BackgroundCard.tsx +++ b/src/sub-blocks/BackgroundCard/BackgroundCard.tsx @@ -1,12 +1,14 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import {useUniqId} from '@gravity-ui/uikit'; -import {BackgroundImage, Buttons, CardBase, Links} from '../../components/'; +import {BackgroundImage, CardBase} from '../../components/'; import {useTheme} from '../../context/theme'; import {BackgroundCardProps} from '../../models'; import {block, getThemedValue} from '../../utils'; +import renderContentControls from '../../utils/renderContentControls/renderContentControls'; import Content from '../Content/Content'; +import renderCardFooterControlsContainer from '../renderCardFooterControlsContainer/renderCardFooterControlsContainer'; import './BackgroundCard.scss'; @@ -37,6 +39,20 @@ const BackgroundCard = (props: BackgroundCardProps) => { const borderType = hasBackgroundColor ? 'none' : border; const areControlsInFooter = !paddingBottom && controlPosition === 'footer'; + const footerControls = useMemo( + () => + renderContentControls( + { + links: areControlsInFooter ? links : undefined, + buttons: areControlsInFooter ? buttons : undefined, + size: 's', + titleId, + }, + renderCardFooterControlsContainer, + ), + [areControlsInFooter, links, buttons, titleId], + ); + return ( { analyticsEvents={analyticsEvents} urlTitle={urlTitle} > - + { colSizes={{all: 12, md: 12}} /> - {areControlsInFooter && (links || buttons) && ( - - - - - )} + {footerControls} ); }; diff --git a/src/sub-blocks/BackgroundCard/__stories__/BackgroundCard.stories.tsx b/src/sub-blocks/BackgroundCard/__stories__/BackgroundCard.stories.tsx index bfd32e0e3..282638255 100644 --- a/src/sub-blocks/BackgroundCard/__stories__/BackgroundCard.stories.tsx +++ b/src/sub-blocks/BackgroundCard/__stories__/BackgroundCard.stories.tsx @@ -107,7 +107,7 @@ const ControlPositionTemplate: StoryFn = (args) => ( - + {data.cardLayout.items.map((item, index) => ( = (args) => ( {data.cardLayout.items.map((item, index) => ( diff --git a/src/sub-blocks/BackgroundCard/__stories__/data.json b/src/sub-blocks/BackgroundCard/__stories__/data.json index cb1224255..ec729e6a1 100644 --- a/src/sub-blocks/BackgroundCard/__stories__/data.json +++ b/src/sub-blocks/BackgroundCard/__stories__/data.json @@ -119,6 +119,9 @@ ] }, "cardLayout": { + "contentTitle": "With controlPosition = content", + "footerTitle": "With controlPosition = footer", + "footerDescription": "Please note that the controlPosition prop manages the position of buttons and links only when paddingBottom = default.", "items": [ { "title": "Lorem ipsumt", diff --git a/src/sub-blocks/BasicCard/BasicCard.scss b/src/sub-blocks/BasicCard/BasicCard.scss index 80367eb71..70f51003d 100644 --- a/src/sub-blocks/BasicCard/BasicCard.scss +++ b/src/sub-blocks/BasicCard/BasicCard.scss @@ -7,12 +7,4 @@ $block: '.#{$ns}basic-card'; @include add-specificity(&) { min-height: auto; } - - &__footer { - margin-top: 0px; - } - &__links, - &__buttons { - margin-top: $indentXS; - } } diff --git a/src/sub-blocks/BasicCard/BasicCard.tsx b/src/sub-blocks/BasicCard/BasicCard.tsx index 2507386ac..342adbcdd 100644 --- a/src/sub-blocks/BasicCard/BasicCard.tsx +++ b/src/sub-blocks/BasicCard/BasicCard.tsx @@ -1,12 +1,14 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import {useUniqId} from '@gravity-ui/uikit'; -import {Buttons, CardBase, IconWrapper, Links} from '../../components'; +import {CardBase, IconWrapper} from '../../components'; import {BasicCardProps} from '../../models'; import {IconPosition} from '../../models/constructor-items/sub-blocks'; import {block} from '../../utils'; +import renderContentControls from '../../utils/renderContentControls/renderContentControls'; import Content from '../Content/Content'; +import renderCardFooterControlsContainer from '../renderCardFooterControlsContainer/renderCardFooterControlsContainer'; import './BasicCard.scss'; @@ -28,6 +30,19 @@ const BasicCard = (props: BasicCardProps) => { const titleId = useUniqId(); const descriptionId = useUniqId(); const areControlsInFooter = controlPosition === 'footer'; + const footerControls = useMemo( + () => + renderContentControls( + { + links: areControlsInFooter ? links : undefined, + buttons: areControlsInFooter ? buttons : undefined, + size: 's', + titleId, + }, + renderCardFooterControlsContainer, + ), + [areControlsInFooter, links, buttons, titleId], + ); return ( { {...cardParams} extraProps={{'aria-describedby': descriptionId, 'aria-labelledby': titleId}} > - + { /> - {areControlsInFooter && (links || buttons) && ( - - - - - )} + {footerControls} ); }; diff --git a/src/sub-blocks/BasicCard/__stories__/BasicCard.stories.tsx b/src/sub-blocks/BasicCard/__stories__/BasicCard.stories.tsx index 623ef97b7..a384f52af 100644 --- a/src/sub-blocks/BasicCard/__stories__/BasicCard.stories.tsx +++ b/src/sub-blocks/BasicCard/__stories__/BasicCard.stories.tsx @@ -118,7 +118,7 @@ const ControlPositionTemplate: StoryFn = (args) => ( - + {data.cardLayout.items.map((item, index) => ( = (args) => ( - + {data.cardLayout.items.map((item, index) => ( { const defaultTitleId = useUniqId(); const titleId = titleIdFromProps || defaultTitleId; + const controls = useMemo( + () => + renderContentControls({ + size, + links, + buttons, + titleId, + qa: qaAttributes, + }), + [size, links, buttons, titleId, qa], + ); + return ( { /> )} - - + {controls} ); }; diff --git a/src/sub-blocks/LayoutItem/LayoutItem.scss b/src/sub-blocks/LayoutItem/LayoutItem.scss index 222a7d5c6..8370360b3 100644 --- a/src/sub-blocks/LayoutItem/LayoutItem.scss +++ b/src/sub-blocks/LayoutItem/LayoutItem.scss @@ -30,9 +30,4 @@ $block: '.#{$ns}layout-item'; margin: 0; } } - - &__links, - &__buttons { - margin-top: $indentXS; - } } diff --git a/src/sub-blocks/LayoutItem/LayoutItem.tsx b/src/sub-blocks/LayoutItem/LayoutItem.tsx index d279e45c9..f26b054e5 100644 --- a/src/sub-blocks/LayoutItem/LayoutItem.tsx +++ b/src/sub-blocks/LayoutItem/LayoutItem.tsx @@ -1,10 +1,11 @@ -import React, {Fragment, useMemo} from 'react'; +import React, {useMemo} from 'react'; import {useUniqId} from '@gravity-ui/uikit'; -import {Buttons, FullscreenMedia, IconWrapper, Links, Media, MetaInfo} from '../../components'; +import {FullscreenMedia, IconWrapper, Media, MetaInfo} from '../../components'; import {ContentBlockProps, LayoutItemProps} from '../../models'; import {block} from '../../utils'; +import renderContentControls from '../../utils/renderContentControls/renderContentControls'; import Content from '../Content/Content'; import {getLayoutItemLinks, hasFullscreen, showFullscreenIcon} from './utils'; @@ -34,7 +35,16 @@ const LayoutItem = ({ colSizes: {all: 12, md: 12}, }; const titleId = useUniqId(); - + const footerControls = useMemo( + () => + renderContentControls({ + links: areControlsInFooter ? links : undefined, + buttons: areControlsInFooter ? buttons : undefined, + size: 's', + titleId, + }), + [areControlsInFooter, links, buttons, titleId], + ); const renderMedia = () => { if (!media) { return null; @@ -67,22 +77,7 @@ const LayoutItem = ({ - {areControlsInFooter && (links || buttons) && ( - - - - - )} + {footerControls} ); }; diff --git a/src/sub-blocks/LayoutItem/__stories__/LayoutItem.stories.tsx b/src/sub-blocks/LayoutItem/__stories__/LayoutItem.stories.tsx index 006be6512..716a4dfc9 100644 --- a/src/sub-blocks/LayoutItem/__stories__/LayoutItem.stories.tsx +++ b/src/sub-blocks/LayoutItem/__stories__/LayoutItem.stories.tsx @@ -40,7 +40,7 @@ const ControlPositionTemplate: StoryFn = (args) => ( - + {data.cardLayout.items.map((item, index) => ( = (args) => ( - + {data.cardLayout.items.map((item, index) => ( ( + {children} +); + +export default renderCardFooterControlsContainer; diff --git a/src/utils/renderContentControls/ContentControls.scss b/src/utils/renderContentControls/ContentControls.scss new file mode 100644 index 000000000..299cd924d --- /dev/null +++ b/src/utils/renderContentControls/ContentControls.scss @@ -0,0 +1,17 @@ +@import '../../../styles/variables.scss'; + +$block: '.#{$ns}content-controls'; + +#{$block} { + &__links, + &__buttons { + &_size { + &_s { + margin-top: $indentXS; + } + &_l { + margin-top: $indentSM; + } + } + } +} diff --git a/src/utils/renderContentControls/renderContentControls.tsx b/src/utils/renderContentControls/renderContentControls.tsx new file mode 100644 index 000000000..860aa3a6c --- /dev/null +++ b/src/utils/renderContentControls/renderContentControls.tsx @@ -0,0 +1,48 @@ +import React, {Fragment} from 'react'; + +import {Buttons, Links} from '../../components'; +import {ButtonProps, ContentSize, LinkProps} from '../../models'; +import {block} from '../../utils'; + +import './ContentControls.scss'; + +const b = block('content-controls'); + +type ContentControlsArgs = { + links?: LinkProps[]; + buttons?: ButtonProps[]; + titleId?: string; + size?: ContentSize; + qa?: Record; +}; +const renderContentControls = ( + {links, buttons, titleId, size = 's', qa = {}}: ContentControlsArgs, + renderContainer: (children: React.ReactElement) => React.ReactElement = (children) => children, +) => { + const {links: linksQa, link: linkQa, buttons: buttonsQa, button: buttonQa} = qa; + + return links || buttons + ? renderContainer( + + + + , + ) + : null; +}; + +export default renderContentControls;