stable state
This commit is contained in:
@@ -1,8 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useState } from "react";
|
||||
import SafeImage from "./SafeImage";
|
||||
|
||||
interface Experience {
|
||||
name: string;
|
||||
company: string;
|
||||
@@ -25,30 +24,10 @@ function formatDate(d: string) {
|
||||
}
|
||||
|
||||
function ExperienceItem({ exp, index }: { exp: Experience; index: number }) {
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const el = ref.current;
|
||||
if (!el) return;
|
||||
const obs = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry.isIntersecting) {
|
||||
setTimeout(() => el.classList.add("visible"), index * 100);
|
||||
obs.disconnect();
|
||||
}
|
||||
},
|
||||
{ threshold: 0.1 }
|
||||
);
|
||||
obs.observe(el);
|
||||
return () => obs.disconnect();
|
||||
}, [index]);
|
||||
|
||||
const isCurrent = exp.endDate === "current";
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={ref}
|
||||
className="reveal"
|
||||
style={{
|
||||
display: "grid",
|
||||
gridTemplateColumns: "120px 1px 1fr",
|
||||
@@ -146,20 +125,7 @@ function ExperienceItem({ exp, index }: { exp: Experience; index: number }) {
|
||||
}
|
||||
|
||||
export default function Experience({ experiences }: ExperienceProps) {
|
||||
const headingRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const el = headingRef.current;
|
||||
if (!el) return;
|
||||
const obs = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
if (entry.isIntersecting) { el.classList.add("visible"); obs.disconnect(); }
|
||||
},
|
||||
{ threshold: 0.1 }
|
||||
);
|
||||
obs.observe(el);
|
||||
return () => obs.disconnect();
|
||||
}, []);
|
||||
const [showAll, setShowAll] = useState(false);
|
||||
|
||||
return (
|
||||
<section
|
||||
@@ -167,7 +133,7 @@ export default function Experience({ experiences }: ExperienceProps) {
|
||||
style={{ padding: "8rem 2rem", background: "#0a0b0e" }}
|
||||
>
|
||||
<div style={{ maxWidth: "1200px", margin: "0 auto" }}>
|
||||
<div ref={headingRef} className="reveal" style={{ marginBottom: "4rem" }}>
|
||||
<div style={{ marginBottom: "4rem" }}>
|
||||
<div className="section-label" style={{ marginBottom: "0.75rem" }}>Career Path</div>
|
||||
<h2
|
||||
className="font-display"
|
||||
@@ -185,10 +151,52 @@ export default function Experience({ experiences }: ExperienceProps) {
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{experiences.map((exp, i) => (
|
||||
<ExperienceItem key={exp.name} exp={exp} index={i} />
|
||||
{(showAll ? experiences : experiences.slice(0, 2)).map((exp, i) => (
|
||||
<div
|
||||
key={exp.name}
|
||||
style={{
|
||||
opacity: 1,
|
||||
animation: "fadeUp 0.6s ease both",
|
||||
animationDelay: `${i * 100}ms`
|
||||
}}
|
||||
>
|
||||
<ExperienceItem exp={exp} index={i} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{experiences.length > 2 && (
|
||||
<div style={{ display: "flex", justifyContent: "center", marginTop: "1rem" }}>
|
||||
<button
|
||||
onClick={() => setShowAll(!showAll)}
|
||||
style={{
|
||||
fontFamily: "var(--font-jetbrains), monospace",
|
||||
fontSize: "0.75rem",
|
||||
letterSpacing: "0.15em",
|
||||
textTransform: "uppercase",
|
||||
padding: "14px 28px",
|
||||
background: "transparent",
|
||||
border: "1px solid #1c1f26",
|
||||
color: "#c8a96e",
|
||||
cursor: "pointer",
|
||||
transition: "all 0.3s ease",
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
gap: "0.5rem"
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
e.currentTarget.style.background = "rgba(200, 169, 110, 0.03)";
|
||||
e.currentTarget.style.borderColor = "#c8a96e";
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.background = "transparent";
|
||||
e.currentTarget.style.borderColor = "#1c1f26";
|
||||
}}
|
||||
>
|
||||
{showAll ? "— Show Less" : "+ Show More"}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user