Skip to content

Commit f61dcd6

Browse files
committed
Add animated hero visuals and floating formulas
Introduce animated hero background assets and floating chemical motifs. Adds extensive CSS for glowing orbs, dot grid, drifting formulas, molecular bond SVG styles, and fade-in animations. Implements a FloatingFormulas component (formulas list and bond definitions) and integrates it into the HeroSection, replacing the previous static decorative blobs and adding staggered fade-in on hero content and a dark-theme background tweak.
1 parent b550e9d commit f61dcd6

File tree

2 files changed

+250
-28
lines changed

2 files changed

+250
-28
lines changed

src/css/custom.css

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,142 @@ article h2 {
907907
-webkit-text-fill-color: transparent;
908908
}
909909

910+
/* ── Hero background ── */
911+
.hero-orb {
912+
position: absolute;
913+
border-radius: 50%;
914+
filter: blur(100px);
915+
opacity: 0.4;
916+
}
917+
918+
.hero-orb--1 {
919+
top: -15%;
920+
right: -8%;
921+
width: 500px;
922+
height: 500px;
923+
background: radial-gradient(circle, rgba(249, 115, 22, 0.15), transparent 70%);
924+
animation: hero-float-1 8s ease-in-out infinite;
925+
}
926+
927+
.hero-orb--2 {
928+
bottom: -20%;
929+
left: -5%;
930+
width: 400px;
931+
height: 400px;
932+
background: radial-gradient(circle, rgba(194, 65, 12, 0.1), transparent 70%);
933+
animation: hero-float-2 10s ease-in-out infinite;
934+
}
935+
936+
[data-theme="dark"] .hero-orb--1 {
937+
background: radial-gradient(circle, rgba(249, 115, 22, 0.3), transparent 70%);
938+
}
939+
940+
[data-theme="dark"] .hero-orb--2 {
941+
background: radial-gradient(circle, rgba(194, 65, 12, 0.2), transparent 70%);
942+
}
943+
944+
@keyframes hero-float-1 {
945+
0%, 100% { transform: translate(0, 0) scale(1); }
946+
50% { transform: translate(-30px, 20px) scale(1.05); }
947+
}
948+
949+
@keyframes hero-float-2 {
950+
0%, 100% { transform: translate(0, 0) scale(1); }
951+
50% { transform: translate(25px, -15px) scale(1.08); }
952+
}
953+
954+
/* Subtle dot grid */
955+
.hero-grid {
956+
position: absolute;
957+
inset: 0;
958+
background-image: radial-gradient(rgba(0, 0, 0, 0.04) 1px, transparent 1px);
959+
background-size: 32px 32px;
960+
}
961+
962+
[data-theme="dark"] .hero-grid {
963+
background-image: radial-gradient(rgba(255, 255, 255, 0.03) 1px, transparent 1px);
964+
}
965+
966+
/* Floating chemical formulas */
967+
.hero-formula {
968+
position: absolute;
969+
font-family: "JetBrains Mono", "Fira Code", monospace;
970+
font-weight: 700;
971+
color: #C2410C;
972+
white-space: nowrap;
973+
-webkit-user-select: none;
974+
user-select: none;
975+
will-change: transform;
976+
}
977+
978+
[data-theme="dark"] .hero-formula {
979+
color: #F97316;
980+
}
981+
982+
/* Molecular bond structures */
983+
.hero-bond {
984+
position: absolute;
985+
will-change: transform;
986+
}
987+
988+
.hero-bond-line {
989+
stroke: #C2410C;
990+
opacity: 0.6;
991+
}
992+
993+
.hero-bond-node {
994+
fill: #C2410C;
995+
opacity: 0.7;
996+
}
997+
998+
[data-theme="dark"] .hero-bond-line {
999+
stroke: #F97316;
1000+
opacity: 0.5;
1001+
}
1002+
1003+
[data-theme="dark"] .hero-bond-node {
1004+
fill: #F97316;
1005+
opacity: 0.6;
1006+
}
1007+
1008+
.hero-drift-a {
1009+
animation: hero-drift-a ease-in-out infinite;
1010+
}
1011+
1012+
.hero-drift-b {
1013+
animation: hero-drift-b ease-in-out infinite;
1014+
}
1015+
1016+
@keyframes hero-drift-a {
1017+
0% { transform: translate(0, 0) scale(1) rotate(0deg); }
1018+
25% { transform: translate(30px, -20px) scale(1.15) rotate(3deg); }
1019+
50% { transform: translate(-10px, -40px) scale(0.85) rotate(-2deg); }
1020+
75% { transform: translate(-30px, -15px) scale(1.1) rotate(2deg); }
1021+
100% { transform: translate(0, 0) scale(1) rotate(0deg); }
1022+
}
1023+
1024+
@keyframes hero-drift-b {
1025+
0% { transform: translate(0, 0) scale(1) rotate(0deg); }
1026+
25% { transform: translate(-25px, 15px) scale(0.9) rotate(-3deg); }
1027+
50% { transform: translate(15px, 35px) scale(1.2) rotate(2deg); }
1028+
75% { transform: translate(25px, 10px) scale(0.85) rotate(-1deg); }
1029+
100% { transform: translate(0, 0) scale(1) rotate(0deg); }
1030+
}
1031+
1032+
/* Fade-in-up for hero content */
1033+
.hero-fade-in {
1034+
opacity: 0;
1035+
transform: translateY(16px);
1036+
animation: hero-fade-up 0.6s ease-out forwards;
1037+
}
1038+
1039+
@keyframes hero-fade-up {
1040+
to {
1041+
opacity: 1;
1042+
transform: translateY(0);
1043+
}
1044+
}
1045+
9101046
/* ── Scroll detection script hook ── */
9111047
html {
9121048
scroll-behavior: smooth;

src/pages/index.tsx

Lines changed: 114 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,52 +107,138 @@ const community: CommunityLink[] = [
107107
},
108108
];
109109

110+
const FORMULAS = [
111+
"H\u2082O", "CO\u2082", "NaCl", "C\u2086H\u2081\u2082O\u2086", "O\u2082",
112+
"NH\u2083", "CH\u2084", "H\u2082SO\u2084", "Fe\u2082O\u2083", "CaCO\u2083",
113+
"C\u2082H\u2085OH", "HCl", "NaOH", "KMnO\u2084", "N\u2082",
114+
"SiO\u2082", "Al\u2082O\u2083", "MgO", "ZnSO\u2084", "Cu",
115+
];
116+
117+
const FORMULA_ITEMS = FORMULAS.map((f, i) => ({
118+
text: f,
119+
top: `${5 + ((i * 37) % 85)}%`,
120+
left: `${2 + ((i * 53) % 92)}%`,
121+
size: 0.85 + (i % 4) * 0.3,
122+
duration: 14 + (i % 7) * 4,
123+
delay: (i % 5) * -3,
124+
drift: i % 2 === 0 ? "hero-drift-a" : "hero-drift-b",
125+
opacity: 0.25 + (i % 3) * 0.1,
126+
}));
127+
128+
/* Molecular bond structures rendered as SVG */
129+
interface Bond {
130+
top: string;
131+
left: string;
132+
size: number;
133+
duration: number;
134+
delay: number;
135+
drift: string;
136+
opacity: number;
137+
path: string;
138+
}
139+
140+
const BONDS: Bond[] = [
141+
{ top: "12%", left: "8%", size: 80, duration: 18, delay: -2, drift: "hero-drift-b", opacity: 0.35,
142+
path: "M10,40 L40,20 L70,40 M40,20 L40,5 M40,20 L25,8 M40,20 L55,8" },
143+
{ top: "25%", left: "75%", size: 100, duration: 22, delay: -5, drift: "hero-drift-a", opacity: 0.3,
144+
path: "M20,50 L50,30 L80,50 M50,30 L50,10 M20,50 L20,70 M80,50 L80,70 M50,30 L35,15 M50,30 L65,15" },
145+
{ top: "60%", left: "85%", size: 70, duration: 16, delay: -1, drift: "hero-drift-b", opacity: 0.32,
146+
path: "M15,35 L35,15 L55,35 L35,55 Z M35,15 L35,5 M55,35 L65,35" },
147+
{ top: "70%", left: "15%", size: 90, duration: 20, delay: -4, drift: "hero-drift-a", opacity: 0.3,
148+
path: "M10,45 L45,25 L80,45 M45,25 L45,5 M10,45 L10,65 M80,45 L80,65" },
149+
{ top: "8%", left: "45%", size: 60, duration: 15, delay: -3, drift: "hero-drift-b", opacity: 0.28,
150+
path: "M10,30 L30,10 L50,30 M30,10 L30,0 M10,30 L0,40 M50,30 L60,40" },
151+
{ top: "45%", left: "5%", size: 75, duration: 19, delay: -6, drift: "hero-drift-a", opacity: 0.3,
152+
path: "M20,40 L40,20 L60,40 M40,20 L40,5 M20,40 L5,50 M60,40 L75,50 M40,5 L30,0 M40,5 L50,0" },
153+
{ top: "80%", left: "55%", size: 85, duration: 21, delay: -2, drift: "hero-drift-b", opacity: 0.28,
154+
path: "M15,45 L42,20 L70,45 M42,20 L42,5 M15,45 L30,60 M70,45 L55,60" },
155+
{ top: "35%", left: "92%", size: 65, duration: 17, delay: -5, drift: "hero-drift-a", opacity: 0.10,
156+
path: "M10,35 L32,15 L55,35 M32,15 L32,3 M10,35 L10,50" },
157+
];
158+
159+
function FloatingFormulas(): JSX.Element {
160+
return (
161+
<div className="absolute inset-0 pointer-events-none overflow-hidden" aria-hidden="true">
162+
{/* Ambient glow */}
163+
<div className="hero-orb hero-orb--1" />
164+
<div className="hero-orb hero-orb--2" />
165+
{/* Dot grid */}
166+
<div className="hero-grid" />
167+
{/* Molecular bonds */}
168+
{BONDS.map((b, i) => (
169+
<svg
170+
key={`bond-${i}`}
171+
className={`hero-bond ${b.drift}`}
172+
width={b.size}
173+
height={b.size}
174+
viewBox={`0 0 ${b.size} ${b.size}`}
175+
style={{
176+
top: b.top,
177+
left: b.left,
178+
animationDuration: `${b.duration}s`,
179+
animationDelay: `${b.delay}s`,
180+
opacity: b.opacity,
181+
}}
182+
>
183+
<path d={b.path} fill="none" className="hero-bond-line" strokeWidth="1.5" strokeLinecap="round" />
184+
{/* Atom nodes at path endpoints */}
185+
{b.path.match(/[ML]\s*(\d+),(\d+)/g)?.map((m, j) => {
186+
const coords = m.match(/(\d+),(\d+)/);
187+
if (!coords) return null;
188+
return <circle key={j} cx={coords[1]} cy={coords[2]} r="3" className="hero-bond-node" />;
189+
})}
190+
</svg>
191+
))}
192+
{/* Formulas */}
193+
{FORMULA_ITEMS.map((item, i) => (
194+
<span
195+
key={`f-${i}`}
196+
className={`hero-formula ${item.drift}`}
197+
style={{
198+
top: item.top,
199+
left: item.left,
200+
fontSize: `${item.size}rem`,
201+
animationDuration: `${item.duration}s`,
202+
animationDelay: `${item.delay}s`,
203+
opacity: item.opacity,
204+
}}
205+
>
206+
{item.text}
207+
</span>
208+
))}
209+
</div>
210+
);
211+
}
212+
110213
function HeroSection(): JSX.Element {
111214
return (
112-
<section className="home-section relative overflow-hidden bg-white py-24 px-6 dark:bg-background">
113-
{/* Decorative blobs */}
114-
<div
115-
className="absolute pointer-events-none"
116-
style={{
117-
top: "-20%",
118-
right: "-10%",
119-
width: "40%",
120-
height: "80%",
121-
background: "radial-gradient(circle, rgba(249,115,22,0.08) 0%, transparent 70%)",
122-
}}
123-
/>
124-
<div
125-
className="absolute pointer-events-none"
126-
style={{
127-
bottom: "-10%",
128-
left: "-5%",
129-
width: "30%",
130-
height: "60%",
131-
background: "radial-gradient(circle, rgba(194,65,12,0.06) 0%, transparent 70%)",
132-
}}
133-
/>
215+
<section className="home-section relative overflow-hidden bg-white dark:bg-slate-950 py-28 px-6">
216+
<FloatingFormulas />
134217

135-
<div className="home-section-inner relative">
136-
<Badge variant="default" className="mb-6">
218+
<div className="home-section-inner relative z-10">
219+
<Badge variant="default" className="mb-6 hero-fade-in">
137220
<span className="w-1.5 h-1.5 rounded-full bg-brand" />
138221
Open Source
139222
</Badge>
140223

141224
<h1
142-
className="font-extrabold text-foreground tracking-tight leading-tight mb-4"
143-
style={{ fontSize: "clamp(2.5rem, 5vw, 4rem)" }}
225+
className="hero-fade-in font-extrabold text-foreground tracking-tight leading-tight mb-4"
226+
style={{ fontSize: "clamp(2.5rem, 5vw, 4rem)", animationDelay: "0.1s" }}
144227
>
145228
Documentation for{" "}
146229
<span className="gradient-text">Viglet</span>{" "}
147230
Products
148231
</h1>
149232

150-
<p className="text-lg text-muted-foreground max-w-xl mx-auto mb-10 leading-relaxed">
233+
<p
234+
className="hero-fade-in text-lg text-muted-foreground max-w-xl mx-auto mb-10 leading-relaxed"
235+
style={{ animationDelay: "0.2s" }}
236+
>
151237
Explore guides, API references, and tutorials for Turing ES,
152238
Shio CMS, and Dumont DEP.
153239
</p>
154240

155-
<div className="flex gap-3 justify-center flex-wrap">
241+
<div className="hero-fade-in flex gap-3 justify-center flex-wrap" style={{ animationDelay: "0.3s" }}>
156242
<Button asChild>
157243
<Link to="/#products">Get Started</Link>
158244
</Button>

0 commit comments

Comments
 (0)