Skip to content

feat: use gravity icons #1232

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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@gravity-ui/page-constructor",
"version": "6.9.0",
"version": "7.4.0",
"description": "Gravity UI Page Constructor",
"license": "MIT",
"type": "commonjs",
Expand Down
8 changes: 6 additions & 2 deletions src/components/ContentList/ContentList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import YFMWrapper from '../YFMWrapper/YFMWrapper';
import ItemIcon from './ContentListItemIcon';

import './ContentList.scss';
import Icon from '../Icon/Icon';

const b = block('content-list');

Expand All @@ -30,10 +31,13 @@ const ContentList = ({list, size = 'l', qa, theme}: ContentListProps & QAProps)
return (
<div className={b({size, theme})} data-qa={qa}>
{list?.map((item) => {
const {icon, title, text} = item;
const {icon, title, text, gravityIcon} = item;
return (
<div className={b('item', {'without-title': !title})} key={uuidv4()}>
<ItemIcon icon={icon} className={b('icon')} qa={qaAttributes.image} />
{icon && (
<ItemIcon icon={icon} className={b('icon')} qa={qaAttributes.image} />
)}
{gravityIcon && <Icon className={b('icon')} icon={gravityIcon} />}
<div>
{title &&
React.createElement(
Expand Down
22 changes: 22 additions & 0 deletions src/components/Icon/Icon.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@import '../../../styles/variables.scss';
@import '../../../styles/mixins.scss';

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

#{$block} {
&_color {
&_brand {
/* stylelint-disable-next-line declaration-no-important */
color: var(--g-color-base-brand) !important;

& * {
/* stylelint-disable-next-line declaration-no-important */
color: var(--g-color-base-brand) !important;
}
}

&_text-color {
// as in nearest text
}
}
}
35 changes: 35 additions & 0 deletions src/components/Icon/Icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {ThemeSupporting, block, getThemedValue} from '../../utils';
import * as icons from '@gravity-ui/icons';
import {Icon as UiKitIcon} from '@gravity-ui/uikit';
import {useTheme} from '../../context/theme';
import './Icon.scss';
import {GravityIconProps} from '../../models';

const b = block('icon');

type Props = {
icon: ThemeSupporting<GravityIconProps>;
className?: string;
};

const Icon = ({icon, className}: Props) => {
const theme = useTheme();

if (!icon) {
return null;
}

const themedIcon = getThemedValue(icon, theme);
const data = (
typeof themedIcon === 'string' ? themedIcon : themedIcon.name
) as keyof typeof icons;
const color = typeof themedIcon === 'string' ? 'brand' : themedIcon.color;

return (
<div className={b({color}, className)}>
<UiKitIcon data={icons[data]} />
</div>
);
};

export default Icon;
17 changes: 12 additions & 5 deletions src/components/IconWrapper/IconWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,22 @@ import * as React from 'react';

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

import Icon from '../Icon/Icon';
import './IconWrapper.scss';
import {getMediaImage} from '../Media/Image/utils';
import Image from '../Image/Image';

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

const IconWrapper = (props: React.PropsWithChildren<IconWrapperProps> & ClassNameProps) => {
const {icon, children, className} = props;
if (!icon) {
const {icon, children, className, gravityIcon} = props;
if (!icon && !gravityIcon) {
return <React.Fragment>{children}</React.Fragment>;
}

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

return (
<div className={b({['icon-position']: iconPosition}, className)}>
Expand All @@ -27,6 +28,12 @@ const IconWrapper = (props: React.PropsWithChildren<IconWrapperProps> & ClassNam
className={b('icon', {['icon-position']: iconPosition})}
/>
)}
{gravityIcon?.value && (
<Icon
icon={gravityIcon?.value}
className={b('icon', {['icon-position']: iconPosition})}
/>
)}
<div className={b('content', {['icon-position']: iconPosition})}>{children}</div>
</div>
);
Expand Down
4 changes: 3 additions & 1 deletion src/models/constructor-items/blocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
ContentTextSize,
ContentTheme,
FileLinkProps,
GravityIconProps,
HeaderBreadCrumbsProps,
HeaderImageSize,
HeaderOffset,
Expand Down Expand Up @@ -405,7 +406,8 @@ export type SVGIcon = React.FC<React.SVGProps<SVGSVGElement>>;
export interface ContentItemProps {
title?: string;
text?: string;
icon: ThemeSupporting<ImageProps | SVGIcon>;
icon?: ThemeSupporting<ImageProps | SVGIcon>;
gravityIcon?: ThemeSupporting<GravityIconProps>;
}

export interface ContentListProps {
Expand Down
2 changes: 2 additions & 0 deletions src/models/constructor-items/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {ButtonView, ButtonProps as UikitButtonProps} from '@gravity-ui/uikit';

import {ThemeSupporting} from '../../utils';
import {AnalyticsEventsBase, AnalyticsEventsProp, ClassNameProps, QAProps} from '../common';
import * as icons from '@gravity-ui/icons';

// enums
export enum AuthorType {
Expand Down Expand Up @@ -151,6 +152,7 @@ export interface ImageDeviceProps extends ImageInfoProps {
}

export type ImageProps = string | ImageObjectProps | ImageDeviceProps;
export type GravityIconProps = string | {name: keyof typeof icons; color: 'brand' | 'text-color'};
export type ThemedImage = ThemeSupporting<ImageProps>;

export interface BackgroundImageProps
Expand Down
9 changes: 8 additions & 1 deletion src/models/constructor-items/sub-blocks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ClassNameProps, QuoteType} from '../../models';
import {ClassNameProps, GravityIconProps, QuoteType} from '../../models';
import {ThemeSupporting} from '../../utils';
import {
HubspotEventData,
Expand Down Expand Up @@ -60,8 +60,14 @@ export interface PositionedIcon {
position?: IconPosition;
}

export interface PositionedGravityIcon {
value: GravityIconProps;
position?: IconPosition;
}

export interface IconWrapperProps {
icon?: PositionedIcon;
gravityIcon?: PositionedGravityIcon;
}

export enum ImageCardDirection {
Expand Down Expand Up @@ -156,6 +162,7 @@ export interface BasicCardProps
url: string;
urlTitle?: string;
icon?: ThemeSupporting<ImageProps>;
gravityIcon?: ThemeSupporting<GravityIconProps>;
target?: string;
iconPosition?: IconPosition;
}
Expand Down
7 changes: 7 additions & 0 deletions src/sub-blocks/BasicCard/BasicCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const BasicCard = (props: BasicCardProps) => {
title,
text,
icon,
gravityIcon,
additionalInfo,
links,
list,
Expand All @@ -29,6 +30,7 @@ const BasicCard = (props: BasicCardProps) => {
const areControlsInFooter = controlPosition === 'footer';
const theme = useTheme();
const themedIcon = getThemedValue(icon, theme);
const themedGravityIcon = getThemedValue(gravityIcon, theme);

return (
<CardBase
Expand All @@ -40,6 +42,11 @@ const BasicCard = (props: BasicCardProps) => {
<CardBase.Content>
<IconWrapper
icon={themedIcon ? {value: themedIcon, position: iconPosition} : undefined}
gravityIcon={
themedGravityIcon
? {value: themedGravityIcon, position: iconPosition}
: undefined
}
className={b('wrapper')}
>
<Content
Expand Down
13 changes: 13 additions & 0 deletions src/sub-blocks/BasicCard/__stories__/BasicCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,23 @@ const ControlPositionTemplate: StoryFn<BasicCardProps> = (args) => (
</Grid>
);

const IconSourcesTemplate: StoryFn<Record<number, BasicCardProps>> = (args) => (
<div style={{display: 'flex', padding: '40px 0'}}>
{Object.values(args).map((arg, i) => (
<div key={i} style={{maxWidth: '400px', padding: '0 8px'}}>
<BasicCard {...arg} />
</div>
))}
</div>
);

export const Default = DefaultTemplate.bind({});
export const WithIcon = WithIconTemplate.bind({});
export const WithBorder = WithBorderTemplate.bind({});
export const WithUrl = WithUrlTemplate.bind({});
export const WithContentList = WithContentListTemplate.bind({});
export const ControlPosition = ControlPositionTemplate.bind({});
export const IconSources = IconSourcesTemplate.bind([]);

const DefaultArgs = {
...data.default.content,
Expand Down Expand Up @@ -184,3 +195,5 @@ ControlPosition.argTypes = {
buttons: {table: {disable: true}},
target: {table: {disable: true}},
};

IconSources.args = data.iconSources as BasicCardProps[];
46 changes: 44 additions & 2 deletions src/sub-blocks/BasicCard/__stories__/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"title": "Card with icon on {{position}}",
"icons": [
{
"light": "/story-assets/icon_1_light.svg",
"light": "Rocket",
"dark": "/story-assets/icon_1_dark.svg"
},
{
Expand Down Expand Up @@ -136,5 +136,47 @@
]
}
]
}
},
"iconSources": [
{
"title": "Gravity brand",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. In egestas erat imperdiet sed euismod nisi porta lorem.",
"gravityIcon": "Rocket",
"list": [
{
"gravityIcon": "AbbrZip",
"title": "Gravity icon",
"text": "Exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"icon": "/story-assets/icon_3_light.svg",
"title": "Icon from s3",
"text": "Exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
},
{
"title": "Gravity text-color",
"text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. In egestas erat imperdiet sed euismod nisi porta lorem.",
"gravityIcon": {
"name": "Rocket",
"color": "text-color"
},
"list": [
{
"gravityIcon": {
"name": "AbbrZip",
"color": "text-color"
},
"title": "Gravity icon",
"text": "Exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"icon": "/story-assets/icon_3_light.svg",
"title": "Icon from s3",
"text": "Exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
}
]
}
23 changes: 10 additions & 13 deletions src/sub-blocks/Content/__stories__/data.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,24 @@
],
"list": [
{
"icon": {
"light": "/story-assets/icon_1_light.svg",
"dark": "/story-assets/icon_1_dark.svg"
},
"title": "Lorem ipsum",
"gravityIcon": "Rocket",
"title": "Brand gravity icon",
"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 in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"icon": {
"light": "/story-assets/icon_3_light.svg",
"dark": "/story-assets/icon_3_dark.svg"
"gravityIcon": {
"name": "Rocket",
"color": "text-color"
},
"title": "Lorem ipsum ipsum",
"title": "Text-color gravity icon",
"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 in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
},
{
"icon": {
"light": "/story-assets/icon_2_light.svg",
"dark": "/story-assets/icon_2_dark.svg"
"gravityIcon": {
"light": "Rocket",
"dark": "PinFill"
},
"title": "Lorem ipsum",
"title": "Different icon in themes",
"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 in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
}
]
Expand Down
Loading