Skip to content

Commit

Permalink
feat: ImageCard extension (#876) (#909)
Browse files Browse the repository at this point in the history
* feat: ImageCard extension

* feat: ImageCard extension
  • Loading branch information
Lakate authored Apr 5, 2024
1 parent 2633fb8 commit 4dcf70a
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 20 deletions.
8 changes: 7 additions & 1 deletion src/models/constructor-items/sub-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,18 @@ export interface LayoutItemProps extends ClassNameProps, CardLayoutProps, Analyt
icon?: PositionedIcon;
}

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

// sub-block models
Expand Down
57 changes: 50 additions & 7 deletions src/sub-blocks/ImageCard/ImageCard.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';

import {Link, useUniqId} from '@gravity-ui/uikit';

import {Image} from '../../components';
import {getMediaImage} from '../../components/Media/Image/utils';
import {ImageCardDirection, ImageCardProps} from '../../models';
Expand All @@ -20,16 +22,23 @@ const ImageCard = (props: ImageCardProps) => {
direction = ImageCardDirection.Direct,
margins,
backgroundColor,
url,
target,
urlTitle,
additionalInfo,
links,
buttons,
list,
theme: cardTheme = 'default',
size = 's',
} = props;

const hasContent = Boolean(text || title);
const hasContent = Boolean(text || title || buttons || links || list);
const imageProps = getMediaImage(image);
const titleId = useUniqId();

return (
<div
className={b({border, 'with-content': hasContent, direction})}
style={{backgroundColor}}
>
const cardContent = (
<React.Fragment>
<div className={b('image', {margins})}>
<Image
className={b('image_inner', {radius: enableImageBorderRadius})}
Expand All @@ -38,9 +47,43 @@ const ImageCard = (props: ImageCardProps) => {
</div>
{hasContent && (
<div className={b('content')}>
<Content title={title} text={text} colSizes={{all: 12, md: 12}} size="s" />
<Content
titleId={titleId}
title={title}
text={text}
links={links}
buttons={buttons}
list={list}
theme={cardTheme}
additionalInfo={additionalInfo}
size={size}
colSizes={{all: 12, md: 12}}
/>
</div>
)}
</React.Fragment>
);

return url ? (
<Link
href={url}
target={target}
rel={target === '_blank' ? 'noopener noreferrer' : undefined}
className={b({border, 'with-content': hasContent, direction})}
title={urlTitle}
extraProps={{
draggable: false,
onDragStart: (e: React.DragEvent<HTMLAnchorElement>) => e.preventDefault(),
}}
>
{cardContent}
</Link>
) : (
<div
className={b({border, 'with-content': hasContent, direction})}
style={{backgroundColor}}
>
{cardContent}
</div>
);
};
Expand Down
10 changes: 10 additions & 0 deletions src/sub-blocks/ImageCard/__stories__/ImageCard.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,14 @@ import * as ImageCardStories from './ImageCard.stories.tsx';

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

`url?: string` — URL that opens when clicking the card

`additionalInfo?: string` — Gray text (with YFM support)

`links?: Link[]` — An array with link objects (see [Content blocks](?path=/docs/documentation-types--docs))

`buttons?: Button[]` — An array with button objects (see [Content blocks](?path=/docs/documentation-types--docs))

`list?: ContentItemProps[]` - An Array of items with icon - [ContentList](?path=/story/components-contentlist--docs&viewMode=docs)

</StoryTemplate>
41 changes: 31 additions & 10 deletions src/sub-blocks/ImageCard/__stories__/ImageCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import React from 'react';

import {Meta, StoryFn} from '@storybook/react';

import {ImageCardProps} from '../../../models';
import {yfmTransform} from '../../../../.storybook/utils';
import {ButtonProps, ContentItemProps, ImageCardProps, LinkProps} from '../../../models';
import ImageCard from '../ImageCard';

import data from './data.json';
Expand Down Expand Up @@ -42,6 +43,13 @@ const MultipleTemplate: StoryFn<ImageCardProps> = (args) => (
</div>
);

const transformedContentList = data.content.list.map((item) => {
return {
...item,
text: item?.text && yfmTransform(item.text),
};
}) as ContentItemProps[];

const ContentTemplate: StoryFn<ImageCardProps> = (args) => (
<div
style={{display: 'flex', flexWrap: 'wrap', flexDirection: 'row', alignItems: 'flex-start'}}
Expand All @@ -55,14 +63,27 @@ const ContentTemplate: StoryFn<ImageCardProps> = (args) => (
<div style={{width: 400, margin: 20}}>
<ImageCard {...args} text="" title="" />
</div>
</div>
);

const MultipleContentTemplate: StoryFn<ImageCardProps> = (args) => (
<div>
<ContentTemplate {...args} {...(data.margins.none as Partial<ImageCardProps>)} />
<ContentTemplate {...args} {...(data.margins.small as Partial<ImageCardProps>)} />
<ContentTemplate {...args} {...(data.margins.medium as Partial<ImageCardProps>)} />
<div style={{width: 400, margin: 20}}>
<ImageCard
{...args}
title="With buttons"
buttons={data.content.buttons as ButtonProps[]}
/>
</div>
<div style={{width: 400, margin: 20}}>
<ImageCard {...args} title="With links" links={data.content.links as LinkProps[]} />
</div>
<div style={{width: 400, margin: 20}}>
<ImageCard
{...args}
title="With url and list"
url={data.content.url}
list={transformedContentList}
/>
</div>
<div style={{width: 400, margin: 20}}>
<ImageCard {...args} text="" title="" size="l" list={transformedContentList} />
</div>
</div>
);

Expand Down Expand Up @@ -92,7 +113,7 @@ const BorderRadiusTemplate: StoryFn<ImageCardProps> = (args) => (
export const Default = DefaultTemplate.bind({});
export const Margins = MultipleTemplate.bind({});
export const DirectionReverse = MultipleTemplate.bind({});
export const Content = MultipleContentTemplate.bind({});
export const Content = ContentTemplate.bind({});
export const BackgroundColor = MultipleTemplate.bind({});
export const Border = BorderTemplate.bind({});
export const BorderRadius = BorderRadiusTemplate.bind({});
Expand Down
50 changes: 50 additions & 0 deletions src/sub-blocks/ImageCard/__stories__/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,55 @@
"content": {
"backgroundColor": "#ccf0d2"
}
},
"content": {
"url": "https://example.com",
"links": [
{
"url": "#",
"text": "Link",
"theme": "normal",
"arrow": true
}
],
"buttons": [
{
"text": "Button\r",
"theme": "action",
"url": "https://example.com"
},
{
"text": "Button",
"theme": "outlined",
"url": "#"
}
],
"list": [
{
"icon": {
"light": "/story-assets/icon_1_light.svg",
"dark": "/story-assets/icon_1_dark.svg"
},
"title": "Lorem ipsum",
"text": "**Ut enim ad minim veniam** [quis nostrud](https://example.com) exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor"
},
{
"icon": {
"light": "/story-assets/icon_3_light.svg",
"dark": "/story-assets/icon_3_dark.svg"
},
"title": "Lorem ipsum ipsum",
"text": "**Ut enim ad minim veniam** [quis nostrud](https://example.com) exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor"
},
{
"icon": {
"light": "/story-assets/icon_2_light.svg",
"dark": "/story-assets/icon_2_dark.svg"
},
"title": "Lorem ipsum",
"text": "**Ut enim ad minim veniam** [quis nostrud](https://example.com) exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor"
}
],
"additionalInfo": "Duis aute irure dolor in [reprehenderit](https://example.com) n voluptate velit esse cillum dolore eu fugiat nulla pariatur."
}
}
10 changes: 8 additions & 2 deletions src/sub-blocks/ImageCard/schema.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import pick from 'lodash/pick';
import omit from 'lodash/omit';

import {BaseProps, CardBase} from '../../schema/validators/common';
import {ImageProps} from '../../schema/validators/components';
import {ContentBase} from '../Content/schema';

const ImageCardBlockContentProps = pick(ContentBase, ['title', 'text']);
const ImageCardBlockContentProps = omit(ContentBase, ['centered', 'colSizes']);

export const ImageCard = {
'image-card': {
Expand All @@ -26,6 +26,12 @@ export const ImageCard = {
backgroundColor: {
type: 'string',
},
url: {
type: 'string',
},
urlTitle: {
type: 'string',
},
},
},
};

0 comments on commit 4dcf70a

Please sign in to comment.