Skip to content

Commit 69955eb

Browse files
authored
Merge pull request #426 from CodebilityDev/deo/onboarding
wip: continue onboarding work - Fix hero flicker. remove other sections
2 parents da74790 + e7088e3 commit 69955eb

3 files changed

Lines changed: 179 additions & 107 deletions

File tree

‎apps/codebility/app/auth/onboarding/_components/Expect/ExpectSection.tsx‎

Lines changed: 48 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,122 +7,132 @@ const items = [
77
{
88
number: "01",
99
text: "A self-driven attitude — you’re responsible for your own learning",
10-
color: "bg-cyan-500",
10+
color: "bg-cyan-400",
1111
},
1212
{
1313
number: "02",
1414
text: "Professionalism in communication, time management, and behavior",
15-
color: "bg-emerald-500",
15+
color: "bg-emerald-400",
1616
},
1717
{
1818
number: "03",
1919
text: "Active participation in tasks, meetings, and community discussions",
20-
color: "bg-rose-500",
20+
color: "bg-rose-400",
2121
},
2222
{
2323
number: "04",
2424
text: "Respect for team members, deadlines, and project goals",
25-
color: "bg-indigo-500",
25+
color: "bg-indigo-400",
2626
},
2727
{
2828
number: "05",
2929
text: "Willingness to grow from feedback and mistakes",
30-
color: "bg-amber-500",
30+
color: "bg-amber-400",
3131
},
3232
{
3333
number: "06",
3434
text: "Transparency — especially if you’re unavailable, struggling, or need support",
35-
color: "bg-fuchsia-500",
35+
color: "bg-fuchsia-400",
3636
},
3737
];
3838

39-
export default function ExpectSection() {
39+
export default function ExpectSectionLight() {
4040
const lineRef = useRef<HTMLDivElement>(null);
41+
const sectionRef = useRef<HTMLElement>(null);
4142

4243
useEffect(() => {
44+
const target = sectionRef.current;
45+
const line = lineRef.current;
46+
if (!target || !line) return;
47+
4348
const observer = new IntersectionObserver(
44-
([entry]) => {
45-
if (entry?.isIntersecting && lineRef.current) {
46-
lineRef.current.style.height = "100%";
47-
}
49+
(entries) => {
50+
const [entry] = entries;
51+
if (entry?.isIntersecting) line.style.height = "100%";
4852
},
49-
{ threshold: 0.2 },
53+
{ threshold: 0.25 },
5054
);
5155

52-
if (lineRef.current) observer.observe(lineRef.current);
56+
observer.observe(target);
5357
return () => observer.disconnect();
5458
}, []);
5559

5660
return (
57-
<section className="relative flex w-full items-center justify-center overflow-hidden bg-gradient-to-br from-zinc-900 via-zinc-950 to-black px-6 py-24 text-white lg:min-h-screen">
58-
{/* soft pastel glows for light motif */}
59-
<div className="pointer-events-none absolute inset-0 bg-[radial-gradient(900px_520px_at_85%_20%,rgba(236,72,153,0.15),transparent_60%),radial-gradient(800px_480px_at_10%_80%,rgba(20,184,166,0.15),transparent_60%)]" />
61+
<section
62+
ref={sectionRef}
63+
className="relative flex w-full items-center justify-center overflow-hidden bg-white px-6 py-24 text-zinc-800 lg:min-h-screen"
64+
>
65+
{/* very soft background accents */}
66+
<div className="pointer-events-none absolute inset-0 opacity-70">
67+
<div className="absolute -right-24 -top-24 h-80 w-80 rounded-full bg-cyan-100 blur-2xl" />
68+
<div className="absolute -bottom-24 -left-24 h-80 w-80 rounded-full bg-pink-100 blur-2xl" />
69+
</div>
6070

6171
<div className="w-full max-w-5xl">
6272
{/* Heading */}
6373
<motion.h2
64-
initial={{ opacity: 0, y: 30 }}
74+
initial={{ opacity: 0, y: 24 }}
6575
whileInView={{ opacity: 1, y: 0 }}
66-
transition={{ duration: 0.8 }}
76+
transition={{ duration: 0.6 }}
6777
viewport={{ once: true }}
68-
className="mb-20 text-center text-4xl font-bold leading-tight text-purple-500 md:text-5xl"
78+
className="mb-14 text-center text-3xl font-extrabold tracking-tight"
6979
>
7080
What we expect from{" "}
71-
<span className="bg-gradient-to-r from-pink-400 via-purple-500 to-teal-600 bg-clip-text text-[3.5rem] font-black text-transparent drop-shadow-lg md:text-[4.5rem]">
81+
<span className="bg-gradient-to-r from-purple-600 via-fuchsia-600 to-cyan-600 bg-clip-text font-extrabold text-transparent">
7282
YOU
7383
</span>
7484
</motion.h2>
7585

7686
{/* Timeline */}
7787
<div className="relative">
78-
{/* Glowing vertical line */}
88+
{/* Subtle vertical line */}
7989
<motion.div
8090
ref={lineRef}
8191
initial={{ height: 0 }}
8292
animate={{ height: "100%" }}
83-
transition={{ duration: 1.2, ease: "easeInOut" }}
84-
className="absolute left-1/2 hidden w-[5px] -translate-x-1/2 animate-pulse bg-cyan-400 shadow-[0_0_12px_3px_rgba(34,211,238,0.7)] md:block"
93+
transition={{ duration: 0.9, ease: "easeInOut" }}
94+
className="absolute left-1/2 hidden w-px -translate-x-1/2 bg-zinc-200 md:block"
8595
/>
8696

8797
{/* Steps */}
88-
<div className="flex flex-col gap-14">
98+
<div className="flex flex-col gap-12">
8999
{items.map((item, i) => {
90100
const isLeft = i % 2 === 0;
91101

92102
return (
93103
<motion.div
94-
key={i}
95-
initial={{ opacity: 0, y: 30 }}
104+
key={item.number}
105+
initial={{ opacity: 0, y: 18 }}
96106
whileInView={{ opacity: 1, y: 0 }}
97-
transition={{ duration: 0.5, delay: i * 0.1 }}
98-
viewport={{ once: true }}
107+
transition={{ duration: 0.45, delay: i * 0.05 }}
108+
viewport={{ once: true, amount: 0.3 }}
99109
className={`relative flex flex-col items-center md:flex-row ${
100110
isLeft ? "md:justify-start" : "md:justify-end"
101111
}`}
102112
>
103-
{/* Connector line above */}
113+
{/* Connector (super soft) */}
104114
{i !== 0 && (
105-
<div className="absolute left-1/2 top-[-24px] z-0 hidden h-full w-1 -translate-x-1/2 bg-white/20 md:block" />
115+
<div className="absolute left-1/2 top-[-18px] z-0 hidden h-full w-px -translate-x-1/2 bg-zinc-100 md:block" />
106116
)}
107117

108-
{/* Content wrapper with flex gap */}
118+
{/* Row */}
109119
<div
110-
className={`z-10 flex w-full flex-col items-center gap-4 md:w-[calc(50%-1.5rem)] md:flex-row ${
120+
className={`z-10 flex w-full flex-col items-center gap-4 md:w-[calc(50%-1rem)] md:flex-row ${
111121
isLeft
112-
? "md:order-2 md:ml-0 md:mr-auto"
113-
: "flex-row-reverse md:order-1 md:ml-auto md:mr-0"
122+
? "md:order-2 md:mr-auto"
123+
: "flex-row-reverse md:order-1 md:ml-auto"
114124
}`}
115125
>
116-
{/* Number bubble */}
126+
{/* Number badge (light, with border) */}
117127
<div
118-
className={`flex h-16 w-16 items-center justify-center rounded-full text-2xl font-bold text-white shadow-xl ${item.color}`}
128+
className={`flex h-14 w-14 items-center justify-center rounded-full text-lg font-bold text-white ${item.color} shadow-sm ring-1 ring-white/60`}
119129
>
120130
{item.number}
121131
</div>
122132

123-
{/* Card */}
133+
{/* Card (light, subtle shadow) */}
124134
<div
125-
className={`mt-4 w-full rounded-xl bg-white/5 p-5 text-center text-sm md:mt-0 lg:text-left ${
135+
className={`mt-2 w-full rounded-xl border border-zinc-200 bg-white/80 p-5 text-center text-sm leading-relaxed shadow-sm backdrop-blur-sm md:mt-0 ${
126136
isLeft ? "md:text-left" : "md:text-right"
127137
}`}
128138
>
Lines changed: 127 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
"use client";
22

3-
import { useEffect, useState } from "react";
4-
import { motion, useMotionValue, useTransform } from "framer-motion";
3+
import { useMemo } from "react";
4+
import { motion, useReducedMotion } from "framer-motion";
55

66
const codeTags = [
77
"const",
@@ -15,80 +15,142 @@ const codeTags = [
1515
"=>",
1616
];
1717

18+
/** Seeded RNG so positions/timings are stable */
19+
function mulberry32(seed: number) {
20+
let t = seed >>> 0;
21+
return () => {
22+
t += 0x6d2b79f5;
23+
let r = Math.imul(t ^ (t >>> 15), 1 | t);
24+
r ^= r + Math.imul(r ^ (r >>> 7), 61 | r);
25+
return ((r ^ (r >>> 14)) >>> 0) / 4294967296;
26+
};
27+
}
28+
type Pos = { top: number; left: number };
29+
type CornerIndex = 0 | 1 | 2 | 3;
30+
31+
function placeAwayFromCenter(rand: () => number): Pos {
32+
let top = rand() * 90 + 5;
33+
let left = rand() * 90 + 5;
34+
35+
const inCenter = top > 30 && top < 70 && left > 30 && left < 70;
36+
if (inCenter) {
37+
const cornerIndex = Math.min(
38+
3,
39+
Math.max(0, Math.floor(rand() * 4)),
40+
) as CornerIndex;
41+
42+
// Tuple of exactly 4 positions
43+
const ranges: readonly [Pos, Pos, Pos, Pos] = [
44+
{ top: rand() * 25 + 5, left: rand() * 25 + 5 }, // TL
45+
{ top: rand() * 25 + 5, left: rand() * 25 + 75 }, // TR
46+
{ top: rand() * 25 + 75, left: rand() * 25 + 5 }, // BL
47+
{ top: rand() * 25 + 75, left: rand() * 25 + 75 }, // BR
48+
] as const;
49+
50+
const chosen: Pos = ranges[cornerIndex]; // always defined with tuple indexing
51+
top = chosen.top;
52+
left = chosen.left;
53+
}
54+
55+
return { top, left };
56+
}
1857
export function FloatingCodeTags() {
19-
const [windowSize, setWindowSize] = useState({ width: 1000, height: 800 });
58+
const reduceMotion = useReducedMotion();
2059

21-
const mouseX = useMotionValue(0);
22-
const mouseY = useMotionValue(0);
60+
const configs = useMemo(() => {
61+
return codeTags.map((tag, i) => {
62+
const seed =
63+
Array.from((tag + i).toString()).reduce(
64+
(a, c) => a + c.charCodeAt(0),
65+
0,
66+
) +
67+
i * 99991;
68+
const rnd = mulberry32(seed);
2369

24-
useEffect(() => {
25-
if (typeof window === "undefined") return;
70+
const { top, left } = placeAwayFromCenter(rnd);
71+
const floatDuration = 10 + Math.floor(rnd() * 6); // 10–15s
72+
const floatDelay = rnd() * 2; // 0–2s
73+
const floatAmplitude = 8 + rnd() * 6; // 8–14px
2674

27-
setWindowSize({ width: window.innerWidth, height: window.innerHeight });
75+
// add a very subtle horizontal drift to avoid uniformity (no parallax)
76+
const drift = 4 + rnd() * 4; // 4–8px
77+
const driftDuration = 12 + Math.floor(rnd() * 6); // 12–17s
78+
const driftDelay = rnd() * 2;
2879

29-
const handleMouseMove = (e: MouseEvent) => {
30-
mouseX.set(e.clientX);
31-
mouseY.set(e.clientY);
32-
};
33-
window.addEventListener("mousemove", handleMouseMove);
34-
return () => window.removeEventListener("mousemove", handleMouseMove);
35-
}, [mouseX, mouseY]);
80+
return {
81+
key: `${tag}-${i}`,
82+
tag,
83+
topPct: top,
84+
leftPct: left,
85+
floatDuration,
86+
floatDelay,
87+
floatAmplitude,
88+
drift,
89+
driftDuration,
90+
driftDelay,
91+
};
92+
});
93+
}, []);
3694

3795
return (
38-
<div className="pointer-events-none absolute inset-0 z-[1] overflow-hidden">
39-
{codeTags.map((tag, i) => {
40-
const x = useTransform(mouseX, [0, windowSize.width], [-8, 8]);
41-
const y = useTransform(mouseY, [0, windowSize.height], [-8, 8]);
42-
43-
// Avoid placing tags in the center area where logo/text is
44-
let top = Math.random() * 90 + 5;
45-
let left = Math.random() * 90 + 5;
46-
47-
// Keep tags away from center area (30%-70% both horizontally and vertically)
48-
if (top > 30 && top < 70 && left > 30 && left < 70) {
49-
// Randomly place in corners instead
50-
const corners = [
51-
{ top: Math.random() * 25 + 5, left: Math.random() * 25 + 5 }, // top-left
52-
{ top: Math.random() * 25 + 5, left: Math.random() * 25 + 75 }, // top-right
53-
{ top: Math.random() * 25 + 75, left: Math.random() * 25 + 5 }, // bottom-left
54-
{ top: Math.random() * 25 + 75, left: Math.random() * 25 + 75 }, // bottom-right
55-
];
56-
const corner = corners[Math.floor(Math.random() * corners.length)];
57-
if (corner) {
58-
top = corner.top;
59-
left = corner.left;
60-
}
61-
}
62-
63-
const delay = Math.random() * 2;
64-
65-
return (
96+
<div
97+
className="pointer-events-none absolute inset-0 z-[1] overflow-hidden"
98+
aria-hidden
99+
>
100+
{configs.map(
101+
({
102+
key,
103+
tag,
104+
topPct,
105+
leftPct,
106+
floatDuration,
107+
floatDelay,
108+
floatAmplitude,
109+
drift,
110+
driftDuration,
111+
driftDelay,
112+
}) => (
66113
<motion.span
67-
key={tag + i}
68-
className="absolute select-none font-mono text-xs text-white opacity-15 blur-[0.3px] lg:text-sm"
69-
style={{
70-
top: `${top}%`,
71-
left: `${left}%`,
72-
x,
73-
y,
74-
}}
75-
initial={{ opacity: 0, scale: 0.6 }}
76-
animate={{
77-
opacity: [0.1, 0.2, 0.1],
78-
scale: [0.8, 1, 0.8],
79-
y: ["0%", "-8%", "0%"],
80-
}}
81-
transition={{
82-
duration: 8 + Math.random() * 4,
83-
repeat: Infinity,
84-
delay,
85-
ease: "easeInOut",
86-
}}
114+
key={key}
115+
className="absolute select-none font-mono text-xs text-white/20 will-change-transform lg:text-sm"
116+
style={{ top: `${topPct}%`, left: `${leftPct}%` }}
117+
initial={{ opacity: 0, scale: 0.95 }}
118+
animate={
119+
reduceMotion
120+
? { opacity: 0.2, scale: 1 }
121+
: {
122+
opacity: 0.2, // steady (no flicker)
123+
scale: 1,
124+
// gentle vertical bob + slow horizontal drift
125+
translateY: [0, -floatAmplitude, 0],
126+
translateX: [0, drift, 0, -drift, 0],
127+
}
128+
}
129+
transition={
130+
reduceMotion
131+
? { opacity: { duration: 0.6, ease: "easeOut" } }
132+
: {
133+
opacity: { duration: 0.8, ease: "easeOut" },
134+
scale: { duration: 0.8, ease: "easeOut" },
135+
translateY: {
136+
duration: floatDuration,
137+
repeat: Infinity,
138+
delay: floatDelay,
139+
ease: "easeInOut",
140+
},
141+
translateX: {
142+
duration: driftDuration,
143+
repeat: Infinity,
144+
delay: driftDelay,
145+
ease: "easeInOut",
146+
},
147+
}
148+
}
87149
>
88150
{tag}
89151
</motion.span>
90-
);
91-
})}
152+
),
153+
)}
92154
</div>
93155
);
94156
}

0 commit comments

Comments
 (0)