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 (
+
+
+
+ );
+});