diff --git a/src/entities/Article/ui/ArticleList/ArticleList.module.scss b/src/entities/Article/ui/ArticleList/ArticleList.module.scss index 5fc39dec..9d68aad4 100644 --- a/src/entities/Article/ui/ArticleList/ArticleList.module.scss +++ b/src/entities/Article/ui/ArticleList/ArticleList.module.scss @@ -1,11 +1,11 @@ -.articleList { - padding-top: 30px; -} - .BIG { .card { margin-bottom: 30px; } + + .row { + margin-bottom: 30px; + } } .SMALL { diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItem.tsx b/src/entities/Article/ui/ArticleListItem/ArticleListItem.tsx index 7a3ad9c7..b9f4ab59 100644 --- a/src/entities/Article/ui/ArticleListItem/ArticleListItem.tsx +++ b/src/entities/Article/ui/ArticleListItem/ArticleListItem.tsx @@ -1,22 +1,11 @@ import { HTMLAttributeAnchorTarget, memo } from 'react'; -import { useTranslation } from 'react-i18next'; -import { classNames } from '@/shared/lib/classNames'; -import { Text } from '@/shared/ui/deprecated/Text'; -import { Card } from '@/shared/ui/deprecated/Card'; -import { Avatar } from '@/shared/ui/deprecated/Avatar'; -import { Button } from '@/shared/ui/deprecated/Button'; -import { Icon } from '@/shared/ui/deprecated/Icon'; -import EyeIcon from '@/shared/assets/icons/eye-20-20.svg'; -import { AppLink } from '@/shared/ui/deprecated/AppLink'; -import { getRouteArticlesDetails } from '@/shared/const/router'; -import { AppImage } from '@/shared/ui/redesigned/AppImage'; -import { Skeleton } from '@/shared/ui/deprecated/Skeleton'; +import { ToggleFeatures } from '@/shared/lib/features'; -import { ArticleBlockType, ArticleView } from '../../model/consts/consts'; -import { Article, ArticleTextBlock } from '../../model/types/article'; -import cls from './ArticleListItem.module.scss'; -import { ArticleTextBlockComponent } from '../../ui/ArticleTextBlockComponent/ArticleTextBlockComponent'; +import { ArticleListItemRedesigned } from './ArticleListItemRedesigned/ArticleListItemRedesigned'; +import { ArticleListItemDeprecated } from './ArticleListItemDeprecated/ArticleListItemDeprecated'; +import { ArticleView } from '../../model/consts/consts'; +import { Article } from '../../model/types/article'; interface ArticleListItemProps { className?: string; @@ -28,82 +17,26 @@ interface ArticleListItemProps { export const ArticleListItem = memo((props: ArticleListItemProps) => { const { className, article, view, target } = props; - const { t } = useTranslation('articles'); - - const types = ; - const views = ( - <> - - - - ); - - if (view === ArticleView.BIG) { - const textBlock = article.blocks.find( - (block) => block.type === ArticleBlockType.TEXT, - ) as ArticleTextBlock; - - return ( -
- -
- - - -
- - - {types} - } - src={article.img} - alt={article.title} - className={cls.img} - /> - {!!textBlock && } - -
- - - - - {views} -
-
-
- ); - } - return ( - - -
- } - className={cls.img} - src={article.img} - alt={article.title} - /> - - -
- -
- {types} - {views} -
- - -
-
+ + } + off={ + + } + /> ); }); diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItem.module.scss b/src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.module.scss similarity index 100% rename from src/entities/Article/ui/ArticleListItem/ArticleListItem.module.scss rename to src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.module.scss diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItem.stories.tsx b/src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.stories.tsx similarity index 84% rename from src/entities/Article/ui/ArticleListItem/ArticleListItem.stories.tsx rename to src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.stories.tsx index da7e0787..93000759 100644 --- a/src/entities/Article/ui/ArticleListItem/ArticleListItem.stories.tsx +++ b/src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.stories.tsx @@ -2,10 +2,10 @@ import type { ComponentMeta, ComponentStory } from '@storybook/react'; import { ArticleView } from '../../model/consts/consts'; import { article } from '../../mocks/data'; -import { ArticleListItem } from './ArticleListItem'; +import { ArticleListItem } from './ArticleListItemDeprecated'; export default { - title: 'entities/Article/ArticleListItem', + title: 'entities/Article/ArticleListItemRedesigned', component: ArticleListItem, argTypes: { backgroundColor: { control: 'color' }, diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.tsx b/src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.tsx new file mode 100644 index 00000000..63c36232 --- /dev/null +++ b/src/entities/Article/ui/ArticleListItem/ArticleListItemDeprecated/ArticleListItemDeprecated.tsx @@ -0,0 +1,110 @@ +import { HTMLAttributeAnchorTarget, memo } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { classNames } from '@/shared/lib/classNames'; +import { Text } from '@/shared/ui/deprecated/Text'; +import { Card } from '@/shared/ui/deprecated/Card'; +import { Avatar } from '@/shared/ui/deprecated/Avatar'; +import { Button } from '@/shared/ui/deprecated/Button'; +import { Icon } from '@/shared/ui/deprecated/Icon'; +import EyeIcon from '@/shared/assets/icons/eye-20-20.svg'; +import { AppLink } from '@/shared/ui/deprecated/AppLink'; +import { getRouteArticlesDetails } from '@/shared/const/router'; +import { AppImage } from '@/shared/ui/redesigned/AppImage'; +import { Skeleton } from '@/shared/ui/deprecated/Skeleton'; + +import { ArticleBlockType, ArticleView } from '../../../model/consts/consts'; +import { Article, ArticleTextBlock } from '../../../model/types/article'; +import cls from './ArticleListItemDeprecated.module.scss'; +import { ArticleTextBlockComponent } from '../../../ui/ArticleTextBlockComponent/ArticleTextBlockComponent'; + +interface ArticleListItemProps { + className?: string; + article: Article; + view: ArticleView; + target?: HTMLAttributeAnchorTarget; +} + +export const ArticleListItemDeprecated = memo((props: ArticleListItemProps) => { + const { className, article, view, target } = props; + + const { t } = useTranslation('articles'); + + const types = ; + const views = ( + <> + + + + ); + + if (view === ArticleView.BIG) { + const textBlock = article.blocks.find( + (block) => block.type === ArticleBlockType.TEXT, + ) as ArticleTextBlock; + + return ( +
+ +
+ + + +
+ + + {types} + } + src={article.img} + alt={article.title} + className={cls.img} + /> + {!!textBlock && } + +
+ + + + + {views} +
+
+
+ ); + } + + return ( + + +
+ } + className={cls.img} + src={article.img} + alt={article.title} + /> + + +
+ +
+ {types} + {views} +
+ + +
+
+ ); +}); + +ArticleListItemDeprecated.displayName = 'ArticleListItemDeprecated'; diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.module.scss b/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.module.scss new file mode 100644 index 00000000..0a8cd0e0 --- /dev/null +++ b/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.module.scss @@ -0,0 +1,68 @@ +.BIG { + .img { + width: 100%; + max-height: 250px; + object-fit: cover; + } + + .textBlock { + max-height: 72px; + overflow-y: hidden; + } +} + +.SMALL { + width: 230px; + transition: 0.2s; + cursor: pointer; + + &:hover { + opacity: 0.8; + transform: scale(1.01); + + .date { + display: block; + } + } + + .imageWrapper { + width: 200px; + height: 200px; + position: relative; + } + + .img { + width: 200px; + height: 200px; + object-fit: cover; + } + + .infoWrapper { + display: flex; + align-items: center; + margin-top: 8px; + } + + .types p { + width: 115px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .views { + margin-left: auto; + margin-right: 8px; + } + + .title { + margin-top: 8px; + + p { + width: 200px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + } +} diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.stories.tsx b/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.stories.tsx new file mode 100644 index 00000000..5d33baca --- /dev/null +++ b/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.stories.tsx @@ -0,0 +1,29 @@ +import type { ComponentMeta, ComponentStory } from '@storybook/react'; + +import { ArticleView } from '../../../model/consts/consts'; +import { article } from '../../../mocks/data'; +import { ArticleListItemRedesigned } from './ArticleListItemRedesigned'; + +export default { + title: 'entities/Article/redesigned/ArticleListItemRedesigned', + component: ArticleListItemRedesigned, + argTypes: { + backgroundColor: { control: 'color' }, + }, +} as ComponentMeta; + +const Template: ComponentStory = (args) => ( + +); + +export const NormalSmall = Template.bind({}); +NormalSmall.args = { + article, + view: ArticleView.SMALL, +}; + +export const NormalBig = Template.bind({}); +NormalBig.args = { + article, + view: ArticleView.BIG, +}; diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.tsx b/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.tsx new file mode 100644 index 00000000..8c27d809 --- /dev/null +++ b/src/entities/Article/ui/ArticleListItem/ArticleListItemRedesigned/ArticleListItemRedesigned.tsx @@ -0,0 +1,113 @@ +import { HTMLAttributeAnchorTarget, memo } from 'react'; +import { useTranslation } from 'react-i18next'; + +import { classNames } from '@/shared/lib/classNames'; +import { Text } from '@/shared/ui/redesigned/Text'; +import { Card } from '@/shared/ui/redesigned/Card'; +import { Avatar } from '@/shared/ui/redesigned/Avatar'; +import { Button } from '@/shared/ui/redesigned/Button'; +import { Icon } from '@/shared/ui/redesigned/Icon'; +import EyeIcon from '@/shared/assets/icons/eye.svg'; +import { AppLink } from '@/shared/ui/redesigned/AppLink'; +import { getRouteArticlesDetails } from '@/shared/const/router'; +import { AppImage } from '@/shared/ui/redesigned/AppImage'; +import { Skeleton } from '@/shared/ui/redesigned/Skeleton'; +import { HStack, VStack } from '@/shared/ui/redesigned/Stack'; + +import { ArticleBlockType, ArticleView } from '../../../model/consts/consts'; +import { Article, ArticleTextBlock } from '../../../model/types/article'; +import cls from './ArticleListItemRedesigned.module.scss'; + +interface ArticleListItemProps { + className?: string; + article: Article; + view: ArticleView; + target?: HTMLAttributeAnchorTarget; +} + +export const ArticleListItemRedesigned = memo((props: ArticleListItemProps) => { + const { className, article, view, target } = props; + + const { t } = useTranslation('articles'); + + const views = ( + + + + + ); + + if (view === ArticleView.BIG) { + const textBlock = article.blocks.find( + (block) => block.type === ArticleBlockType.TEXT, + ) as ArticleTextBlock; + + return ( + + + + + + + + + + + } + src={article.img} + alt={article.title} + className={cls.img} + /> + {!!textBlock?.paragraphs && ( + + )} + + + + + + + {views} + + + + ); + } + + return ( + + +
+ } + className={cls.img} + src={article.img} + alt={article.title} + /> + + +
+ +
+ {/* {types} */} + {views} +
+ + +
+
+ ); +}); + +ArticleListItemRedesigned.displayName = 'ArticleListItemRedesigned'; diff --git a/src/entities/Article/ui/ArticleListItem/ArticleListItemSkeleton.tsx b/src/entities/Article/ui/ArticleListItem/ArticleListItemSkeleton.tsx index 91a43851..f3cd5311 100644 --- a/src/entities/Article/ui/ArticleListItem/ArticleListItemSkeleton.tsx +++ b/src/entities/Article/ui/ArticleListItem/ArticleListItemSkeleton.tsx @@ -1,11 +1,16 @@ import { memo } from 'react'; import { classNames } from '@/shared/lib/classNames'; -import { Skeleton } from '@/shared/ui/deprecated/Skeleton'; -import { Card } from '@/shared/ui/deprecated/Card'; +import { Skeleton as SkeletonDeprecated } from '@/shared/ui/deprecated/Skeleton'; +import { Skeleton } from '@/shared/ui/redesigned/Skeleton'; +import { Card as CardDeprecated } from '@/shared/ui/deprecated/Card'; +import { Card } from '@/shared/ui/redesigned/Card'; +import { ToggleFeatures } from '@/shared/lib/features'; +import { HStack, VStack } from '@/shared/ui/redesigned/Stack'; import { ArticleView } from '../../model/consts/consts'; -import cls from './ArticleListItem.module.scss'; +import clsDeprecated from './ArticleListItemDeprecated/ArticleListItemDeprecated.module.scss'; +import cls from './ArticleListItemRedesigned/ArticleListItemRedesigned.module.scss'; interface ArticleListItemSkeletonProps { className?: string; @@ -17,39 +22,95 @@ export const ArticleListItemSkeleton = memo((props: ArticleListItemSkeletonProps if (view === ArticleView.BIG) { return ( -
- -
- - - -
+ + + + + + + + + + + - - + + +
+ } + off={ +
+ +
+ + + +
-
- + + + +
+ +
+
- -
+ } + /> ); } return ( -
- -
- -
+ + +
+ +
-
- +
+ +
+ + +
+ } + off={ +
+ +
+ +
+ +
+ +
- - -
+ + +
+ } + /> ); }); diff --git a/src/shared/ui/redesigned/Button/ui/Button.module.scss b/src/shared/ui/redesigned/Button/ui/Button.module.scss index 658483a5..928de43c 100644 --- a/src/shared/ui/redesigned/Button/ui/Button.module.scss +++ b/src/shared/ui/redesigned/Button/ui/Button.module.scss @@ -45,6 +45,17 @@ border-radius: 34px; } +.outline { + background: none; + border: 1px solid var(--icon-redesigned); + outline: none; + border-radius: 34px; + + &:hover { + border: 1px solid var(--accent-redesigned); + } +} + .m { font: var(--font-m-redesigned); } diff --git a/src/shared/ui/redesigned/Text/ui/Text.module.scss b/src/shared/ui/redesigned/Text/ui/Text.module.scss index 66507f79..c684c2ba 100644 --- a/src/shared/ui/redesigned/Text/ui/Text.module.scss +++ b/src/shared/ui/redesigned/Text/ui/Text.module.scss @@ -67,3 +67,10 @@ font: var(--font-l-redesigned); } } + +.bold { + .title, + .text { + font-weight: 700; + } +} diff --git a/src/shared/ui/redesigned/Text/ui/Text.tsx b/src/shared/ui/redesigned/Text/ui/Text.tsx index 7a93d561..dcfc9792 100644 --- a/src/shared/ui/redesigned/Text/ui/Text.tsx +++ b/src/shared/ui/redesigned/Text/ui/Text.tsx @@ -17,6 +17,7 @@ interface TextProps { variant?: TextVariant; align?: TextAlign; size?: TextSize; + bold?: boolean; 'data-testid'?: string; } @@ -36,6 +37,7 @@ export const Text = memo((props: TextProps) => { variant = 'primary', align = 'left', size = 'm', + bold = false, 'data-testid': dataTestId = 'Text', } = props; @@ -43,7 +45,7 @@ export const Text = memo((props: TextProps) => { const additionalClasses = [className, cls[variant], cls[align], cls[size]]; return ( -
+
{title && ( {title}