Skip to content

Commit 7a05e33

Browse files
Surjit Kumar SahooSurjit Kumar Sahoo
authored andcommitted
revamp landing page
1 parent 3b3d583 commit 7a05e33

7 files changed

Lines changed: 315 additions & 47 deletions

File tree

src/components/reactLogo/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './reactLogo';
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
.container {
2+
/* React's brand color 👇 */
3+
/* --logo-color: #61dafb; */
4+
--logo-color: #56a5ba;
5+
--electron-color: #53ffd1;
6+
--trail-color: var(--electron-color);
7+
--trail-width: 4;
8+
display: flex;
9+
justify-content: center;
10+
align-items: center;
11+
height: 100%;
12+
}
13+
14+
.ellipses {
15+
stroke: var(--logo-color);
16+
stroke-width: 3;
17+
fill: none;
18+
}
19+
20+
.nucleusBulb {
21+
/* Glowing bulb effect for the nucleus */
22+
filter: drop-shadow(0 0 32px #fff) drop-shadow(0 0 64px var(--logo-color)) drop-shadow(0 0 96px var(--logo-color));
23+
}
24+
25+
.electron {
26+
/* Use a radial gradient for the bulb effect */
27+
fill: url(#electron-bulb-gradient);
28+
/* Strong glow radiating from the center */
29+
filter: drop-shadow(0 0 16px #fff) drop-shadow(0 0 32px var(--electron-color)) drop-shadow(0 0 48px var(--electron-color));
30+
}
31+
32+
.trail {
33+
stroke: var(--trail-color);
34+
stroke-width: var(--trail-width);
35+
fill: none;
36+
filter: url(#trail-blur);
37+
opacity: 0.8;
38+
stroke-linecap: round;
39+
}
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import React, { useRef, useEffect, useState } from 'react';
2+
import clsx from 'clsx';
3+
import styles from './reactLogo.module.css';
4+
import { ReactLogoProps } from './reactLogo.types';
5+
6+
// Helper to get ellipse point by angle (radians)
7+
function getEllipsePoint(rx: number, ry: number, angle: number) {
8+
return {
9+
x: rx * Math.cos(angle),
10+
y: ry * Math.sin(angle),
11+
};
12+
}
13+
14+
// Helper to create a short arc path (SVG) from angle1 to angle2
15+
function describeArc(rx: number, ry: number, angle1: number, angle2: number) {
16+
const p1 = getEllipsePoint(rx, ry, angle1);
17+
const p2 = getEllipsePoint(rx, ry, angle2);
18+
// Large arc flag is 0 because the arc is always < 180deg
19+
return `M${p1.x},${p1.y} A${rx},${ry} 0 0,1 ${p2.x},${p2.y}`;
20+
}
21+
22+
// For each electron, define its rotation offset (in radians)
23+
const ELECTRON_OFFSETS = [0, (2 * Math.PI) / 3, (4 * Math.PI) / 3];
24+
const ELLIPSE_ROTATIONS = [0, 60, 120];
25+
26+
export const AnimatedReactLogo: React.FC<ReactLogoProps> = ({ className }) => {
27+
// Animation state for all electrons
28+
const [angle, setAngle] = useState(0); // radians
29+
const requestRef = useRef<number | undefined>(undefined);
30+
const duration = 4; // seconds for full orbit
31+
const rx = 110;
32+
const ry = 42;
33+
const electronRadius = 8;
34+
const trailLength = Math.PI / 5; // short arc (about 36deg)
35+
36+
useEffect(() => {
37+
let start: number | null = null;
38+
const animate = (timestamp: number) => {
39+
if (!start) start = timestamp;
40+
const elapsed = (timestamp - start) / 1000; // seconds
41+
// Orbit: angle from 0 to 2PI over duration
42+
const newAngle = ((elapsed % duration) / duration) * Math.PI * 2;
43+
setAngle(newAngle);
44+
requestRef.current = requestAnimationFrame(animate);
45+
};
46+
requestRef.current = requestAnimationFrame(animate);
47+
return () => requestRef.current && cancelAnimationFrame(requestRef.current);
48+
}, []);
49+
50+
// For each electron, calculate its position and trail
51+
const electrons = ELECTRON_OFFSETS.map((offset, i) => {
52+
// The ellipse is rotated, so we just rotate the group in SVG
53+
const electronAngle = angle + offset;
54+
const electronPos = getEllipsePoint(rx, ry, electronAngle);
55+
const trailStart = electronAngle - trailLength;
56+
const trailEnd = electronAngle;
57+
const trailPath = describeArc(rx, ry, trailStart, trailEnd);
58+
return {
59+
pos: electronPos,
60+
trailPath,
61+
rotation: ELLIPSE_ROTATIONS[i],
62+
};
63+
});
64+
65+
return (
66+
<div className={clsx(styles.container, className)}>
67+
<svg width='800' height='800' viewBox='-150 -150 300 300'>
68+
<defs>
69+
<filter id='glow' x='-30%' y='-30%' width='160%' height='160%'>
70+
<feGaussianBlur stdDeviation='4' result='coloredBlur' />
71+
<feMerge>
72+
<feMergeNode in='coloredBlur' />
73+
<feMergeNode in='SourceGraphic' />
74+
</feMerge>
75+
</filter>
76+
{/* Subtle blur for trail */}
77+
<filter id='trail-blur' x='-20%' y='-20%' width='140%' height='140%'>
78+
<feGaussianBlur stdDeviation='2' />
79+
</filter>
80+
{/* Gradient for trail fade-out (uses CSS variable) */}
81+
<linearGradient id='trail-gradient' x1='0%' y1='0%' x2='100%' y2='0%'>
82+
<stop offset='0%' stopColor='var(--trail-color)' stopOpacity='1' />
83+
<stop offset='100%' stopColor='var(--trail-color)' stopOpacity='0' />
84+
</linearGradient>
85+
{/* Electron bulb gradient: white center, electron color edge, transparent outer */}
86+
<radialGradient id='electron-bulb-gradient' cx='50%' cy='50%' r='50%'>
87+
<stop offset='0%' stopColor='#fff' stopOpacity='1' />
88+
<stop offset='40%' stopColor='var(--electron-color)' stopOpacity='1' />
89+
<stop offset='100%' stopColor='var(--electron-color)' stopOpacity='0' />
90+
</radialGradient>
91+
{/* Nucleus bulb gradient: very bright white center, logo color edge, transparent outer */}
92+
<radialGradient id='nucleus-bulb-gradient' cx='50%' cy='50%' r='50%'>
93+
<stop offset='0%' stopColor='#fff' stopOpacity='1' />
94+
<stop offset='30%' stopColor='#fff' stopOpacity='0.8' />
95+
<stop offset='60%' stopColor='var(--logo-color)' stopOpacity='0.7' />
96+
<stop offset='100%' stopColor='var(--logo-color)' stopOpacity='0' />
97+
</radialGradient>
98+
</defs>
99+
<g>
100+
<animateTransform attributeName='transform' type='rotate' from='0 0 0' to='360 0 0' dur='25s' repeatCount='indefinite' />
101+
102+
{/* Static ellipses and glowing nucleus bulb */}
103+
<g className={styles.ellipses}>
104+
<ellipse cx='0' cy='0' rx={rx} ry={ry} />
105+
<ellipse cx='0' cy='0' rx={rx} ry={ry} transform='rotate(60)' />
106+
<ellipse cx='0' cy='0' rx={rx} ry={ry} transform='rotate(120)' />
107+
{/* Glowing nucleus bulb */}
108+
<circle cx='0' cy='0' r='18' fill='url(#nucleus-bulb-gradient)' stroke='none' />
109+
</g>
110+
111+
{/* Animated subtle trails and electrons for all 3 */}
112+
{electrons.map((e, i) => (
113+
<g key={i} transform={`rotate(${e.rotation})`}>
114+
<path className={styles.trail} d={e.trailPath} stroke='url(#trail-gradient)' />
115+
<circle className={styles.electron} cx={e.pos.x} cy={e.pos.y} r={electronRadius} fill='url(#electron-bulb-gradient)' />
116+
</g>
117+
))}
118+
</g>
119+
</svg>
120+
</div>
121+
);
122+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export interface ReactLogoProps {
2+
className?: string;
3+
}

src/pages/index.module.css

Lines changed: 133 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@
55

66
.heroBanner {
77
padding-top: 4rem;
8-
margin-bottom: -4rem;
9-
padding-bottom: 0;
108
text-align: center;
119
position: relative;
12-
overflow: hidden;
1310
background-color: transparent;
14-
z-index: 3;
11+
}
12+
13+
.title {
14+
color: #61dafb;
15+
text-shadow: 0 0 20px #61dafb;
16+
animation: glow 2s ease-in-out infinite alternate;
17+
}
18+
19+
@keyframes glow {
20+
from {
21+
text-shadow: 0 0 10px #61dafb, 0 0 20px #61dafb, 0 0 30px #61dafb;
22+
}
23+
to {
24+
text-shadow: 0 0 20px #61dafb, 0 0 30px #61dafb, 0 0 40px #61dafb;
25+
}
1526
}
1627

1728
@media screen and (max-width: 996px) {
@@ -21,49 +32,69 @@
2132
}
2233

2334
.main {
24-
position: relative;
2535
min-height: 32rem;
2636
}
2737

28-
.mainImage {
29-
width: 100%;
30-
height: auto;
31-
display: block;
38+
.flexMain {
39+
display: flex;
40+
flex-direction: row;
41+
align-items: flex-start;
42+
justify-content: flex-end;
43+
gap: 3rem;
44+
min-height: 32rem;
45+
max-height: 75vh;
46+
max-width: 90rem;
47+
margin: 0 auto;
3248
position: relative;
33-
z-index: 1;
34-
box-shadow: 0 -4rem 4rem -8px rgba(0, 0, 0, 0.85);
3549
}
3650

37-
.bottomOverlay {
38-
position: absolute;
39-
left: 0;
40-
right: 0;
41-
bottom: 0;
42-
z-index: 2;
51+
.leftContent {
52+
flex: 1 1 0;
4353
display: flex;
4454
flex-direction: column;
4555
align-items: center;
46-
padding-bottom: 4rem;
47-
width: 100%;
48-
pointer-events: none;
56+
justify-content: center;
57+
max-width: 45rem;
58+
margin-left: 10rem;
59+
margin-top: 2rem;
60+
gap: 1.5rem;
61+
z-index: 2;
62+
position: absolute;
63+
left: 0;
64+
top: 7rem;
4965
}
5066

51-
.description {
52-
max-width: 50rem;
53-
margin: 0 auto 1.5rem auto;
54-
position: static;
55-
left: unset;
56-
right: unset;
57-
bottom: unset;
58-
background: rgba(255, 255, 255, 0.1);
59-
backdrop-filter: blur(18px) saturate(180%);
60-
-webkit-backdrop-filter: blur(18px) saturate(180%);
67+
.logo {
68+
margin-top: -6rem;
69+
}
70+
71+
@media screen and (max-width: 996px) {
72+
.logo {
73+
display: none !important;
74+
}
75+
.leftContent {
76+
margin-left: 0;
77+
margin-top: 1.5rem;
78+
position: static;
79+
max-width: 100vw;
80+
padding: 0 0.5rem;
81+
}
82+
}
83+
84+
.descContainer {
6185
border: 1px solid rgba(255, 255, 255, 0.14);
62-
border-radius: 1rem;
86+
margin: 0 auto 1.5rem auto;
87+
max-width: 50rem;
6388
padding: 1.25rem 2rem;
64-
box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
65-
z-index: 3;
66-
pointer-events: auto;
89+
}
90+
91+
.description {
92+
font-size: 1.1rem;
93+
font-weight: 500;
94+
text-indent: 1.2rem;
95+
text-align: justify;
96+
color: white;
97+
text-shadow: 0 1px 6px rgba(0, 0, 0, 0.28);
6798
}
6899

69100
.button {
@@ -95,10 +126,10 @@
95126
padding: 2px;
96127
background: linear-gradient(270deg, #ff6ec4, #7873f5, #1fd1f9, #ff6ec4);
97128
background-size: 600% 600%;
98-
animation: animated-border 4s linear infinite;
129+
animation: btn-animation 4s linear infinite;
99130
}
100131

101-
@keyframes animated-border {
132+
@keyframes btn-animation {
102133
0% {
103134
background-position: 0% 50%;
104135
}
@@ -117,6 +148,58 @@
117148
border-radius: 0.5rem;
118149
}
119150

151+
@keyframes cardGradientMove {
152+
0% {
153+
background-position: 0% 50%;
154+
}
155+
50% {
156+
background-position: 100% 50%;
157+
}
158+
100% {
159+
background-position: 0% 50%;
160+
}
161+
}
162+
163+
.animatedCard {
164+
border-radius: 0.75rem;
165+
background: linear-gradient(135deg, #ff6ec4, #7873f5, #10677b, #ff6ec4 90%);
166+
background-size: 300% 300%;
167+
animation: cardBgAnimation 6s ease-in-out infinite;
168+
box-shadow: 0 4px 32px 0 rgba(31, 209, 249, 0.18);
169+
position: relative;
170+
opacity: 0.85;
171+
backdrop-filter: blur(16px);
172+
-webkit-backdrop-filter: blur(16px);
173+
}
174+
175+
.animatedCard::after {
176+
content: '';
177+
position: absolute;
178+
inset: 10px;
179+
border-radius: 0.5rem;
180+
background: rgba(255, 255, 255, 0.12);
181+
z-index: 1;
182+
backdrop-filter: blur(8px);
183+
-webkit-backdrop-filter: blur(8px);
184+
}
185+
186+
.animatedCard > * {
187+
position: relative;
188+
z-index: 2;
189+
}
190+
191+
@keyframes cardBgAnimation {
192+
0% {
193+
background-position: 0% 50%;
194+
}
195+
50% {
196+
background-position: 100% 50%;
197+
}
198+
100% {
199+
background-position: 0% 50%;
200+
}
201+
}
202+
120203
@media screen and (max-width: 996px) {
121204
.main {
122205
min-height: 20rem;
@@ -128,4 +211,18 @@
128211
padding: 1rem 1rem;
129212
font-size: 0.98rem;
130213
}
214+
.flexMain {
215+
flex-direction: column;
216+
gap: 1.5rem;
217+
min-height: 20rem;
218+
}
219+
.leftContent,
220+
.rightImage {
221+
width: 100%;
222+
justify-content: center;
223+
align-items: center;
224+
}
225+
.animatedCard {
226+
padding: 1.2rem 1rem 1rem 1rem;
227+
}
131228
}

0 commit comments

Comments
 (0)