Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 14 additions & 26 deletions app/components/home/portfolio.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import React from "react";
import Album from '@/app/Media/Photos/Fox Album Cover Alt2.jpg';
import Ript from '@/app/Media/Photos/Ript Portfolio Icon.png';
import Dansbands from '@/app/Media/Photos/dansbands icon.png';
import Image from "next/image";

import { portfolioItems } from "@/app/util/const";

const Portfolio = () => {
return (
Expand All @@ -17,28 +14,19 @@ const Portfolio = () => {
<h2 className="subtitle">
SELECTED PROJECTS. <a href="/portfolio">{"SEE MORE >"}</a>
</h2>
<div className="row">
<Image
alt="Fox album artwork"
src={Album}
width={300}
height={300}
sizes="(max-width: 767px) 200px, (max-width: 1199px) 200px, 300px"
/>
<Image
alt="Ript project cover"
src={Ript}
width={300}
height={300}
sizes="(max-width: 767px) 200px, (max-width: 1199px) 200px, 300px"
/>
<Image
alt="dansbands project cover"
src={Dansbands}
width={300}
height={300}
sizes="(max-width: 767px) 200px, (max-width: 1199px) 200px, 300px"
/>
<div className="portfolio-carousel">
{portfolioItems.map((item) => (
<a key={item.title} className="portfolio-card" href="/portfolio">
<Image
alt={item.title}
src={item.image}
width={420}
height={236}
sizes="(max-width: 767px) 280px, (max-width: 1199px) 280px, 420px"
/>
<p className="portfolio-card-title">{item.title}</p>
</a>
))}
</div>
</div>
</div>
Expand Down
145 changes: 63 additions & 82 deletions app/components/home/professional.tsx
Original file line number Diff line number Diff line change
@@ -1,115 +1,96 @@
"use client";

import React, { useRef, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faServer, faSitemap, faRobot } from "@fortawesome/free-solid-svg-icons";
import { faCss3Alt, faFigma } from "@fortawesome/free-brands-svg-icons";
import type { IconDefinition } from "@fortawesome/fontawesome-svg-core";
import type { StaticImageData } from "next/image";
import ReactIcon from "@/app/Media/Icons/React.svg";
import TypeScriptIcon from "@/app/Media/Icons/TypeScript.svg";
import NextIcon from "@/app/Media/Icons/Next.svg";
import NodeIcon from "@/app/Media/Icons/Node.svg";
import XStateIcon from "@/app/Media/Icons/xState.svg";

type ImgTechItem = {
label: string;
accent: boolean;
kind: "img";
src: StaticImageData;
};
type FaTechItem = {
label: string;
accent: boolean;
kind: "fa";
icon: IconDefinition;
};
type TechItem = ImgTechItem | FaTechItem;

const techStack: TechItem[] = [
{ label: "React", kind: "img", src: ReactIcon as StaticImageData, accent: true },
{ label: "TypeScript", kind: "img", src: TypeScriptIcon as StaticImageData, accent: false },
{ label: "Next.js", kind: "img", src: NextIcon as StaticImageData, accent: true },
{ label: "Node.js", kind: "img", src: NodeIcon as StaticImageData, accent: false },
{ label: "XState", kind: "img", src: XStateIcon as StaticImageData, accent: false },
{ label: "CSS Animations", kind: "fa", icon: faCss3Alt, accent: true },
{ label: "REST APIs", kind: "fa", icon: faServer, accent: false },
{ label: "System Design", kind: "fa", icon: faSitemap, accent: false },
{ label: "AI Integration", kind: "fa", icon: faRobot, accent: true },
{ label: "Figma", kind: "fa", icon: faFigma, accent: false },
];

const Professional = () => {
const professionalRef = useRef<HTMLDivElement>(null);
const animationContainerRef = useRef<HTMLDivElement>(null);
const sectionRef = useRef<HTMLDivElement>(null);
const compositionRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const sectionElement = professionalRef.current;
const animationContainer = animationContainerRef.current;
const section = sectionRef.current;
const composition = compositionRef.current;

const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting && animationContainer) {
animationContainer.classList.add("is-visible");
if (entry.isIntersecting && composition) {
composition.classList.add("is-visible");
observer.unobserve(entry.target);
}
});
},
{ threshold: 0.35 }
{ threshold: 0.25 }
);

if (sectionElement) {
observer.observe(sectionElement);
}
if (section) observer.observe(section);

return () => {
if (sectionElement) {
observer.unobserve(sectionElement);
}
if (section) observer.unobserve(section);
};
}, []);

return (
<div className="professional" ref={professionalRef}>
<div className="professional" ref={sectionRef}>
<div id="professional" className="smooth"></div>
<div className="container">
<h1 className="title">
<span className="gray">01</span> PROFESSIONAL
</h1>
<h2 className="subtitle">CORE TECHNOLOGIES USED IN SHIPPED WORK</h2>
<div className="visible-on-scroll" ref={animationContainerRef}>
<div id="skills">
<div id="apps">
<p>JavaScript</p>
<p>HTML5</p>
<p>CSS3</p>
<p>Express</p>
<p>React</p>
<p>NextJS</p>
<p>Figma</p>
</div>

<div className="grid">
<div className="bar pct-95">
<div className="inner"></div>
<div className="right">
<p>95%</p>
</div>
</div>
<div className="bar pct-95">
<div className="inner2"></div>
<div className="right">
<p>95%</p>
</div>
</div>
<div className="bar pct-95">
<div className="inner3"></div>
<div className="right">
<p>95%</p>
</div>
</div>
<div className="bar pct-85">
<div className="inner"></div>
<div className="right">
<p>85%</p>
</div>
</div>
<div className="bar pct-95">
<div className="inner3"></div>
<div className="right">
<p>95%</p>
</div>
</div>
<div className="bar pct-95">
<div className="inner2"></div>
<div className="right">
<p>95%</p>
</div>
</div>
<div className="bar pct-85">
<div className="inner"></div>
<div className="right">
<p>85%</p>
</div>
</div>

<div className="v-divider one"></div>
<div className="v-divider two"></div>
<div className="v-divider three"></div>

<div id="scale">
<p className="zero">0%</p>
<p className="one">25%</p>
<p className="two">50%</p>
<p className="three">75%</p>
<p className="four">100%</p>
<h2 className="subtitle">CORE TECHNOLOGIES IN SHIPPED WORK</h2>
<div className="tech-motion-composition" ref={compositionRef}>
{techStack.map((item, i) => (
<div
key={item.label}
className={`tech-card${item.accent ? " accent" : ""}`}
style={{ "--tech-delay": `${i * 0.07}s` } as React.CSSProperties}
>
<div className="tech-card-icon">
{item.kind === "img" ? (
<img src={item.src.src} alt={item.label} />
) : (
<FontAwesomeIcon icon={item.icon} />
)}
</div>
<span className="tech-card-label">{item.label}</span>
</div>
</div>
))}
</div>
</div>
</div>
Expand Down
Loading