Skip to content

Commit

Permalink
feat: add icon prop to LayoutItem (#781)
Browse files Browse the repository at this point in the history
* feat: add icon prop to LayoutItem
  • Loading branch information
qradle-yndx authored Feb 1, 2024
1 parent 0521d42 commit 32bf165
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 70 deletions.
42 changes: 42 additions & 0 deletions src/components/IconWrapper/IconWrapper.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
@import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss';

$block: '.#{$ns}icon-wrapper';

#{$block} {
$iconSizePositionTop: 32px;
$iconSizePositionLeft: 22px;

display: flex;
flex-direction: column;

&_icon-position {
&_left {
flex-direction: row;
}
}

&__icon {
max-width: 100%;
margin-bottom: $indentXXS;
height: $iconSizePositionTop;
object-fit: contain;
display: block;

&_icon-position {
&_left {
height: $iconSizePositionLeft;
width: $iconSizePositionLeft;
margin: 1px $indentXXS 1px 0px;
}
}
}

&_content {
&_left {
@include add-specificity(&) {
flex: 1 0 0;
}
}
}
}
31 changes: 31 additions & 0 deletions src/components/IconWrapper/IconWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React, {Fragment, PropsWithChildren} from 'react';

import {IconWrapperProps} from '../../models';
import {block} from '../../utils';
import Image from '../Image/Image';
import {getMediaImage} from '../Media/Image/utils';

import './IconWrapper.scss';

const b = block('icon-wrapper');

const IconWrapper = (props: PropsWithChildren<IconWrapperProps>) => {
const {icon, children} = props;
if (!icon) {
return <Fragment>{children}</Fragment>;
}

const iconProps = getMediaImage(icon.value);
const iconPosition = icon?.position;

return (
<div className={b({['icon-position']: iconPosition})}>
{iconProps && (
<Image {...iconProps} className={b('icon', {['icon-position']: iconPosition})} />
)}
<div className={b({['content']: iconPosition})}>{children}</div>
</div>
);
};

export default IconWrapper;
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export {default as MetaInfo} from './MetaInfo/MetaInfo';
export {default as FullscreenMedia} from './FullscreenMedia/FullscreenMedia';
export {default as ContentList} from './ContentList/ContentList';
export {default as InnerForm} from './InnerForm/InnerForm';
export {default as IconWrapper} from './IconWrapper/IconWrapper';

export type {RouterLinkProps} from './RouterLink/RouterLink';
export type {ImageBaseProps} from './ImageBase/ImageBase';
12 changes: 11 additions & 1 deletion src/models/constructor-items/sub-blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ export enum IconPosition {
Left = 'left',
}

export interface PositionedIcon {
value: ImageProps;
position?: IconPosition;
}

export interface IconWrapperProps {
icon?: PositionedIcon;
}

export const SubBlockTypes = Object.values(SubBlockType);

export interface DividerProps {
Expand Down Expand Up @@ -162,10 +171,11 @@ export interface PriceCardProps extends CardBaseProps, Pick<ContentBlockProps, '

export interface LayoutItemProps extends ClassNameProps, AnalyticsEventsBase {
content: Omit<ContentBlockProps, 'colSizes' | 'centered' | 'size'>;
media: MediaProps;
media?: MediaProps;
metaInfo?: string[];
border?: boolean;
fullscreen?: boolean;
icon?: PositionedIcon;
}

// sub-block models
Expand Down
38 changes: 0 additions & 38 deletions src/sub-blocks/BasicCard/BasicCard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,45 +4,7 @@
$block: '.#{$ns}basic-card';

#{$block} {
$iconSizePositionTop: 32px;
$iconSizePositionLeft: 22px;

@include add-specificity(&) {
min-height: auto;
}

&__icon {
max-width: 100%;
margin-bottom: $indentXXS;
height: $iconSizePositionTop;
object-fit: contain;
display: block;

&_icon-position {
&_left {
height: $iconSizePositionLeft;
width: $iconSizePositionLeft;
margin: 1px $indentXXS 1px 0px;
}
}
}

&__content {
display: flex;
flex-direction: column;

&_icon-position {
&_left {
flex-direction: row;
}
}
}

&_content-layout {
&_left {
@include add-specificity(&) {
flex: 1 0 0;
}
}
}
}
19 changes: 5 additions & 14 deletions src/sub-blocks/BasicCard/BasicCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ import React from 'react';

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

import {Content} from '../';
import CardBase from '../../components/CardBase/CardBase';
import Image from '../../components/Image/Image';
import {getMediaImage} from '../../components/Media/Image/utils';
import IconWrapper from '../../components/IconWrapper/IconWrapper';
import {BasicCardProps} from '../../models';
import {IconPosition} from '../../models/constructor-items/sub-blocks';
import {block} from '../../utils';
import Content from '../Content/Content';

import './BasicCard.scss';

Expand All @@ -25,7 +24,6 @@ const BasicCard = (props: BasicCardProps) => {
iconPosition = IconPosition.Top,
...cardParams
} = props;
const iconProps = icon && getMediaImage(icon);
const titleId = useUniqId();
const descriptionId = useUniqId();

Expand All @@ -36,13 +34,7 @@ const BasicCard = (props: BasicCardProps) => {
extraProps={{'aria-describedby': descriptionId, 'aria-labelledby': titleId}}
>
<CardBase.Content>
<div className={b('content', {['icon-position']: iconPosition})}>
{iconProps && (
<Image
{...iconProps}
className={b('icon', {['icon-position']: iconPosition})}
/>
)}
<IconWrapper icon={icon ? {value: icon, position: iconPosition} : undefined}>
<Content
title={title}
titleId={titleId}
Expand All @@ -51,11 +43,10 @@ const BasicCard = (props: BasicCardProps) => {
additionalInfo={additionalInfo}
links={links}
buttons={buttons}
colSizes={{all: 12, md: 12}}
size="s"
className={b({['content-layout']: iconPosition})}
colSizes={{all: 12, md: 12}}
/>
</div>
</IconWrapper>
</CardBase.Content>
</CardBase>
);
Expand Down
4 changes: 4 additions & 0 deletions src/sub-blocks/LayoutItem/LayoutItem.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@ $block: '.#{$ns}layout-item';

&__content {
margin: $indentXS $indentXS 0 0;

&_no-media {
margin: 0;
}
}
}
46 changes: 29 additions & 17 deletions src/sub-blocks/LayoutItem/LayoutItem.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from 'react';

import {Content} from '..';
import {FullscreenMedia, Media, MetaInfo} from '../../components';
import {LayoutItemProps} from '../../models';
import {FullscreenMedia, IconWrapper, Media, MetaInfo} from '../../components';
import {ContentBlockProps, LayoutItemProps} from '../../models';
import {block} from '../../utils';
import Content from '../Content/Content';

import {getLayoutItemLinks, hasFullscreen, showFullscreenIcon} from './utils';

Expand All @@ -17,11 +17,21 @@ const LayoutItem = ({
media,
border,
fullscreen,
icon,
className,
analyticsEvents,
}: LayoutItemProps) => (
<div className={b(null, className)}>
{fullscreen && hasFullscreen(media) ? (
}: LayoutItemProps) => {
const contentProps: ContentBlockProps = {
...content,
links: getLayoutItemLinks(links),
size: 's',
colSizes: {all: 12, md: 12},
};
const renderMedia = () => {
if (!media) {
return null;
}
return fullscreen && hasFullscreen(media) ? (
<FullscreenMedia showFullscreenIcon={showFullscreenIcon(media)}>
{({
className: mediaClassName,
Expand All @@ -38,17 +48,19 @@ const LayoutItem = ({
</FullscreenMedia>
) : (
<Media {...media} className={b('media', {border})} analyticsEvents={analyticsEvents} />
)}
{metaInfo && <MetaInfo items={metaInfo} className={b('meta-info')} />}
<div className={b('content')}>
<Content
{...content}
links={getLayoutItemLinks(links)}
size="s"
colSizes={{all: 12, md: 12}}
/>
);
};
return (
<div className={b(null, className)}>
{renderMedia()}
{metaInfo && <MetaInfo items={metaInfo} className={b('meta-info')} />}
<div className={b('content', {'no-media': !media})}>
<IconWrapper icon={icon}>
<Content {...contentProps} />
</IconWrapper>
</div>
</div>
</div>
);
);
};

export default LayoutItem;
19 changes: 19 additions & 0 deletions src/sub-blocks/LayoutItem/__stories__/LayoutItem.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,24 @@ const DefaultTemplate: StoryFn<LayoutItemProps> = (args) => (
</div>
);

const WithIconTemplate: StoryFn<LayoutItemProps> = (args) => (
<div>
<div style={{marginBottom: '100px'}}>
<h1>Icon: Top</h1>
<DefaultTemplate {...args} />
</div>
<div>
<h1>Icon: Left</h1>
<DefaultTemplate {...args} icon={data.withIcon.iconLeft as LayoutItemProps['icon']} />
</div>
</div>
);

export const Default = DefaultTemplate.bind({});
export const Fullscreen = DefaultTemplate.bind({});
export const MetaInfo = DefaultTemplate.bind({});
export const Youtube = DefaultTemplate.bind({});
export const WithIcon = WithIconTemplate.bind({});

const DefaultArgs = {
...data.default.content,
Expand All @@ -40,3 +54,8 @@ MetaInfo.args = {
metaInfo: data.metaInfo.content.metaInfo.map((item) => yfmTransform(item)),
} as LayoutItemProps;
Youtube.args = {...DefaultArgs, ...data.youtube.content} as LayoutItemProps;
WithIcon.args = {
...DefaultArgs,
media: undefined,
icon: data.withIcon.iconTop as LayoutItemProps['icon'],
};
10 changes: 10 additions & 0 deletions src/sub-blocks/LayoutItem/__stories__/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,15 @@
"image": "/story-assets/img-mini_4-12_light.png"
}
}
},
"withIcon": {
"iconTop": {
"value": "/story-assets/icon_1_light.svg",
"position": "top"
},
"iconLeft": {
"value": "/story-assets/icon_2_light.svg",
"position": "left"
}
}
}

0 comments on commit 32bf165

Please sign in to comment.