Skip to content

Commit 7ca0e04

Browse files
Lisofffaalsakhaev
authored andcommitted
fix: update animation to home page
1 parent b7d0780 commit 7ca0e04

File tree

6 files changed

+278
-137
lines changed

6 files changed

+278
-137
lines changed

website/src/components/Header/Header.module.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
align-items: center;
77
justify-content: space-between;
88
padding: 0.9375rem 1.25rem;
9+
overflow: hidden
910
}
1011

1112
.logoLink:hover img {
Lines changed: 167 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use client';
2+
13
import Link from 'next/link';
24
import styles from './Header.module.scss';
35
import cn from 'classnames';
@@ -6,7 +8,7 @@ import { ThemeImage } from '../ThemeImage';
68
import { FC, useEffect, useRef, useState } from 'react';
79
import { usePathname } from 'next/navigation';
810
import { Button } from '../Button';
9-
import gsap from 'gsap'
11+
import gsap from 'gsap';
1012

1113
const menuItems = [
1214
{
@@ -23,20 +25,107 @@ export interface HeaderProps {
2325
setModalOpen: (x: boolean) => void;
2426
}
2527

26-
export const Header:FC<HeaderProps>=({ setModalOpen }) =>{
28+
export const Header: FC<HeaderProps> = ({ setModalOpen }) => {
2729
const { resolvedTheme, setTheme } = useTheme();
2830
const pathname = usePathname();
2931
const [isMobileMenu, setMobileMenu] = useState(false);
3032
const headerRef = useRef<HTMLDivElement>(null);
31-
const logoRef = useRef<HTMLAnchorElement>(null);
32-
const navLinksRef = useRef<HTMLDivElement>(null);
33-
const themeSwitcherRef = useRef<HTMLDivElement>(null);
34-
const buttonRef = useRef<HTMLDivElement>(null);
33+
const timelineRef = useRef<gsap.core.Timeline | null>(null);
34+
const mobileMenuRef = useRef<HTMLDivElement>(null);
3535

3636
const toggleDarkMode = () => {
3737
setTheme(resolvedTheme === 'dark' ? 'light' : 'dark');
3838
};
3939

40+
useEffect(() => {
41+
if (typeof window === 'undefined' || window.innerWidth < 1024 || !headerRef.current) return;
42+
43+
const logo = headerRef.current.querySelector(`.${styles.logoLink}`);
44+
const navLinks = Array.from(headerRef.current.querySelectorAll(`.${styles.navLinks} a`));
45+
const themeSwitcher = headerRef.current.querySelector(`.${styles.themeSwitcher}`);
46+
const button = headerRef.current.querySelector(`.${styles.mvmButton}`);
47+
48+
const animatableElements: gsap.TweenTarget[] = [];
49+
50+
if (logo) animatableElements.push(logo);
51+
animatableElements.push(...navLinks);
52+
if (themeSwitcher) animatableElements.push(themeSwitcher);
53+
if (button) animatableElements.push(button);
54+
55+
timelineRef.current = gsap.timeline()
56+
.fromTo(logo,
57+
{ opacity: 0, x: -30 },
58+
{ opacity: 1, x: 0, duration: 0.6, ease: 'power3.out' }
59+
)
60+
.fromTo(navLinks,
61+
{ opacity: 0, y: 15 },
62+
{
63+
opacity: 1,
64+
y: 0,
65+
duration: 0.5,
66+
stagger: 0.1,
67+
ease: 'back.out(1.2)'
68+
},
69+
'-=0.4'
70+
);
71+
72+
if (themeSwitcher && button) {
73+
timelineRef.current
74+
.fromTo([themeSwitcher, button],
75+
{ opacity: 0, scale: 0.8 },
76+
{
77+
opacity: 1,
78+
scale: 1,
79+
duration: 0.4,
80+
stagger: 0.1,
81+
ease: 'elastic.out(1, 0.5)'
82+
},
83+
'-=0.3'
84+
);
85+
}
86+
87+
return () => {
88+
timelineRef.current?.kill();
89+
};
90+
}, []);
91+
92+
useEffect(() => {
93+
if (typeof window === 'undefined' || !mobileMenuRef.current) return;
94+
95+
if (isMobileMenu) {
96+
gsap.fromTo(mobileMenuRef.current,
97+
{ opacity: 0, y: -20 },
98+
{
99+
opacity: 1,
100+
y: 0,
101+
duration: 0.3,
102+
ease: 'power2.out'
103+
}
104+
);
105+
106+
gsap.fromTo(mobileMenuRef.current.querySelectorAll('a'),
107+
{ opacity: 0, y: 10 },
108+
{
109+
opacity: 1,
110+
y: 0,
111+
duration: 0.4,
112+
stagger: 0.08,
113+
ease: 'back.out(1.2)',
114+
delay: 0.2
115+
}
116+
);
117+
} else {
118+
gsap.to(mobileMenuRef.current,
119+
{
120+
opacity: 0,
121+
y: -20,
122+
duration: 0.2,
123+
ease: 'power2.in'
124+
}
125+
);
126+
}
127+
}, [isMobileMenu]);
128+
40129
useEffect(() => {
41130
const updateDimensions = () => {
42131
if (typeof window !== 'undefined' && window.innerWidth >= 1025) {
@@ -50,36 +139,12 @@ export const Header:FC<HeaderProps>=({ setModalOpen }) =>{
50139
return () => window.removeEventListener('resize', updateDimensions);
51140
}, []);
52141

53-
useEffect(() => {
54-
if (typeof window === 'undefined' || window.innerWidth < 1024) return;
55-
56-
const elements = [
57-
logoRef.current,
58-
navLinksRef.current,
59-
themeSwitcherRef.current,
60-
buttonRef.current
61-
].filter(Boolean) as HTMLElement[];
62-
63-
gsap.set(elements, { opacity: 0, y: 40 });
64-
65-
gsap.to(elements, {
66-
opacity: 1,
67-
y: 0,
68-
duration: 0.8,
69-
stagger: 0.15,
70-
ease: 'power2.in',
71-
delay: 0.3
72-
});
73-
74-
}, []);
75-
76142
return (
77143
<div className={styles.wrapper} ref={headerRef}>
78144
<Link
79145
prefetch={false}
80146
className={cn(styles.linkHover, styles.logoLink)}
81147
href='/'
82-
ref={logoRef}
83148
>
84149
<ThemeImage
85150
width={178}
@@ -90,7 +155,7 @@ export const Header:FC<HeaderProps>=({ setModalOpen }) =>{
90155
/>
91156
</Link>
92157

93-
<div className={styles.navLinks} ref={navLinksRef}>
158+
<div className={styles.navLinks}>
94159
{menuItems.map((menuItem, i) => (
95160
<Link prefetch={false} key={i} href={menuItem.path}>
96161
<div
@@ -104,7 +169,7 @@ export const Header:FC<HeaderProps>=({ setModalOpen }) =>{
104169
))}
105170
</div>
106171

107-
<div className={styles.themeSwitcher} onClick={toggleDarkMode} ref={themeSwitcherRef}>
172+
<div className={styles.themeSwitcher} onClick={toggleDarkMode}>
108173
<ThemeImage
109174
width={34}
110175
height={34}
@@ -113,96 +178,91 @@ export const Header:FC<HeaderProps>=({ setModalOpen }) =>{
113178
/>
114179
</div>
115180

116-
117-
<Button
118-
onClick={() => setModalOpen(true)}
119-
classNames={styles.mvmButton}
120-
text='MWM'
121-
isPrimary
122-
ref={buttonRef}
123-
/>
124-
181+
<Button
182+
onClick={() => setModalOpen(true)}
183+
classNames={styles.mvmButton}
184+
text='MWM'
185+
isPrimary
186+
/>
125187

126188
<div
127189
onClick={() => setMobileMenu(!isMobileMenu)}
128190
className={styles.burger}
129191
>
130-
<div className={styles.burgerLines}></div>
192+
<div className={isMobileMenu ? styles.burgerLinesActive : styles.burgerLines}></div>
131193
</div>
132194

133-
{isMobileMenu && (
134-
<div className={styles.mobileMenu}>
135-
<div className={styles.mobileMenuContent}>
136-
<div className={styles.mobileHeader}>
137-
<Link prefetch={false} className={styles.logoLink} href='/'>
138-
<ThemeImage
139-
width={178}
140-
height={50}
141-
alt='Dapplets'
142-
src='icons/header/logo.svg'
143-
className={styles.logoImage}
144-
/>
145-
</Link>
146-
<div className={styles.themeSwitcher} onClick={toggleDarkMode}>
147-
<ThemeImage
148-
width={34}
149-
height={34}
150-
alt='darkMode'
151-
src='icons/header/theme-switcher.svg'
152-
/>
153-
</div>
154-
<div
155-
onClick={() => setMobileMenu(!isMobileMenu)}
156-
className={styles.burger}
157-
>
158-
<div className={styles.burgerLinesActive}></div>
159-
</div>
195+
<div className={styles.mobileMenu} ref={mobileMenuRef} style={{ display: isMobileMenu ? 'block' : 'none' }}>
196+
<div className={styles.mobileMenuContent}>
197+
<div className={styles.mobileHeader}>
198+
<Link prefetch={false} className={styles.logoLink} href='/'>
199+
<ThemeImage
200+
width={178}
201+
height={50}
202+
alt='Dapplets'
203+
src='icons/header/logo.svg'
204+
className={styles.logoImage}
205+
/>
206+
</Link>
207+
<div className={styles.themeSwitcher} onClick={toggleDarkMode}>
208+
<ThemeImage
209+
width={34}
210+
height={34}
211+
alt='darkMode'
212+
src='icons/header/theme-switcher.svg'
213+
/>
160214
</div>
215+
<div
216+
onClick={() => setMobileMenu(!isMobileMenu)}
217+
className={styles.burger}
218+
>
219+
<div className={styles.burgerLinesActive}></div>
220+
</div>
221+
</div>
161222

162-
<div className={styles.mobileNav}>
163-
{menuItems.map((menuItem, i) => (
223+
<div className={styles.mobileNav}>
224+
{menuItems.map((menuItem, i) => (
225+
<Link
226+
prefetch={false}
227+
key={i}
228+
href={menuItem.path}
229+
onClick={() => setMobileMenu(false)}
230+
>
231+
<div
232+
className={cn(styles.linkHover, {
233+
[styles.active]: pathname === menuItem.path,
234+
})}
235+
>
236+
{menuItem.title}
237+
</div>
238+
</Link>
239+
))}
240+
</div>
241+
242+
<div className={styles.socialLinks}>
243+
{['github', 'discord', 'tg', 'medium', 'x', 'email'].map(
244+
(social) => (
164245
<Link
246+
key={social}
165247
prefetch={false}
166-
key={i}
167-
href={menuItem.path}
168-
onClick={() => setMobileMenu(false)}
248+
target='_blank'
249+
href={`#${social}`}
169250
>
170-
<div
171-
className={cn(styles.linkHover, {
172-
[styles.active]: pathname === menuItem.path,
173-
})}
174-
>
175-
{menuItem.title}
176-
</div>
251+
<ThemeImage
252+
className={styles.socialIcon}
253+
width={36}
254+
height={36}
255+
alt={social}
256+
src={`icons/footer/${social}.svg`}
257+
/>
177258
</Link>
178-
))}
179-
</div>
180-
181-
<div className={styles.socialLinks}>
182-
{['github', 'discord', 'tg', 'medium', 'x', 'email'].map(
183-
(social) => (
184-
<Link
185-
key={social}
186-
prefetch={false}
187-
target='_blank'
188-
href={`#${social}`}
189-
>
190-
<ThemeImage
191-
className={styles.socialIcon}
192-
width={36}
193-
height={36}
194-
alt={social}
195-
src={`icons/footer/${social}.svg`}
196-
/>
197-
</Link>
198-
)
199-
)}
200-
</div>
259+
)
260+
)}
201261
</div>
202262
</div>
203-
)}
263+
</div>
204264
</div>
205265
);
206-
}
266+
};
207267

208-
export default Header
268+
export default Header;

website/src/components/HomePage/ExamplesSection.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const ExamplesSection = () => {
4141
defaults: { duration: 0.8, ease: 'power2.in' }
4242
});
4343

44-
tl.to(items[0], { x: 0, opacity: 1, delay: 0.3 })
44+
tl.to(items[0], { x: 0, opacity: 1, delay: 0.1 })
4545
.to(items[1], { y: 0, opacity: 1 }, '-=0.6')
4646
.to(items[2], { x: 0, opacity: 1 }, '-=0.6');
4747

website/src/components/HomePage/GetStartedSection.module.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,16 @@
77
max-width: 75rem;
88
margin: 0 auto;
99
gap: 2.5rem;
10+
will-change: transform, opacity;
1011
}
1112

1213
.container {
1314
display: flex;
1415
flex-direction: column;
1516
max-width: 18.4375rem;
17+
transform: translateY(20px);
18+
opacity: 0;
19+
transition: none !important;
1620
}
1721

1822
.title {

0 commit comments

Comments
 (0)