Skip to content

Commit

Permalink
feat: add image card sub-block (#807)
Browse files Browse the repository at this point in the history
* feat: add image card sub-block
  • Loading branch information
qradle-yndx authored Feb 14, 2024
1 parent cd0ee7d commit 52890dd
Show file tree
Hide file tree
Showing 16 changed files with 370 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .storybook/stories/documentation/Sub Blocks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ _Cards are components that are only used together with the slider or layout:_
## [Price Detailed(deprecated)](?path=/story/components-cards-pricedetailed--marked-list&viewMode=docs)

## [Divider](?path=/story/components-divider--docs&viewMode=docs)

## [ImageCard](?path=/story/components-cards-imagecard--docs&viewMode=docs)
1 change: 1 addition & 0 deletions src/blocks/CardLayout/__stories__/CardLayout.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ The following blocks are currently supported:
- [`BackgroundCard` — Background card](?path=/story/components-cards-backgroundcard--default&viewMode=docs)
- [`PriceCard` — Price card](?path=/story/components-cards-pricecard--default&viewMode=docs)
- [`LayoutItem` — Component part of `Layout` component, consists with `Media` and `Content`](?path=/story/components-cards-layoutitem--default&viewMode=docs)
- [`ImageCard` — Image card](?path=/story/components-cards-imagecard--default&viewMode=docs)
</StoryTemplate>
5 changes: 5 additions & 0 deletions src/blocks/CardLayout/__stories__/CardLayout.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ const DefaultTemplate: StoryFn<CardLayoutBlockModel> = (args) => (
},
],
},
{
...args,
title: 'Card layout with image cards',
children: createCardArray(3, data.cards.imageCard),
},
],
}}
/>
Expand Down
6 changes: 6 additions & 0 deletions src/blocks/CardLayout/__stories__/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@
"Ut enim ad minim veniam exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.",
"Ut enim ad minim veniam exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
]
},
"imageCard": {
"type": "image-card",
"title": "Tell a story and build a narrative",
"text": "We are all storytellers. Stories are a powerful way to communicate ideas and share information. The right story can lead to a better understanding of a situation, make us laugh, or even inspire us to do something in the future.",
"image": "/story-assets/img_8-12_light.png"
}
},
"buttons": {
Expand Down
2 changes: 2 additions & 0 deletions src/constructor-items.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
BasicCard,
Content,
Divider,
ImageCard,
LayoutItem,
MediaCard,
PriceCard,
Expand Down Expand Up @@ -73,6 +74,7 @@ export const subBlockMap = {
[SubBlockType.Content]: Content,
[SubBlockType.Quote]: Quote,
[SubBlockType.PriceCard]: PriceCard,
[SubBlockType.ImageCard]: ImageCard,
};

export const navItemMap = {
Expand Down
1 change: 1 addition & 0 deletions src/models/constructor-items/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export type ContentSize = 's' | 'l';
export type ContentTextSize = 's' | 'm' | 'l';
export type ContentTheme = 'default' | 'dark' | 'light';
export type FileLinkType = 'vertical' | 'horizontal';
export type ImageCardMargins = 's' | 'm';

// modifiers
export interface Themable {
Expand Down
22 changes: 21 additions & 1 deletion src/models/constructor-items/sub-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
CardBaseProps,
ContentTheme,
DividerSize,
ImageCardMargins,
ImageObjectProps,
ImageProps,
LinkProps,
Expand Down Expand Up @@ -41,6 +42,7 @@ export enum SubBlockType {
*/
Card = 'card',
PriceCard = 'price-card',
ImageCard = 'image-card',
}

export enum IconPosition {
Expand All @@ -57,6 +59,11 @@ export interface IconWrapperProps {
icon?: PositionedIcon;
}

export enum ImageCardDirection {
Direct = 'direct',
Reverse = 'reverse',
}

export const SubBlockTypes = Object.values(SubBlockType);

export interface DividerProps {
Expand Down Expand Up @@ -180,6 +187,14 @@ export interface LayoutItemProps extends ClassNameProps, AnalyticsEventsBase {
icon?: PositionedIcon;
}

export interface ImageCardProps extends CardBaseProps, Pick<ContentBlockProps, 'title' | 'text'> {
image: ImageProps;
enableImageBorderRadius?: boolean;
margins?: ImageCardMargins;
direction?: ImageCardDirection;
backgroundColor?: string;
}

// sub-block models
export type DividerModel = {
type: SubBlockType.Divider;
Expand Down Expand Up @@ -221,6 +236,10 @@ export type PriceCardModel = {
type: SubBlockType.PriceCard;
} & PriceCardProps;

export type ImageCardModel = {
type: SubBlockType.ImageCard;
} & ImageCardProps;

export type SubBlockModels =
| DividerModel
| QuoteModel
Expand All @@ -231,6 +250,7 @@ export type SubBlockModels =
| BannerCardModel
| BasicCardModel
| PriceCardModel
| LayoutItemModel;
| LayoutItemModel
| ImageCardModel;

export type SubBlock = SubBlockModels;
3 changes: 3 additions & 0 deletions src/schema/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
BackgroundCard,
BasicCard,
Divider,
ImageCard,
MediaCardBlock,
PriceCardBlock,
PriceDetailedBlock,
Expand Down Expand Up @@ -63,6 +64,7 @@ export const cardSchemas = {
...Quote,
...BasicCard,
...PriceCardBlock,
...ImageCard,
};

export const constructorBlockSchemaNames = [
Expand Down Expand Up @@ -102,4 +104,5 @@ export const constructorCardSchemaNames = [
'basic-card',
'layout-item',
'price-card',
'image-card',
];
1 change: 1 addition & 0 deletions src/schema/validators/sub-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from '../../sub-blocks/Divider/schema';
export * from '../../sub-blocks/BasicCard/schema';
export * from '../../sub-blocks/PriceCard/schema';
export * from '../../sub-blocks/HubspotForm/schema';
export * from '../../sub-blocks/ImageCard/schema';
71 changes: 71 additions & 0 deletions src/sub-blocks/ImageCard/ImageCard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
@import '../../../styles/variables.scss';
@import '../../../styles/mixins';

$block: '.#{$ns}image-card';

#{$block} {
@include card();
min-height: 1px;
$image: #{&}__image;
$content: #{&}__content;

#{$content} {
padding: $indentM;
}

#{$image} {
&_inner {
width: 100%;
display: block;

&_radius {
border-radius: $borderRadius;
}
}

&_margins {
&_s {
padding: 4px;

#{$image}_inner {
border-radius: calc(#{$borderRadius} - #{$imagePadding});
}
}

&_m {
padding: $indentM;

#{$image}_inner {
border-radius: initial;
}
}
}
}

&_with-content {
display: flex;
flex-direction: column;

&#{$block}_direction_direct {
#{$image} {
padding-bottom: 0;
}

#{$content} {
padding-top: $indentSM;
}
}

&#{$block}_direction_reverse {
flex-direction: column-reverse;

#{$image} {
padding-top: 0;
}

#{$content} {
padding-bottom: $indentSM;
}
}
}
}
48 changes: 48 additions & 0 deletions src/sub-blocks/ImageCard/ImageCard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';

import {Image} from '../../components';
import {getMediaImage} from '../../components/Media/Image/utils';
import {ImageCardDirection, ImageCardProps} from '../../models';
import {block} from '../../utils';
import Content from '../Content/Content';

import './ImageCard.scss';

const b = block('image-card');

const ImageCard = (props: ImageCardProps) => {
const {
border = 'shadow',
title,
text,
image,
enableImageBorderRadius = false,
direction = ImageCardDirection.Direct,
margins,
backgroundColor,
} = props;

const hasContent = Boolean(text || title);
const imageProps = getMediaImage(image);

return (
<div
className={b({border, 'with-content': hasContent, direction})}
style={{backgroundColor}}
>
<div className={b('image', {margins})}>
<Image
className={b('image_inner', {radius: enableImageBorderRadius})}
{...imageProps}
/>
</div>
{hasContent && (
<div className={b('content')}>
<Content title={title} text={text} colSizes={{all: 12, md: 12}} size="s" />
</div>
)}
</div>
);
};

export default ImageCard;
28 changes: 28 additions & 0 deletions src/sub-blocks/ImageCard/__stories__/ImageCard.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {Meta} from '@storybook/blocks';

import {StoryTemplate} from '../../../demo/StoryTemplate.mdx';
import * as ImageCardStories from './ImageCard.stories.tsx';

<Meta of={ImageCardStories} />
<StoryTemplate>
## Parameters

`type: "image-card"`

[`image: string | ImageObjectProps | ReactNode` — ImageProps](?path=/docs/documentation-types--docs#imageobjectprops---image-property).

`title?: Title | string` — Card title.

`text?: string` — Card description (with YFM support).

`border: 'shadow' | 'line' | 'none'` — Select border of the card.

`backgroundColor?: string` — Card background color.

`margins?: 's' | 'm'` — Space between the image and the card borders.

`direction?: 'direct' | 'reverse'` — Image and Content direction.

`enableImageBorderRadius?: boolean` — Set border-radius for the image. Affects only when `margins='none'`.

</StoryTemplate>
Loading

0 comments on commit 52890dd

Please sign in to comment.