From 6ab3a984a8503b0b545e351169dbf9868b0818aa Mon Sep 17 00:00:00 2001 From: Nothingg Date: Mon, 30 Oct 2023 14:09:49 -0500 Subject: [PATCH] Redesign article blocks, articles list --- json-server/db.json | 2 +- .../ArticleCodeBlockComponent.tsx | 2 +- .../ArticleDetails/ArticleDetails.module.scss | 4 - .../ui/ArticleDetails/ArticleDetails.tsx | 97 ++++++------------- .../ArticleDetailsDeprecatedContent.tsx | 51 ++++++++++ .../ArticleDetailsDeprecatedError.tsx | 18 ++++ .../ArticleDetailsDeprecatedSkeletons.tsx | 27 ++++++ .../ArticleDetailsDeprecated/index.ts | 3 + .../ArticleDetailsRedesignedContent.tsx | 39 ++++++++ .../ArticleDetailsRedesignedError.tsx | 15 +++ .../ArticleDetailsRedesignedSkeletons.tsx | 24 +++++ .../ArticleDetailsRedesigned/index.ts | 3 + .../Article/ui/ArticleDetails/renderBlock.tsx | 18 ++++ .../ArticleImageBlockComponent.tsx | 14 ++- .../ArticleTextBlockComponent.module.scss | 4 - .../ArticleTextBlockComponent.tsx | 40 ++++++-- .../ArticlesListItemRedesigned.module.scss | 39 +++----- .../ArticlesListItemRedesigned.tsx | 9 +- .../ui/ArticleRecommendations.module.scss | 1 + .../ArticleDetailsPage/ArticleDetailsPage.tsx | 2 +- .../ArticleDetailsPageHeader.tsx | 3 +- .../ArticlesListFilters.module.scss | 2 +- .../ArticlesListFilters.tsx | 2 +- .../assets/deprecated-icons/AboutPage.tsx | 3 + .../assets/deprecated-icons/ArticlesPage.tsx | 3 + src/shared/assets/deprecated-icons/Copy.tsx | 3 + .../assets/deprecated-icons/CreatedAt.tsx | 3 + .../assets/deprecated-icons/MainPage.tsx | 3 + .../assets/deprecated-icons/Profile.tsx | 3 + .../assets/deprecated-icons/ProfilePage.tsx | 3 + src/shared/assets/deprecated-icons/Star.tsx | 3 + src/shared/assets/redesigned-icons/Copy.tsx | 9 ++ src/shared/assets/redesigned-icons/index.ts | 1 + .../StickyContentLayout.module.scss | 1 + src/shared/ui/deprecated/Code/Code.tsx | 30 ------ .../Code/Code.module.scss | 12 ++- .../Code/Code.stories.tsx | 0 src/shared/ui/redesigned/Code/Code.tsx | 44 +++++++++ .../{deprecated => redesigned}/Code/index.ts | 0 src/shared/ui/redesigned/Text/Text.tsx | 6 +- .../ArticleDetailsWidget.tsx | 4 +- 41 files changed, 386 insertions(+), 164 deletions(-) create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedContent.tsx create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedError.tsx create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedSkeletons.tsx create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/index.ts create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedContent.tsx create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedError.tsx create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedSkeletons.tsx create mode 100644 src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/index.ts create mode 100644 src/entities/Article/ui/ArticleDetails/renderBlock.tsx create mode 100644 src/shared/assets/redesigned-icons/Copy.tsx delete mode 100644 src/shared/ui/deprecated/Code/Code.tsx rename src/shared/ui/{deprecated => redesigned}/Code/Code.module.scss (58%) rename src/shared/ui/{deprecated => redesigned}/Code/Code.stories.tsx (100%) create mode 100644 src/shared/ui/redesigned/Code/Code.tsx rename src/shared/ui/{deprecated => redesigned}/Code/index.ts (100%) diff --git a/json-server/db.json b/json-server/db.json index 59d0caa..7d94dec 100644 --- a/json-server/db.json +++ b/json-server/db.json @@ -1202,7 +1202,7 @@ "isAppRedesigned": true }, "jsonSettings": { - "theme": "app_light_theme", + "theme": "app_sand_theme", "isArticlesPageWasOpenedOnce": true }, "avatar": "https://source.boringavatars.com/pixel/120/Stefan?colors=26a653,2a1d8f,79646a" diff --git a/src/entities/Article/ui/ArticleCodeBlockComponent/ArticleCodeBlockComponent.tsx b/src/entities/Article/ui/ArticleCodeBlockComponent/ArticleCodeBlockComponent.tsx index 0aa457a..d2fbbfa 100644 --- a/src/entities/Article/ui/ArticleCodeBlockComponent/ArticleCodeBlockComponent.tsx +++ b/src/entities/Article/ui/ArticleCodeBlockComponent/ArticleCodeBlockComponent.tsx @@ -1,6 +1,6 @@ import { FC, memo } from 'react'; import { classNames } from '@/shared/lib/classNames/classNames'; -import { Code } from '@/shared/ui/deprecated/Code'; +import { Code } from '@/shared/ui/redesigned/Code'; import { ArticleCodeBlock } from '../../model/types/article'; import cls from './ArticleCodeBlockComponent.module.scss'; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetails.module.scss b/src/entities/Article/ui/ArticleDetails/ArticleDetails.module.scss index c77b8b3..a7ee82b 100644 --- a/src/entities/Article/ui/ArticleDetails/ArticleDetails.module.scss +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetails.module.scss @@ -12,7 +12,3 @@ margin: 0 auto; } -.article { - // width: 100%; - // height: 100%; -} diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetails.tsx b/src/entities/Article/ui/ArticleDetails/ArticleDetails.tsx index 5373204..bce3dfe 100644 --- a/src/entities/Article/ui/ArticleDetails/ArticleDetails.tsx +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetails.tsx @@ -1,28 +1,29 @@ -import { FC, memo, ReactNode, useCallback } from 'react'; -import { useTranslation } from 'react-i18next'; +import { FC, memo, ReactNode } from 'react'; import { useAppSelector } from '@/shared/lib/hooks/useAppSelector'; import { DynamicModuleWrapper, ReducersList } from '@/shared/lib/components/DynamicModuleWrapper'; import { classNames } from '@/shared/lib/classNames/classNames'; import { useAppDispatch } from '@/shared/lib/hooks/useAppDispatch'; import { useInitialEffect } from '@/shared/lib/hooks/useInitialEffect'; -import { CreatedAtIcon, ViewsIcon } from '@/shared/assets/deprecated-icons'; -import { Skeleton } from '@/shared/ui/deprecated/Skeleton'; -import { Avatar } from '@/shared/ui/deprecated/Avatar'; -import { Icon } from '@/shared/ui/deprecated/Icon'; -import { HStack, VStack } from '@/shared/ui/redesigned/Stack'; -import { Text, TextAlign, TextSize, TextTheme } from '@/shared/ui/deprecated/Text'; +import { ToggleFeatures } from '@/shared/lib/features'; + import { articleDetailsReducer } from '../../model/slices/articleDetailsSlice'; import { fetchArticleById } from '../../model/services/fetchArticleById/fetchArticleById'; -import { ArticleBlock } from '../../model/types/article'; -import { ArticleCodeBlockComponent } from '../ArticleCodeBlockComponent'; -import { ArticleImageBlockComponent } from '../ArticleImageBlockComponent'; -import { ArticleTextBlockComponent } from '../ArticleTextBlockComponent'; -import { ArticleBlockType } from '../../model/consts'; import { getArticleDetailsData, getArticleDetailsError, getArticleDetailsIsLoading, } from '../../model/selectors/articleDetails'; +import { + ArticleDetailsRedesignedContent, + ArticleDetailsRedesignedError, + ArticleDetailsRedesignedSkeletons, +} from './ArticleDetailsRedesigned'; +import { + ArticleDetailsDeprecatedContent, + ArticleDetailsDeprecatedError, + ArticleDetailsDeprecatedSkeletons, +} from './ArticleDetailsDeprecated'; + import cls from './ArticleDetails.module.scss'; const reducers: ReducersList = { @@ -34,27 +35,12 @@ interface ArticleDetailsProps { } export const ArticleDetails: FC = memo(({ className, id }) => { - const { t } = useTranslation('articles'); - const dispatch = useAppDispatch(); const data = useAppSelector(getArticleDetailsData); const error = useAppSelector(getArticleDetailsError); const isLoading = useAppSelector(getArticleDetailsIsLoading); - const renderBlock = useCallback((block: ArticleBlock) => { - switch (block.type) { - case ArticleBlockType.CODE: - return ; - case ArticleBlockType.IMAGE: - return ; - case ArticleBlockType.TEXT: - return ; - default: - return null; - } - }, []); - useInitialEffect(() => { dispatch(fetchArticleById(id)); }, [dispatch, id]); @@ -63,54 +49,27 @@ export const ArticleDetails: FC = memo(({ className, id }) if (isLoading) { content = ( -
- - - - - - - -
+ } + off={} + /> ); } else if (error) { content = ( - } + off={} /> ); } else { content = ( -
- - - - - - - } /> - - - - } /> - - - - - {data?.blocks.map(renderBlock)} - -
+ } + off={} + /> ); } diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedContent.tsx b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedContent.tsx new file mode 100644 index 0000000..90d3b94 --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedContent.tsx @@ -0,0 +1,51 @@ +import { FC } from 'react'; +import { Avatar } from '@/shared/ui/deprecated/Avatar'; +import { HStack, VStack } from '@/shared/ui/redesigned/Stack'; +import { Text, TextSize } from '@/shared/ui/deprecated/Text'; +import { Icon } from '@/shared/ui/deprecated/Icon'; +import { CreatedAtIcon, ViewsIcon } from '@/shared/assets/deprecated-icons'; + +import { renderBlock } from '../renderBlock'; +import { Article } from '../../../model/types/article'; + +interface ArticleDetailsDeprecatedContentProps { + data?: Article +} + +/** + * @deprecated + */ +export const ArticleDetailsDeprecatedContent: FC = (props) => { + const { data } = props; + + return ( +
+ + + + + + + } /> + + + + } /> + + + + + {data?.blocks.map(renderBlock)} + +
+ ); +}; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedError.tsx b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedError.tsx new file mode 100644 index 0000000..af20ba4 --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedError.tsx @@ -0,0 +1,18 @@ +import { FC } from 'react'; +import { useAppTranslation } from '@/shared/lib/hooks/useAppTranslation'; +import { Text, TextAlign, TextTheme } from '@/shared/ui/deprecated/Text'; + +/** + * @deprecated + */ +export const ArticleDetailsDeprecatedError: FC = () => { + const { t } = useAppTranslation('articles'); + + return ( + + ); +}; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedSkeletons.tsx b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedSkeletons.tsx new file mode 100644 index 0000000..dd3e10a --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/ArticleDetailsDeprecatedSkeletons.tsx @@ -0,0 +1,27 @@ +import { FC } from 'react'; +import { classNames } from '@/shared/lib/classNames/classNames'; +import { Skeleton } from '@/shared/ui/deprecated/Skeleton'; + +import cls from '../ArticleDetails.module.scss'; + +interface ArticleDetailsRedesignedSkeletonsProps { + isLoading: boolean; + className?: string; +} + +/** + * @deprecated + */ +export const ArticleDetailsDeprecatedSkeletons: FC = ({ isLoading, className }) => { + return ( +
+ + + + + + + +
+ ); +}; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/index.ts b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/index.ts new file mode 100644 index 0000000..bcc7145 --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsDeprecated/index.ts @@ -0,0 +1,3 @@ +export { ArticleDetailsDeprecatedContent } from './ArticleDetailsDeprecatedContent'; +export { ArticleDetailsDeprecatedError } from './ArticleDetailsDeprecatedError'; +export { ArticleDetailsDeprecatedSkeletons } from './ArticleDetailsDeprecatedSkeletons'; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedContent.tsx b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedContent.tsx new file mode 100644 index 0000000..54ed751 --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedContent.tsx @@ -0,0 +1,39 @@ +import { FC } from 'react'; +import { VStack } from '@/shared/ui/redesigned/Stack'; +import { Text } from '@/shared/ui/redesigned/Text'; +import { AppImage } from '@/shared/ui/redesigned/AppImage'; +import { Skeleton } from '@/shared/ui/redesigned/Skeleton'; + +import { renderBlock } from '../renderBlock'; +import { Article } from '../../../model/types/article'; + +interface ArticleDetailsRedesignedContentProps { + data?: Article +} + +export const ArticleDetailsRedesignedContent: FC = (props) => { + const { data } = props; + + return ( + + + + } + /> + + + {data?.blocks.map(renderBlock)} + + + ); +}; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedError.tsx b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedError.tsx new file mode 100644 index 0000000..28e954d --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedError.tsx @@ -0,0 +1,15 @@ +import { FC } from 'react'; +import { useAppTranslation } from '@/shared/lib/hooks/useAppTranslation'; +import { Text } from '@/shared/ui/redesigned/Text'; + +export const ArticleDetailsRedesignedError: FC = () => { + const { t } = useAppTranslation('articles'); + + return ( + + ); +}; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedSkeletons.tsx b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedSkeletons.tsx new file mode 100644 index 0000000..8d00eaa --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/ArticleDetailsRedesignedSkeletons.tsx @@ -0,0 +1,24 @@ +import { FC } from 'react'; +import { classNames } from '@/shared/lib/classNames/classNames'; +import { Skeleton } from '@/shared/ui/redesigned/Skeleton'; + +import cls from '../ArticleDetails.module.scss'; + +interface ArticleDetailsRedesignedSkeletonsProps { + isLoading: boolean; + className?: string; +} + +export const ArticleDetailsRedesignedSkeletons: FC = ({ isLoading, className }) => { + return ( +
+ + + + + + + +
+ ); +}; diff --git a/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/index.ts b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/index.ts new file mode 100644 index 0000000..57a3107 --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/ArticleDetailsRedesigned/index.ts @@ -0,0 +1,3 @@ +export { ArticleDetailsRedesignedContent } from './ArticleDetailsRedesignedContent'; +export { ArticleDetailsRedesignedError } from './ArticleDetailsRedesignedError'; +export { ArticleDetailsRedesignedSkeletons } from './ArticleDetailsRedesignedSkeletons'; diff --git a/src/entities/Article/ui/ArticleDetails/renderBlock.tsx b/src/entities/Article/ui/ArticleDetails/renderBlock.tsx new file mode 100644 index 0000000..54b837a --- /dev/null +++ b/src/entities/Article/ui/ArticleDetails/renderBlock.tsx @@ -0,0 +1,18 @@ +import { ArticleBlockType } from '../../model/consts'; +import { ArticleBlock } from '../../model/types/article'; +import { ArticleCodeBlockComponent } from '../ArticleCodeBlockComponent'; +import { ArticleImageBlockComponent } from '../ArticleImageBlockComponent'; +import { ArticleTextBlockComponent } from '../ArticleTextBlockComponent'; + +export const renderBlock = (block: ArticleBlock) => { + switch (block.type) { + case ArticleBlockType.CODE: + return ; + case ArticleBlockType.IMAGE: + return ; + case ArticleBlockType.TEXT: + return ; + default: + return null; + } +}; diff --git a/src/entities/Article/ui/ArticleImageBlockComponent/ArticleImageBlockComponent.tsx b/src/entities/Article/ui/ArticleImageBlockComponent/ArticleImageBlockComponent.tsx index b770152..6c8cd62 100644 --- a/src/entities/Article/ui/ArticleImageBlockComponent/ArticleImageBlockComponent.tsx +++ b/src/entities/Article/ui/ArticleImageBlockComponent/ArticleImageBlockComponent.tsx @@ -1,7 +1,11 @@ import { FC, memo } from 'react'; import { classNames } from '@/shared/lib/classNames/classNames'; import { VStack } from '@/shared/ui/redesigned/Stack'; -import { Text } from '@/shared/ui/deprecated/Text'; +import { Text as TextDeprecated } from '@/shared/ui/deprecated/Text'; +import { AppImage } from '@/shared/ui/redesigned/AppImage'; +import { ToggleFeatures } from '@/shared/lib/features'; +import { Text } from '@/shared/ui/redesigned/Text'; + import { ArticleImageBlock } from '../../model/types/article'; import cls from './ArticleImageBlockComponent.module.scss'; @@ -17,9 +21,13 @@ export const ArticleImageBlockComponent: FC = m align="center" className={classNames(cls.ArticleImageBlockComponent, {}, [className])} > - {block.title} + {block.title && ( - + } + off={} + /> )} ); diff --git a/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.module.scss b/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.module.scss index 18de4ae..8284b59 100644 --- a/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.module.scss +++ b/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.module.scss @@ -1,7 +1,3 @@ -.ArticleTextBlockComponent { - -} - .title { margin-bottom: 16px; } diff --git a/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.tsx b/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.tsx index 576ae7e..78072b6 100644 --- a/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.tsx +++ b/src/entities/Article/ui/ArticleTextBlockComponent/ArticleTextBlockComponent.tsx @@ -1,7 +1,10 @@ import { FC, memo } from 'react'; import { classNames } from '@/shared/lib/classNames/classNames'; import { VStack } from '@/shared/ui/redesigned/Stack'; -import { Text } from '@/shared/ui/deprecated/Text'; +import { Text as TextDeprecated } from '@/shared/ui/deprecated/Text'; +import { Text } from '@/shared/ui/redesigned/Text'; +import { ToggleFeatures } from '@/shared/lib/features'; + import { ArticleTextBlock } from '../../model/types/article'; import cls from './ArticleTextBlockComponent.module.scss'; @@ -12,15 +15,32 @@ interface ArticleTextBlockComponentProps { export const ArticleTextBlockComponent: FC = memo(({ className, block }) => { return ( -
- {block.title && ( - + + {block.title && ( + + )} + + {block.paragraphs.map((p) => ( + + ))} + +
+ )} + off={( +
+ {block.title && ( + + )} + + {block.paragraphs.map((p) => ( + + ))} + +
)} - - {block.paragraphs.map((p) => ( - - ))} - - + /> ); }); diff --git a/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.module.scss b/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.module.scss index e16b3ad..66e6f71 100644 --- a/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.module.scss +++ b/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.module.scss @@ -8,8 +8,6 @@ } .LIST { - width: 100%; - .img { object-fit: contain; max-height: 250px; @@ -25,49 +23,36 @@ } .TILE { - .title { - width: 200px; - - p { - word-break: break-all; - } - } - - .timestamp { - position: absolute; - top: -20px; - right: 0; - display: none; - } &:hover { transform: scale(1.05); opacity: .8; + } - .timestamp { - display: block; - } + .title { + max-width: 100%; + word-wrap: break-word; } .card { width: 240px; - min-height: 350px; + height: 350px; overflow: hidden; display: flex; flex-direction: column; - align-items: center; gap: 8px; + padding-top: 8px !important; } .img { - width: 200px; - height: 200px; + width: 100%; object-fit: contain; - user-select: none; + min-height: 140px; + max-height: 140px; } .info { - padding: 8px 8px 16px; + padding: 8px 8px 16px 8px; height: 100%; } @@ -75,5 +60,7 @@ height: 100%; justify-content: flex-end; } - + .avatar { + margin-left: 8px; + } } diff --git a/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.tsx b/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.tsx index 985d82e..78b04c1 100644 --- a/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.tsx +++ b/src/entities/Article/ui/ArticlesListItem/ArticleListItemRedesigned/ArticlesListItemRedesigned.tsx @@ -87,19 +87,16 @@ export const ArticlesListItemRedesigned: FC = memo(({ cla data-testid="ArticleListItem" target={target} to={getRouteArticleDetails(article.id)} - className={classNames(cls.ArticleListItem, {}, [ - className, - cls[view], - ])} + className={classNames(cls.ArticleListItem, {}, [className, cls[view]])} > - + } alt={article.title} src={article.img} className={cls.img} /> - + diff --git a/src/features/ArticleRecommendations/ui/ArticleRecommendations.module.scss b/src/features/ArticleRecommendations/ui/ArticleRecommendations.module.scss index ddb1a89..8f42f81 100644 --- a/src/features/ArticleRecommendations/ui/ArticleRecommendations.module.scss +++ b/src/features/ArticleRecommendations/ui/ArticleRecommendations.module.scss @@ -3,6 +3,7 @@ } .list { + height: 350px; flex-wrap: nowrap; overflow-y: hidden; overflow-x: auto; diff --git a/src/pages/ArticleDetailsPage/ui/ArticleDetailsPage/ArticleDetailsPage.tsx b/src/pages/ArticleDetailsPage/ui/ArticleDetailsPage/ArticleDetailsPage.tsx index f82bab7..7ac60d5 100644 --- a/src/pages/ArticleDetailsPage/ui/ArticleDetailsPage/ArticleDetailsPage.tsx +++ b/src/pages/ArticleDetailsPage/ui/ArticleDetailsPage/ArticleDetailsPage.tsx @@ -37,6 +37,7 @@ const ArticleDetailsPage: FC = ({ className }) => { const ArticleDetailsPageRedesigned = ( } content={( @@ -47,7 +48,6 @@ const ArticleDetailsPage: FC = ({ className }) => { )} - right={} /> ); diff --git a/src/pages/ArticleDetailsPage/ui/ArticleDetailsPageHeader/ArticleDetailsPageHeader.tsx b/src/pages/ArticleDetailsPage/ui/ArticleDetailsPageHeader/ArticleDetailsPageHeader.tsx index 168359e..08781a4 100644 --- a/src/pages/ArticleDetailsPage/ui/ArticleDetailsPageHeader/ArticleDetailsPageHeader.tsx +++ b/src/pages/ArticleDetailsPage/ui/ArticleDetailsPageHeader/ArticleDetailsPageHeader.tsx @@ -7,6 +7,7 @@ import { useAppSelector } from '@/shared/lib/hooks/useAppSelector'; import { AppLink } from '@/shared/ui/deprecated/AppLink'; import { Button } from '@/shared/ui/deprecated/Button'; import { HStack } from '@/shared/ui/redesigned/Stack'; +import { isUserAdmin } from '@/entities/User'; interface ArticleDetailsPageHeaderProps { id: string; @@ -16,7 +17,7 @@ export const ArticleDetailsPageHeader: FC = memo( const { t } = useTranslation('articles'); const navigate = useNavigate(); - const canEdit = useAppSelector((state) => getCanEditArticle(state)); + const canEdit = useAppSelector((state) => getCanEditArticle(state)) || isUserAdmin; const onReturnBackClick = useCallback(() => { navigate(-1); diff --git a/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.module.scss b/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.module.scss index 91a535a..bc14200 100644 --- a/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.module.scss +++ b/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.module.scss @@ -1,5 +1,5 @@ .ArticlesListFilters { - // padding: 12px; + margin-bottom: 16px; } .sort-filters { diff --git a/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.tsx b/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.tsx index 795c2b4..9bd6039 100644 --- a/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.tsx +++ b/src/pages/ArticlesPage/ui/ArticlesListFilters/ArticlesListFilters.tsx @@ -34,7 +34,7 @@ export const ArticlesListFilters: FC = memo(({ classNa } = useArticleFilters(); return ( - +
> = ({ ...props }) => { return ( diff --git a/src/shared/assets/deprecated-icons/ArticlesPage.tsx b/src/shared/assets/deprecated-icons/ArticlesPage.tsx index 6d69fd7..41d25c7 100644 --- a/src/shared/assets/deprecated-icons/ArticlesPage.tsx +++ b/src/shared/assets/deprecated-icons/ArticlesPage.tsx @@ -1,5 +1,8 @@ import { FC, HTMLAttributes } from 'react'; +/** + * @deprecated + */ export const ArticlesPageIcon: FC> = ({ ...props }) => { return ( diff --git a/src/shared/assets/deprecated-icons/Copy.tsx b/src/shared/assets/deprecated-icons/Copy.tsx index 282852f..982c524 100644 --- a/src/shared/assets/deprecated-icons/Copy.tsx +++ b/src/shared/assets/deprecated-icons/Copy.tsx @@ -1,5 +1,8 @@ import { FC, HTMLAttributes } from 'react'; +/** + * @deprecated + */ export const CopyIcon: FC> = ({ ...props }) => { return ( diff --git a/src/shared/assets/deprecated-icons/CreatedAt.tsx b/src/shared/assets/deprecated-icons/CreatedAt.tsx index 3ac75cc..6e0e015 100644 --- a/src/shared/assets/deprecated-icons/CreatedAt.tsx +++ b/src/shared/assets/deprecated-icons/CreatedAt.tsx @@ -1,5 +1,8 @@ import { FC, HTMLAttributes } from 'react'; +/** + * @deprecated + */ export const CreatedAtIcon: FC> = ({ ...props }) => { return ( diff --git a/src/shared/assets/deprecated-icons/MainPage.tsx b/src/shared/assets/deprecated-icons/MainPage.tsx index 28ed16e..4d05661 100644 --- a/src/shared/assets/deprecated-icons/MainPage.tsx +++ b/src/shared/assets/deprecated-icons/MainPage.tsx @@ -1,5 +1,8 @@ import { FC, HTMLAttributes } from 'react'; +/** + * @deprecated + */ export const MainPageIcon: FC> = ({ ...props }) => { return ( diff --git a/src/shared/assets/deprecated-icons/Profile.tsx b/src/shared/assets/deprecated-icons/Profile.tsx index de148e6..51ecbfd 100644 --- a/src/shared/assets/deprecated-icons/Profile.tsx +++ b/src/shared/assets/deprecated-icons/Profile.tsx @@ -1,5 +1,8 @@ import { FC, HTMLAttributes } from 'react'; +/** + * @deprecated + */ export const ProfileIcon: FC> = ({ ...props }) => { return ( diff --git a/src/shared/assets/deprecated-icons/ProfilePage.tsx b/src/shared/assets/deprecated-icons/ProfilePage.tsx index 90a7bd8..630b9e0 100644 --- a/src/shared/assets/deprecated-icons/ProfilePage.tsx +++ b/src/shared/assets/deprecated-icons/ProfilePage.tsx @@ -1,5 +1,8 @@ import { FC, HTMLAttributes } from 'react'; +/** + * @deprecated + */ export const ProfilePageIcon: FC> = ({ ...props }) => { return ( diff --git a/src/shared/assets/deprecated-icons/Star.tsx b/src/shared/assets/deprecated-icons/Star.tsx index 085ded1..2f126da 100644 --- a/src/shared/assets/deprecated-icons/Star.tsx +++ b/src/shared/assets/deprecated-icons/Star.tsx @@ -1,5 +1,8 @@ import { FC, HTMLAttributes } from 'react'; +/** + * @deprecated + */ export const StarIcon: FC> = (props) => { return ( diff --git a/src/shared/assets/redesigned-icons/Copy.tsx b/src/shared/assets/redesigned-icons/Copy.tsx new file mode 100644 index 0000000..62e23f1 --- /dev/null +++ b/src/shared/assets/redesigned-icons/Copy.tsx @@ -0,0 +1,9 @@ +import { FC, HTMLAttributes } from 'react'; + +export const CopyIcon: FC> = (props) => { + return ( + + + + ); +}; diff --git a/src/shared/assets/redesigned-icons/index.ts b/src/shared/assets/redesigned-icons/index.ts index a308576..24d864a 100644 --- a/src/shared/assets/redesigned-icons/index.ts +++ b/src/shared/assets/redesigned-icons/index.ts @@ -9,3 +9,4 @@ export { NotificationIcon } from './Notification'; export { GridViewIcon } from './GridView'; export { ListViewIcon } from './ListView'; export { SearchIcon } from './Search'; +export { CopyIcon } from './Copy'; diff --git a/src/shared/layouts/StickyContentLayout/StickyContentLayout.module.scss b/src/shared/layouts/StickyContentLayout/StickyContentLayout.module.scss index 0a6bd99..609d07a 100644 --- a/src/shared/layouts/StickyContentLayout/StickyContentLayout.module.scss +++ b/src/shared/layouts/StickyContentLayout/StickyContentLayout.module.scss @@ -23,6 +23,7 @@ .left, .right { + top: 0; position: sticky; top: 32px; height: fit-content; diff --git a/src/shared/ui/deprecated/Code/Code.tsx b/src/shared/ui/deprecated/Code/Code.tsx deleted file mode 100644 index 480784b..0000000 --- a/src/shared/ui/deprecated/Code/Code.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { FC, memo, useCallback } from 'react'; -import { CopyIcon } from '@/shared/assets/deprecated-icons'; -import { classNames } from '@/shared/lib/classNames/classNames'; -import { Button, ButtonTheme } from '../Button/Button'; -import cls from './Code.module.scss'; - -interface CodeProps { - className?: string; - code: string; -} -/** - * Deprecated component. Please use updated version in `@/shared/ui/redesigned` - * @deprecated - */ -export const Code: FC = memo(({ className, code }) => { - const onCopyClipboard = useCallback(async () => { - await navigator.clipboard.writeText(code); - }, [code]); - - return ( -
-      
-      
-        {code}
-      
-    
- ); -}); diff --git a/src/shared/ui/deprecated/Code/Code.module.scss b/src/shared/ui/redesigned/Code/Code.module.scss similarity index 58% rename from src/shared/ui/deprecated/Code/Code.module.scss rename to src/shared/ui/redesigned/Code/Code.module.scss index 2cb306d..77758dc 100644 --- a/src/shared/ui/deprecated/Code/Code.module.scss +++ b/src/shared/ui/redesigned/Code/Code.module.scss @@ -7,6 +7,16 @@ color: var(--primary-color); } +.CodeRedesigned { + padding: 20px; + position: relative; + background: var(--light-bg); + overflow: auto; + border: 1px solid var(--accent); + border-radius: 16px; + font: var(--font-m-redesigned); +} + .copy-btn { position: absolute; right: 20px; @@ -15,4 +25,4 @@ svg > path { stroke: var(--primary-color); } -} \ No newline at end of file +} diff --git a/src/shared/ui/deprecated/Code/Code.stories.tsx b/src/shared/ui/redesigned/Code/Code.stories.tsx similarity index 100% rename from src/shared/ui/deprecated/Code/Code.stories.tsx rename to src/shared/ui/redesigned/Code/Code.stories.tsx diff --git a/src/shared/ui/redesigned/Code/Code.tsx b/src/shared/ui/redesigned/Code/Code.tsx new file mode 100644 index 0000000..cb721c3 --- /dev/null +++ b/src/shared/ui/redesigned/Code/Code.tsx @@ -0,0 +1,44 @@ +import { FC, memo, useCallback } from 'react'; +import { CopyIcon as CopyIconDeprecated } from '@/shared/assets/deprecated-icons'; +import { classNames } from '@/shared/lib/classNames/classNames'; +import { ToggleFeatures } from '@/shared/lib/features'; +import { CopyIcon } from '@/shared/assets/redesigned-icons'; + +import { Button, ButtonTheme } from '../../deprecated/Button/Button'; +import { Icon } from '../Icon'; +import cls from './Code.module.scss'; + +interface CodeProps { + className?: string; + code: string; +} + +export const Code: FC = memo(({ className, code }) => { + const onCopyClipboard = useCallback(async () => { + await navigator.clipboard.writeText(code); + }, [code]); + + return ( + + } clickable onClick={onCopyClipboard} className={cls['copy-btn']} /> + + {code} + + + )} + off={( +
+          
+          
+            {code}
+          
+        
+ )} + /> + ); +}); diff --git a/src/shared/ui/deprecated/Code/index.ts b/src/shared/ui/redesigned/Code/index.ts similarity index 100% rename from src/shared/ui/deprecated/Code/index.ts rename to src/shared/ui/redesigned/Code/index.ts diff --git a/src/shared/ui/redesigned/Text/Text.tsx b/src/shared/ui/redesigned/Text/Text.tsx index 2d6fc1a..d756f25 100644 --- a/src/shared/ui/redesigned/Text/Text.tsx +++ b/src/shared/ui/redesigned/Text/Text.tsx @@ -17,7 +17,7 @@ interface TextProps { size?: TextSize; textNoWrap?: boolean; titleNoWrap?: boolean; - bold?: boolean; + bold?: boolean | { text: boolean, title: boolean }; 'data-testid'?: string; } @@ -46,12 +46,12 @@ export const Text: FC = memo((props) => { const titleMods: Mods = { [cls['no-wrap']]: titleNoWrap, - [cls.bold]: bold, + [cls.bold]: typeof bold === 'object' ? bold.title : bold, }; const textMods: Mods = { [cls['no-wrap']]: textNoWrap, - [cls.bold]: bold, + [cls.bold]: typeof bold === 'object' ? bold.text : bold, }; return ( diff --git a/src/widgets/ArticleDetailsWidget/ui/ArticleDetailsWidget/ArticleDetailsWidget.tsx b/src/widgets/ArticleDetailsWidget/ui/ArticleDetailsWidget/ArticleDetailsWidget.tsx index c1804b3..8d5d6d3 100644 --- a/src/widgets/ArticleDetailsWidget/ui/ArticleDetailsWidget/ArticleDetailsWidget.tsx +++ b/src/widgets/ArticleDetailsWidget/ui/ArticleDetailsWidget/ArticleDetailsWidget.tsx @@ -7,7 +7,7 @@ import { Button } from '@/shared/ui/redesigned/Button'; import { Text } from '@/shared/ui/redesigned/Text'; import { useAppSelector } from '@/shared/lib/hooks/useAppSelector'; import { getCanEditArticle } from '@/entities/Article'; -import { User } from '@/entities/User'; +import { isUserAdmin, User } from '@/entities/User'; interface ArticleDetailsWidgetProps { className?: string; @@ -23,7 +23,7 @@ export const ArticleDetailsWidget: FC = memo((props) const { className, author, createdAt, views, translationNamespace, onEdit, onReturnBack } = props; const { t } = useAppTranslation(translationNamespace); - const canEdit = useAppSelector((state) => getCanEditArticle(state)); + const canEdit = useAppSelector((state) => getCanEditArticle(state)) || isUserAdmin; return (