fix(global): add scroll-to-top

This commit is contained in:
2025-12-03 15:52:25 +03:00
parent 01de6f6e75
commit 0ab354e143
8 changed files with 102 additions and 21 deletions

26
.idea/workspace.xml generated
View File

@@ -5,27 +5,13 @@
</component>
<component name="ChangeListManager">
<list default="true" id="2a96f817-9dc2-4f3c-893a-c4974c750774" name="Changes" comment="">
<change afterPath="$PROJECT_DIR$/src/shared/ui/burger/index.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/shared/ui/burger/styles.module.scss" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/shared/ui/burger/ui.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/mobile-callback/index.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/mobile-callback/styles.module.scss" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/mobile-callback/ui.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/sidebar/index.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/sidebar/menu-item.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/sidebar/menu-list.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/sidebar/styles.module.scss" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/sidebar/ui.tsx" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/scroll-to-top/index.ts" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/scroll-to-top/styles.module.scss" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/widgets/scroll-to-top/ui.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/app/layout.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/app/layout.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/entities/base-menu/styles.module.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/entities/base-menu/styles.module.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/entities/base-menu/ui.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/entities/base-menu/ui.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/shared/const/menu.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/shared/const/menu.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/shared/types/menu.ts" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/src/shared/ui/icon/base.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/shared/ui/icon/base.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/shared/ui/icon/ui.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/shared/ui/icon/ui.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/shared/ui/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/shared/ui/index.ts" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/widgets/footer/styles.module.scss" beforeDir="false" afterPath="$PROJECT_DIR$/src/widgets/footer/styles.module.scss" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/widgets/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/widgets/index.ts" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
@@ -34,16 +20,16 @@
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="DarkyenusTimeTracker">
<option name="totalTimeSeconds" value="192744" />
<option name="totalTimeSeconds" value="194048" />
<option name="gitIntegration" value="true" />
<option name="naggedAbout" value="1" />
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="SCSS File" />
<option value="TypeScript File" />
<option value="TypeScript JSX File" />
<option value="SCSS File" />
</list>
</option>
</component>
@@ -128,7 +114,7 @@
<workItem from="1764590282382" duration="1201000" />
<workItem from="1764591867512" duration="4332000" />
<workItem from="1764657017067" duration="21490000" />
<workItem from="1764741053553" duration="16724000" />
<workItem from="1764741053553" duration="18011000" />
</task>
<servers />
</component>

View File

@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
import { Montserrat, Roboto } from 'next/font/google';
import '@core/styles/globals.scss';
import '@core/styles/reset.scss';
import { Footer, Header, MobileCallback } from '@/widgets';
import { Footer, Header, MobileCallback, ScrollToTop } from '@/widgets';
import { ModalProvider } from '@core/providers/modal-provider';
const roboto = Roboto({
@@ -35,6 +35,7 @@ export default function RootLayout({
<main>{children}</main>
<Footer />
<MobileCallback />
<ScrollToTop />
</ModalProvider>
</body>
</html>

View File

@@ -342,6 +342,22 @@ const MobilePhone = (props: SVGProps<SVGSVGElement>) => (
</svg>
);
//fluent:chevron-up-12-filled
const Chevron = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns='http://www.w3.org/2000/svg'
width={96}
height={96}
viewBox='0 0 12 12'
{...props}
>
<path
fill='currentColor'
d='M2.22 7.53a.75.75 0 0 0 1.06 0L6 4.81l2.72 2.72a.75.75 0 0 0 1.06-1.06L6.53 3.22a.75.75 0 0 0-1.06 0L2.22 6.47a.75.75 0 0 0 0 1.06'
/>
</svg>
);
export {
Map,
Envelope,
@@ -362,4 +378,5 @@ export {
MapOutline,
MobileContact,
MobilePhone,
Chevron,
};

View File

@@ -22,6 +22,7 @@ import {
MapOutline,
MobileContact,
MobilePhone,
Chevron,
} from './base';
import {
@@ -73,6 +74,7 @@ const Icons = Object.assign(
MapOutline,
MobileContact,
MobilePhone,
Chevron,
},
{
GridBook,

View File

@@ -3,3 +3,4 @@ export * from './footer';
export * from './breadcrumbs';
export * from './mobile-callback';
export * from './sidebar';
export * from './scroll-to-top';

View File

@@ -0,0 +1 @@
export * from './ui';

View File

@@ -0,0 +1,35 @@
.Scroll {
position: fixed;
right: rem(20px);
bottom: rem(50px);
width: rem(64px);
height: rem(64px);
border-radius: 15%;
border: none;
cursor: pointer;
background: $color-green;
color: $color-white;
font-size: rem(22px);
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: translateY(20px);
pointer-events: none;
transition: opacity 0.3s ease, transform 0.3s ease;
&.Visible {
opacity: 1;
transform: translateY(0);
pointer-events: all;
}
&:hover {
background: $color-green-hover;
}
}

View File

@@ -0,0 +1,38 @@
'use client';
import s from './styles.module.scss';
import { useEffect, useState } from 'react';
import clsx from 'clsx';
import { Icons } from '@/shared/ui';
function ScrollToTop() {
const [visible, setVisible] = useState(false);
useEffect(() => {
const onScroll = () => {
setVisible(window.scrollY > 300);
};
window.addEventListener('scroll', onScroll);
return () => window.removeEventListener('scroll', onScroll);
}, []);
const scrollToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth',
});
};
return (
<button
className={clsx(s.Scroll, visible && s.Visible)}
onClick={scrollToTop}
aria-label='Переместить наверх'
>
<Icons.Chevron />
</button>
);
}
export { ScrollToTop };