diff --git a/package-lock.json b/package-lock.json index c5e3b26..ce37704 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@vercel/speed-insights": "^1.0.9", "classnames": "^2.5.1", "contentful": "^10.6.21", + "framer-motion": "^11.0.3", "next": "^14.1.0", "prisma": "^5.9.1", "react": "^18.2.0", @@ -1285,6 +1286,21 @@ "node": ">=6.0.0" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -5551,6 +5567,29 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.0.3.tgz", + "integrity": "sha512-6x2poQpIWBdbZwLd73w6cKZ1I9IEPIU94C6/Swp1Zt3LJ+sB5bPe1E2wC6EH5hSISXNkMJ4afH7AdwS7MrtkWw==", + "dependencies": { + "tslib": "^2.4.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": "^18.0.0", + "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", diff --git a/package.json b/package.json index 7ac8b33..1cd0b15 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "@vercel/speed-insights": "^1.0.9", "classnames": "^2.5.1", "contentful": "^10.6.21", + "framer-motion": "^11.0.3", "next": "^14.1.0", "prisma": "^5.9.1", "react": "^18.2.0", diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 9eda01a..977cd49 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,3 +1,7 @@ +"use client"; + +import { motion, Variants } from "framer-motion"; + import { DribbleIcon } from "@/icons/Dribble"; import { FlickrIcon } from "@/icons/Flickr"; import { InstagramIcon } from "@/icons/Instagram"; @@ -9,6 +13,28 @@ import { LINKEDIN_LINK, } from "@/utils/constants"; +const iconsVariants: Variants = { + offscreen: { + y: 20, + opacity: 0, + }, + onscreen: { + y: 0, + opacity: 1, + transition: { + y: { + type: "spring", + bounce: 0.8, + duration: 3, + }, + opacity: { + bounce: 0, + duration: 0.3, + }, + }, + }, +}; + export const Footer: React.FC> = () => { return (
@@ -18,43 +44,53 @@ export const Footer: React.FC> = () => {
-
- + - + - - + - - + - - -
+ +
diff --git a/src/components/Home/Hero.tsx b/src/components/Home/Hero.tsx index 5637c10..dd711f5 100644 --- a/src/components/Home/Hero.tsx +++ b/src/components/Home/Hero.tsx @@ -1,19 +1,50 @@ +"use client"; + +import { motion, Variants } from "framer-motion"; + import { Navbar } from "../Navbar"; +const variants: Variants = { + offscreen: { + y: 10, + opacity: 0, + }, + onscreen: { + y: 0, + opacity: 1, + transition: { + type: "spring", + duration: 1, + }, + }, +}; + export const Hero = () => (
-
-

+ + Have no fear of perfection
— you{"'"}ll never reach it. {"–"} Salvador Dali -

-

+ + Have no fear of perfection—you{"'"}ll never reach it. {"–"} Salvador Dali -

-
+ +

Working in multidisciplinary environments and different design areas including: 2D/3D graphics, 3D interiors and UX/UI strategy. I{"'"}m @@ -21,8 +52,8 @@ export const Hero = () => ( environmentally less impactful, more ethical and always try to be aware of the bigger picture.

-
-
+ +
); diff --git a/src/components/Home/Projects/Filterbar.tsx b/src/components/Home/Projects/Filterbar.tsx index bdbf389..ef441d0 100644 --- a/src/components/Home/Projects/Filterbar.tsx +++ b/src/components/Home/Projects/Filterbar.tsx @@ -1,32 +1,77 @@ "use client"; import { useContext } from "react"; +import { motion, Variants } from "framer-motion"; import { ProjectsFilterContext } from "@/contexts/ProjectsFilterContext"; import { ProjectCategory } from "@/types/global"; const EXCLUDED_CATEGORIES = ["ALL", "PACKAGING_AND_UI"]; +const mainButtonVariants: Variants = { + offscreen: { + opacity: 0, + }, + onscreen: { + opacity: 1, + transition: { + type: "spring", + duration: 1, + }, + }, +}; + +const normalFiltersVariants: Variants = { + offscreen: { + y: 20, + opacity: 0, + }, + onscreen: { + y: 0, + opacity: 1, + transition: { + opacity: { + type: "spring", + bounce: 0, + duration: 0.2, + }, + y: { + type: "spring", + bounce: 0.6, + duration: 2, + }, + }, + }, +}; + export const Filterbar: React.FC = () => { const { currentFilter, setCurrentFilter } = useContext(ProjectsFilterContext); return (
-
-
+ setCurrentFilter(undefined)} > All Projects -
+ {Object.entries(ProjectCategory) .filter(([key]) => !EXCLUDED_CATEGORIES.includes(key)) .map(([key, value]) => ( -
setCurrentFilter(value)} >

{ > {value}

-
+ ))} -
+
); }; diff --git a/src/components/Home/Projects/Project.tsx b/src/components/Home/Projects/Project.tsx index 2cb4f30..39766a1 100644 --- a/src/components/Home/Projects/Project.tsx +++ b/src/components/Home/Projects/Project.tsx @@ -1,3 +1,6 @@ +"use client"; + +import { motion, Variants } from "framer-motion"; import Image from "next/image"; import Link from "next/link"; @@ -7,15 +10,44 @@ interface ProjectsProps { project: IProject; } +const imageVariants: Variants = { + offscreen: { + y: 100, + opacity: 0, + }, + onscreen: { + y: 0, + opacity: 1, + transition: { + type: "spring", + bounce: 0.4, + duration: 1.8, + }, + }, +}; + +const textVariants: Variants = { + offscreen: { y: 100, opacity: 0 }, + onscreen: { + y: 0, + opacity: 1, + transition: { type: "spring", bounce: 0.1, duration: 0.8 }, + }, +}; + export const Project: React.FC = ({ project }) => { const thumbnailImage = project.thumbnailImage; return ( -
-
- + {project.comingSoon ? ( -
+
coming soon @@ -32,27 +64,36 @@ export const Project: React.FC = ({ project }) => {

{project.title}

-
+ ) : ( - - {thumbnailImage && ( - {thumbnailImage.description - )} -

- {project.title} -

- + + + {thumbnailImage && ( + {thumbnailImage.description + )} +

+ {project.title} +

+ +
)} - + {project.categoryText} - - {project.intro &&
{project.intro}
} -
+ + {project.intro && ( + + {project.intro} + + )} +
); }; diff --git a/src/components/Home/Projects/ProjectsList.tsx b/src/components/Home/Projects/ProjectsList.tsx index 2b98b09..d5f35fe 100644 --- a/src/components/Home/Projects/ProjectsList.tsx +++ b/src/components/Home/Projects/ProjectsList.tsx @@ -8,8 +8,6 @@ import { Project as IProject } from "@/types/global"; import { Project } from "./Project"; import { useProjectsWithFilter } from "./useProjectsWithFilter"; -// @TODO Check if it's possible to put a nice transition on appearing/disappearing items - interface ProjectsListProps { projects: Array< Pick< diff --git a/src/components/Home/Skills/index.tsx b/src/components/Home/Skills/index.tsx index 1092a79..35667a5 100644 --- a/src/components/Home/Skills/index.tsx +++ b/src/components/Home/Skills/index.tsx @@ -1,37 +1,94 @@ +"use client"; + +import { motion, Variants } from "framer-motion"; + import { CirclesLogo } from "@/icons/CirclesLogo"; import { SKILLS, SOFTWARES } from "./skills"; +const variants: Variants = { + offscreen: { + y: 100, + opacity: 0, + }, + onscreen: { + y: 0, + opacity: 1, + transition: { + type: "spring", + bounce: 0.4, + duration: 1, + }, + }, +}; + export const Skills = () => (
-
-

Expertise

+ + + Expertise +
-
- SOFTWARE + + + SOFTWARE + {SOFTWARES.map((software, i) => ( - + {software} - + ))} -
+ -
- SKILLS + + + SKILLS + {SKILLS.map((skill, i) => ( - + {skill} - + ))} -
+
-
+
diff --git a/src/components/Navbar/index.tsx b/src/components/Navbar/index.tsx index 88c4ecc..9096708 100644 --- a/src/components/Navbar/index.tsx +++ b/src/components/Navbar/index.tsx @@ -4,7 +4,7 @@ import { CONTRA_LINK } from "@/utils/constants"; export const Navbar: React.FC = () => { return ( -
+
diff --git a/src/components/Project/Navbar/index.tsx b/src/components/Project/Navbar/index.tsx index e526902..695fae9 100644 --- a/src/components/Project/Navbar/index.tsx +++ b/src/components/Project/Navbar/index.tsx @@ -4,7 +4,7 @@ import { CONTRA_LINK } from "@/utils/constants"; export const ProjectNavbar: React.FC = ({}) => { return ( -
+