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

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 };