From ee7f8208fb775345aeeadb91ca01cafdf302d8cd Mon Sep 17 00:00:00 2001 From: "Leon.kov" Date: Sat, 27 Apr 2024 11:09:28 +0300 Subject: [PATCH] feat: add scroll to toolbar and useRouteChange --- src/app/App.tsx | 3 +++ src/app/lib/useAppToolbar.tsx | 15 +++++++++++ src/features/scrollToTopButton/index.ts | 1 + .../ScrollToTopButton/ScrollToTopButton.tsx | 27 +++++++++++++++++++ src/shared/assets/icons/circle-up.svg | 10 +++++++ src/shared/const/router.ts | 13 +++++++++ .../layouts/MainLayout/MainLayout.module.scss | 1 + src/shared/lib/router/useRouteChange.tsx | 18 +++++++++++++ src/widgets/ScrollToolbar/index.ts | 1 + .../ScrollToolbar/ScrollToolbar.module.scss | 3 +++ .../ui/ScrollToolbar/ScrollToolbar.tsx | 24 +++++++++++++++++ 11 files changed, 116 insertions(+) create mode 100644 src/app/lib/useAppToolbar.tsx create mode 100644 src/features/scrollToTopButton/index.ts create mode 100644 src/features/scrollToTopButton/ui/ScrollToTopButton/ScrollToTopButton.tsx create mode 100644 src/shared/assets/icons/circle-up.svg create mode 100644 src/shared/lib/router/useRouteChange.tsx create mode 100644 src/widgets/ScrollToolbar/index.ts create mode 100644 src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.module.scss create mode 100644 src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.tsx diff --git a/src/app/App.tsx b/src/app/App.tsx index acc92d3..4e970a4 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -10,11 +10,13 @@ import { useTheme } from '@/shared/lib/hook/useTheme/useTheme'; import { useAppDispatch } from '@/shared/lib/hook/useAppDispatch/useAppDispatch'; import { MainLayout } from '@/shared/layouts/MainLayout'; import { AppLoaderLayout } from '@/shared/layouts/AppLoaderLayout'; +import { useAppToolbar } from './lib/useAppToolbar'; function App() { const { theme } = useTheme(); const dispatch = useAppDispatch(); const inited = useSelector(getUserInited); + const toolbar = useAppToolbar(); useEffect(() => { dispatch(initAuthData()); @@ -35,6 +37,7 @@ function App() { header={} content={} sidebar={} + toolbar={toolbar} /> diff --git a/src/app/lib/useAppToolbar.tsx b/src/app/lib/useAppToolbar.tsx new file mode 100644 index 0000000..657cd6d --- /dev/null +++ b/src/app/lib/useAppToolbar.tsx @@ -0,0 +1,15 @@ +import { ReactElement } from 'react'; +import { AppRoutes } from '@/shared/const/router'; +import { ScrollToolbar } from '@/widgets/ScrollToolbar'; +import { useRouteChange } from '@/shared/lib/router/useRouteChange'; + +export function useAppToolbar() { + const appRoute = useRouteChange(); + + const toolbarByAppRoute: OptionalRecord = { + [AppRoutes.ARTICLES]: , + [AppRoutes.ARTICLE_DETAILS]: , + }; + + return toolbarByAppRoute[appRoute]; +} diff --git a/src/features/scrollToTopButton/index.ts b/src/features/scrollToTopButton/index.ts new file mode 100644 index 0000000..a4d47ad --- /dev/null +++ b/src/features/scrollToTopButton/index.ts @@ -0,0 +1 @@ +export { ScrollToTopButton } from './ui/ScrollToTopButton/ScrollToTopButton'; diff --git a/src/features/scrollToTopButton/ui/ScrollToTopButton/ScrollToTopButton.tsx b/src/features/scrollToTopButton/ui/ScrollToTopButton/ScrollToTopButton.tsx new file mode 100644 index 0000000..2bd4414 --- /dev/null +++ b/src/features/scrollToTopButton/ui/ScrollToTopButton/ScrollToTopButton.tsx @@ -0,0 +1,27 @@ +import { memo } from 'react'; +import { classNames } from '@/shared/lib/classNames/classNames'; +import { Icon } from '@/shared/ui/redesigned/Icon'; +import CircleIcon from '@/shared/assets/icons/circle-up.svg'; + +interface ScrollToTopButtonProps { + className?: string; +} + +export const ScrollToTopButton = memo((props: ScrollToTopButtonProps) => { + const { className } = props; + + const onCLick = () => { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }; + + return ( + + ); +}); diff --git a/src/shared/assets/icons/circle-up.svg b/src/shared/assets/icons/circle-up.svg new file mode 100644 index 0000000..971a4e2 --- /dev/null +++ b/src/shared/assets/icons/circle-up.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/shared/const/router.ts b/src/shared/const/router.ts index 33bf055..dae5df6 100644 --- a/src/shared/const/router.ts +++ b/src/shared/const/router.ts @@ -23,3 +23,16 @@ export const getRouteArticleEdit = (id: string) => `/articles/${id}/edit`; export const getRouteAdminPanel = () => '/admin'; export const getRouteForbidden = () => '/forbidden'; export const getRouteNotFound = () => '*'; + +export const AppRouteByPathPattern: Record = { + [getRouteMain()]: AppRoutes.MAIN, + [getRouteSettings()]: AppRoutes.SETTINGS, + [getRouteAbout()]: AppRoutes.ABOUT, + [getRouteProfile(':id')]: AppRoutes.PROFILE, + [getRouteArticles()]: AppRoutes.ARTICLES, + [getRouteArticleDetails(':id')]: AppRoutes.ARTICLE_DETAILS, + [getRouteArticleCreate()]: AppRoutes.ARTICLE_CREATE, + [getRouteArticleEdit(':id')]: AppRoutes.ARTICLE_EDIT, + [getRouteAdminPanel()]: AppRoutes.ADMIN_PANEL, + [getRouteForbidden()]: AppRoutes.FORBIDDEN, +}; diff --git a/src/shared/layouts/MainLayout/MainLayout.module.scss b/src/shared/layouts/MainLayout/MainLayout.module.scss index edd1bcc..788cb49 100644 --- a/src/shared/layouts/MainLayout/MainLayout.module.scss +++ b/src/shared/layouts/MainLayout/MainLayout.module.scss @@ -35,4 +35,5 @@ .toolbar { height: 100%; + width: 100%; } diff --git a/src/shared/lib/router/useRouteChange.tsx b/src/shared/lib/router/useRouteChange.tsx new file mode 100644 index 0000000..712c126 --- /dev/null +++ b/src/shared/lib/router/useRouteChange.tsx @@ -0,0 +1,18 @@ +import { matchPath, useLocation } from 'react-router-dom'; +import { useEffect, useState } from 'react'; +import { AppRouteByPathPattern, AppRoutes } from '@/shared/const/router'; + +export function useRouteChange() { + const location = useLocation(); + const [appRoute, setAppRoute] = useState(AppRoutes.MAIN); + + useEffect(() => { + Object.entries(AppRouteByPathPattern).forEach(([pattern, route]) => { + if (matchPath(pattern, location.pathname)) { + setAppRoute(route); + } + }); + }, [location.pathname]); + + return appRoute; +} diff --git a/src/widgets/ScrollToolbar/index.ts b/src/widgets/ScrollToolbar/index.ts new file mode 100644 index 0000000..05e7826 --- /dev/null +++ b/src/widgets/ScrollToolbar/index.ts @@ -0,0 +1 @@ +export { ScrollToolbar } from './ui/ScrollToolbar/ScrollToolbar'; diff --git a/src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.module.scss b/src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.module.scss new file mode 100644 index 0000000..74ab4b9 --- /dev/null +++ b/src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.module.scss @@ -0,0 +1,3 @@ +.ScrollToolbar { + height: 100%; +} diff --git a/src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.tsx b/src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.tsx new file mode 100644 index 0000000..0956db9 --- /dev/null +++ b/src/widgets/ScrollToolbar/ui/ScrollToolbar/ScrollToolbar.tsx @@ -0,0 +1,24 @@ +import { memo } from 'react'; +import { classNames } from '@/shared/lib/classNames/classNames'; +import cls from './ScrollToolbar.module.scss'; +import { VStack } from '@/shared/ui/redesigned/Stack'; +import { ScrollToTopButton } from '@/features/scrollToTopButton'; + +interface ScrollToolbarProps { + className?: string; +} + +export const ScrollToolbar = memo((props: ScrollToolbarProps) => { + const { className } = props; + + return ( + + + + ); +});