diff --git a/index.html b/index.html
index 438c9fe03..c83e9fd4c 100644
--- a/index.html
+++ b/index.html
@@ -4,7 +4,7 @@
-
Lama Dev Portfolio
+ Add Page Title
diff --git a/package-lock.json b/package-lock.json
index 09f389b3c..8ad6536fb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,18 +8,21 @@
"name": "starter",
"version": "0.0.0",
"dependencies": {
- "react": "^18.2.0",
- "react-dom": "^18.2.0"
+ "@emailjs/browser": "^3.11.0",
+ "framer-motion": "^10.16.4",
+ "react": "18.2.0",
+ "react-dom": "18.2.0",
+ "sass": "^1.68.0"
},
"devDependencies": {
- "@types/react": "^18.2.15",
- "@types/react-dom": "^18.2.7",
- "@vitejs/plugin-react": "^4.0.3",
- "eslint": "^8.45.0",
- "eslint-plugin-react": "^7.32.2",
- "eslint-plugin-react-hooks": "^4.6.0",
- "eslint-plugin-react-refresh": "^0.4.3",
- "vite": "^4.4.5"
+ "@types/react": "18.2.15",
+ "@types/react-dom": "18.2.7",
+ "@vitejs/plugin-react": "4.0.3",
+ "eslint": "8.45.0",
+ "eslint-plugin-react": "7.32.2",
+ "eslint-plugin-react-hooks": "4.6.0",
+ "eslint-plugin-react-refresh": "0.4.3",
+ "vite": "4.4.5"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -371,6 +374,29 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@emailjs/browser": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/@emailjs/browser/-/browser-3.11.0.tgz",
+ "integrity": "sha512-RkY3FKZ3fPdK++OeF46mRTFpmmQWCHUVHZH209P3NE4D5sg2Atg7S2wa3gw5062Gl4clt4Wn5SyC4WhlVZC5pA==",
+ "engines": {
+ "node": ">=14.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/@esbuild/android-arm": {
"version": "0.18.20",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz",
@@ -786,9 +812,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.51.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.51.0.tgz",
- "integrity": "sha512-HxjQ8Qn+4SI3/AFv6sOrDB+g6PpUTDwSJiQqOrnneEk8L71161srI9gjzzZvYVbzHiVg/BvcH95+cK/zfIt4pg==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz",
+ "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -910,47 +936,6 @@
"node": ">= 8"
}
},
- "node_modules/@types/babel__core": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.2.tgz",
- "integrity": "sha512-pNpr1T1xLUc2l3xJKuPtsEky3ybxN3m4fJkknfIpTCTfIZCDW57oAg+EfCgIIp2rvCe0Wn++/FfodDS4YXxBwA==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.20.7",
- "@babel/types": "^7.20.7",
- "@types/babel__generator": "*",
- "@types/babel__template": "*",
- "@types/babel__traverse": "*"
- }
- },
- "node_modules/@types/babel__generator": {
- "version": "7.6.5",
- "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.5.tgz",
- "integrity": "sha512-h9yIuWbJKdOPLJTbmSpPzkF67e659PbQDba7ifWm5BJ8xTv+sDmS7rFmywkWOvXedGTivCdeGSIIX8WLcRTz8w==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__template": {
- "version": "7.4.2",
- "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.2.tgz",
- "integrity": "sha512-/AVzPICMhMOMYoSx9MoKpGDKdBRsIXMNByh1PXSZoa+v6ZoLa8xxtsT/uLQ/NJm0XVAWl/BvId4MlDeXJaeIZQ==",
- "dev": true,
- "dependencies": {
- "@babel/parser": "^7.1.0",
- "@babel/types": "^7.0.0"
- }
- },
- "node_modules/@types/babel__traverse": {
- "version": "7.20.2",
- "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.2.tgz",
- "integrity": "sha512-ojlGK1Hsfce93J0+kn3H5R73elidKUaZonirN33GSmgTUMpzI/MIFfSpF3haANe3G1bEBS9/9/QEqwTzwqFsKw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.20.7"
- }
- },
"node_modules/@types/prop-types": {
"version": "15.7.8",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.8.tgz",
@@ -958,9 +943,9 @@
"dev": true
},
"node_modules/@types/react": {
- "version": "18.2.25",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.25.tgz",
- "integrity": "sha512-24xqse6+VByVLIr+xWaQ9muX1B4bXJKXBbjszbld/UEDslGLY53+ZucF44HCmLbMPejTzGG9XgR+3m2/Wqu1kw==",
+ "version": "18.2.15",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.15.tgz",
+ "integrity": "sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==",
"dev": true,
"dependencies": {
"@types/prop-types": "*",
@@ -969,9 +954,9 @@
}
},
"node_modules/@types/react-dom": {
- "version": "18.2.11",
- "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.11.tgz",
- "integrity": "sha512-zq6Dy0EiCuF9pWFW6I6k6W2LdpUixLE4P6XjXU1QHLfak3GPACQfLwEuHzY5pOYa4hzj1d0GxX/P141aFjZsyg==",
+ "version": "18.2.7",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.7.tgz",
+ "integrity": "sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==",
"dev": true,
"dependencies": {
"@types/react": "*"
@@ -984,15 +969,14 @@
"dev": true
},
"node_modules/@vitejs/plugin-react": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.1.0.tgz",
- "integrity": "sha512-rM0SqazU9iqPUraQ2JlIvReeaxOoRj6n+PzB1C0cBzIbd8qP336nC39/R9yPi3wVcah7E7j/kdU1uCUqMEU4OQ==",
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.3.tgz",
+ "integrity": "sha512-pwXDog5nwwvSIzwrvYYmA2Ljcd/ZNlcsSG2Q9CNDBwnsd55UGAyr2doXtB5j+2uymRCnCfExlznzzSFbBRcoCg==",
"dev": true,
"dependencies": {
- "@babel/core": "^7.22.20",
+ "@babel/core": "^7.22.5",
"@babel/plugin-transform-react-jsx-self": "^7.22.5",
"@babel/plugin-transform-react-jsx-source": "^7.22.5",
- "@types/babel__core": "^7.20.2",
"react-refresh": "^0.14.0"
},
"engines": {
@@ -1060,6 +1044,18 @@
"node": ">=4"
}
},
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -1168,15 +1164,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/asynciterator.prototype": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz",
- "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==",
- "dev": true,
- "dependencies": {
- "has-symbols": "^1.0.3"
- }
- },
"node_modules/available-typed-arrays": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
@@ -1195,6 +1182,14 @@
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
+ "node_modules/binary-extensions": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -1205,6 +1200,17 @@
"concat-map": "0.0.1"
}
},
+ "node_modules/braces": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dependencies": {
+ "fill-range": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/browserslist": {
"version": "4.22.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
@@ -1293,6 +1299,43 @@
"node": ">=4"
}
},
+ "node_modules/chokidar": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
+ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ ],
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -1465,28 +1508,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/es-iterator-helpers": {
- "version": "1.0.15",
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz",
- "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==",
- "dev": true,
- "dependencies": {
- "asynciterator.prototype": "^1.0.0",
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.1",
- "es-abstract": "^1.22.1",
- "es-set-tostringtag": "^2.0.1",
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.2.1",
- "globalthis": "^1.0.3",
- "has-property-descriptors": "^1.0.0",
- "has-proto": "^1.0.1",
- "has-symbols": "^1.0.3",
- "internal-slot": "^1.0.5",
- "iterator.prototype": "^1.1.2",
- "safe-array-concat": "^1.0.1"
- }
- },
"node_modules/es-set-tostringtag": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
@@ -1583,27 +1604,27 @@
}
},
"node_modules/eslint": {
- "version": "8.51.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.51.0.tgz",
- "integrity": "sha512-2WuxRZBrlwnXi+/vFSJyjMqrNjtJqiasMzehF0shoLaW7DzS3/9Yvrmq5JiT66+pNjiX4UBnLDiKHcWAr/OInA==",
+ "version": "8.45.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz",
+ "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
- "@eslint-community/regexpp": "^4.6.1",
- "@eslint/eslintrc": "^2.1.2",
- "@eslint/js": "8.51.0",
- "@humanwhocodes/config-array": "^0.11.11",
+ "@eslint-community/regexpp": "^4.4.0",
+ "@eslint/eslintrc": "^2.1.0",
+ "@eslint/js": "8.44.0",
+ "@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
- "ajv": "^6.12.4",
+ "ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
"debug": "^4.3.2",
"doctrine": "^3.0.0",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^7.2.2",
- "eslint-visitor-keys": "^3.4.3",
- "espree": "^9.6.1",
+ "eslint-scope": "^7.2.0",
+ "eslint-visitor-keys": "^3.4.1",
+ "espree": "^9.6.0",
"esquery": "^1.4.2",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -1637,16 +1658,15 @@
}
},
"node_modules/eslint-plugin-react": {
- "version": "7.33.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz",
- "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==",
+ "version": "7.32.2",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz",
+ "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==",
"dev": true,
"dependencies": {
"array-includes": "^3.1.6",
"array.prototype.flatmap": "^1.3.1",
"array.prototype.tosorted": "^1.1.1",
"doctrine": "^2.1.0",
- "es-iterator-helpers": "^1.0.12",
"estraverse": "^5.3.0",
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
"minimatch": "^3.1.2",
@@ -1656,7 +1676,7 @@
"object.values": "^1.1.6",
"prop-types": "^15.8.1",
"resolve": "^2.0.0-next.4",
- "semver": "^6.3.1",
+ "semver": "^6.3.0",
"string.prototype.matchall": "^4.0.8"
},
"engines": {
@@ -1922,6 +1942,17 @@
"node": "^10.12.0 || >=12.0.0"
}
},
+ "node_modules/fill-range": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -1967,6 +1998,29 @@
"is-callable": "^1.1.3"
}
},
+ "node_modules/framer-motion": {
+ "version": "10.16.4",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.4.tgz",
+ "integrity": "sha512-p9V9nGomS3m6/CALXqv6nFGMuFOxbWsmaOrdmhyQimMIlLl3LC7h7l86wge/Js/8cRu5ktutS/zlzgR7eBOtFA==",
+ "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",
@@ -1977,7 +2031,6 @@
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
- "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -2221,6 +2274,11 @@
"node": ">= 4"
}
},
+ "node_modules/immutable": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz",
+ "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA=="
+ },
"node_modules/import-fresh": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@@ -2290,21 +2348,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-async-function": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz",
- "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-bigint": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
@@ -2317,6 +2360,17 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/is-boolean-object": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
@@ -2376,43 +2430,14 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/is-finalizationregistry": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz",
- "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-generator-function": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz",
- "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -2420,15 +2445,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-map": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz",
- "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-negative-zero": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
@@ -2441,6 +2457,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
"node_modules/is-number-object": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
@@ -2481,15 +2505,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-set": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz",
- "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-shared-array-buffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz",
@@ -2547,15 +2562,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-weakmap": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz",
- "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-weakref": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
@@ -2568,19 +2574,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-weakset": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
- "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
@@ -2593,19 +2586,6 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
"dev": true
},
- "node_modules/iterator.prototype": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz",
- "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.2.1",
- "get-intrinsic": "^1.2.1",
- "has-symbols": "^1.0.3",
- "reflect.getprototypeof": "^1.0.4",
- "set-function-name": "^2.0.1"
- }
- },
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -2791,6 +2771,14 @@
"integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true
},
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
@@ -3004,6 +2992,17 @@
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
"dev": true
},
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
"node_modules/postcss": {
"version": "8.4.31",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
@@ -3119,24 +3118,15 @@
"node": ">=0.10.0"
}
},
- "node_modules/reflect.getprototypeof": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz",
- "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==",
- "dev": true,
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.2.0",
- "es-abstract": "^1.22.1",
- "get-intrinsic": "^1.2.1",
- "globalthis": "^1.0.3",
- "which-builtin-type": "^1.1.3"
+ "picomatch": "^2.2.1"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=8.10.0"
}
},
"node_modules/regexp.prototype.flags": {
@@ -3278,6 +3268,22 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/sass": {
+ "version": "1.68.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.68.0.tgz",
+ "integrity": "sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==",
+ "dependencies": {
+ "chokidar": ">=3.0.0 <4.0.0",
+ "immutable": "^4.0.0",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/scheduler": {
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
@@ -3348,7 +3354,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -3481,6 +3486,22 @@
"node": ">=4"
}
},
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
@@ -3625,14 +3646,14 @@
}
},
"node_modules/vite": {
- "version": "4.4.11",
- "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.11.tgz",
- "integrity": "sha512-ksNZJlkcU9b0lBwAGZGGaZHCMqHsc8OpgtoYhsQ4/I2v5cnpmmmqe5pM4nv/4Hn6G/2GhTdj0DhZh2e+Er1q5A==",
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.5.tgz",
+ "integrity": "sha512-4m5kEtAWHYr0O1Fu7rZp64CfO1PsRGZlD3TAB32UmQlpd7qg15VF7ROqGN5CyqN7HFuwr7ICNM2+fDWRqFEKaA==",
"dev": true,
"dependencies": {
"esbuild": "^0.18.10",
- "postcss": "^8.4.27",
- "rollup": "^3.27.1"
+ "postcss": "^8.4.26",
+ "rollup": "^3.25.2"
},
"bin": {
"vite": "bin/vite.js"
@@ -3710,47 +3731,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/which-builtin-type": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz",
- "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==",
- "dev": true,
- "dependencies": {
- "function.prototype.name": "^1.1.5",
- "has-tostringtag": "^1.0.0",
- "is-async-function": "^2.0.0",
- "is-date-object": "^1.0.5",
- "is-finalizationregistry": "^1.0.2",
- "is-generator-function": "^1.0.10",
- "is-regex": "^1.1.4",
- "is-weakref": "^1.0.2",
- "isarray": "^2.0.5",
- "which-boxed-primitive": "^1.0.2",
- "which-collection": "^1.0.1",
- "which-typed-array": "^1.1.9"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/which-collection": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz",
- "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==",
- "dev": true,
- "dependencies": {
- "is-map": "^2.0.1",
- "is-set": "^2.0.1",
- "is-weakmap": "^2.0.1",
- "is-weakset": "^2.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/which-typed-array": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz",
diff --git a/package.json b/package.json
index 2e6793c46..657c4f12c 100644
--- a/package.json
+++ b/package.json
@@ -10,8 +10,11 @@
"preview": "vite preview"
},
"dependencies": {
+ "@emailjs/browser": "^3.11.0",
+ "framer-motion": "^10.16.4",
"react": "18.2.0",
- "react-dom": "18.2.0"
+ "react-dom": "18.2.0",
+ "sass": "^1.68.0"
},
"devDependencies": {
"@types/react": "18.2.15",
diff --git a/src/App.jsx b/src/App.jsx
index cb7b6da73..50b21077d 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,5 +1,39 @@
+//import Test from "./Test";
+import "./app.scss";
+import Contact from "./components/contact/Contact";
+import Cursor from "./components/cursor/Cursor";
+import Hero from "./components/hero/Hero";
+import Navbar from "./components/navbar/Navbar";
+import Parallax from "./components/parallax/Parallax";
+import Portfolio from "./components/portfolio/Portfolio";
+import Services from "./components/services/Services";
+
const App = () => {
- return Hello World
;
+ return (
+
+
+
+
+
+
+
+
+ {/* Framer Motion Crash Course */}
+ {/*
+
*/}
+
+ );
};
-export default App;
+export default App;
\ No newline at end of file
diff --git a/src/Test.jsx b/src/Test.jsx
new file mode 100644
index 000000000..ef6744949
--- /dev/null
+++ b/src/Test.jsx
@@ -0,0 +1,31 @@
+import { motion } from "framer-motion";
+import { useState } from "react";
+
+const Test = () => {
+ const [open, setOpen] = useState(false);
+
+ const variants = {
+ visible: (i)=>( {
+ opacity: 1,
+ x: 100,
+ transition: { delay:i * 0.3 },
+ }),
+ hidden: { opacity: 0 },
+ };
+
+ const items = ["item1", "item2", "item3", "item4"];
+
+ return (
+
+
+ {items.map((item,i) => (
+
+ {item}
+
+ ))}
+
+
+ );
+};
+
+export default Test;
\ No newline at end of file
diff --git a/src/app.scss b/src/app.scss
new file mode 100644
index 000000000..b4ff5573f
--- /dev/null
+++ b/src/app.scss
@@ -0,0 +1,44 @@
+html {
+ scroll-snap-type: y mandatory;
+ scroll-behavior: smooth;
+ }
+
+ * {
+ padding: 0;
+ margin: 0;
+ box-sizing: border-box;
+ font-family: "DM Sans", sans-serif;
+ }
+
+ body {
+ background-color: #0c0c1d;
+ color: lightgray;
+ }
+
+ a {
+ text-decoration: none;
+ color: inherit;
+ }
+
+ section {
+ height: 100vh;
+ width: 100vw;
+ scroll-snap-align: center;
+ overflow: hidden;
+ }
+
+ @mixin mobile {
+ @media (max-width: 738px) {
+ @content;
+ }
+ }
+ @mixin tablet {
+ @media (max-width: 1024px) {
+ @content;
+ }
+ }
+ @mixin desktop {
+ @media (max-width: 1366px) {
+ @content;
+ }
+ }
\ No newline at end of file
diff --git a/src/components/contact/Contact.jsx b/src/components/contact/Contact.jsx
new file mode 100644
index 000000000..302e7a724
--- /dev/null
+++ b/src/components/contact/Contact.jsx
@@ -0,0 +1,121 @@
+import { useRef, useState } from "react";
+import "./contact.scss";
+import { motion, useInView } from "framer-motion";
+import emailjs from "@emailjs/browser";
+
+const variants = {
+ initial: {
+ y: 500,
+ opacity: 0,
+ },
+ animate: {
+ y: 0,
+ opacity: 1,
+ transition: {
+ duration: 0.5,
+ staggerChildren: 0.1,
+ },
+ },
+};
+
+const Contact = () => {
+ const ref = useRef();
+ const formRef = useRef();
+ const [error, setError] = useState(false);
+ const [success, setSuccess] = useState(false);
+
+ const isInView = useInView(ref, { margin: "-100px" });
+
+ const sendEmail = (e) => {
+ e.preventDefault();
+
+ emailjs
+ .sendForm(
+ "service_94y20xo",
+ "template_v10u2oh",
+ formRef.current,
+ "pX_2hasGmGcuvjXIW"
+ )
+ .then(
+ (result) => {
+ setSuccess(true)
+ },
+ (error) => {
+ setError(true);
+ }
+ );
+ };
+
+ return (
+
+
+ Let’s work together
+
+ Mail
+ hello@react.dev
+
+
+ Address
+ Hello street New York
+
+
+ Phone
+ +1 234 5678
+
+
+
+
+
+
+
+
+
+
+
+
+ Submit
+ {error && "Error"}
+ {success && "Success"}
+
+
+
+ );
+};
+
+export default Contact;
diff --git a/src/components/contact/contact.scss b/src/components/contact/contact.scss
new file mode 100644
index 000000000..0619ca235
--- /dev/null
+++ b/src/components/contact/contact.scss
@@ -0,0 +1,91 @@
+@import "../../app.scss";
+
+.contact {
+ height: 100%;
+ max-width: 1366px;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ gap: 50px;
+
+ @include mobile {
+ width: 100%;
+ padding: 10px;
+ flex-direction: column;
+ }
+
+ .textContainer {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 40px;
+
+ @include mobile {
+ gap: 20px;
+ text-align: center;
+ align-items: center;
+ margin-top: 70px;
+ }
+
+ h1 {
+ font-size: 100px;
+ line-height: 88px;
+
+ @include mobile {
+ font-size: 36px;
+ }
+ }
+
+ span {
+ font-weight: 300;
+ }
+ }
+
+ .formContainer {
+ flex: 1;
+ position: relative;
+
+ @include mobile {
+ padding: 50px;
+ width: 100%;
+ }
+
+
+ .phoneSvg {
+ stroke: orange;
+ position: absolute;
+ margin: auto;
+ z-index: -1;
+ }
+
+ form {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+
+ input,
+ textarea {
+ padding: 20px;
+ background-color: transparent;
+ border: 1px solid white;
+ color: white;
+ border-radius: 5px;
+
+ @include mobile {
+ padding: 10px;
+ }
+ }
+
+ button {
+ padding: 20px;
+ border: none;
+ background-color: orange;
+ cursor: pointer;
+ font-weight: 500;
+ @include mobile {
+ padding: 10px;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/cursor/Cursor.jsx b/src/components/cursor/Cursor.jsx
new file mode 100644
index 000000000..e7b63f935
--- /dev/null
+++ b/src/components/cursor/Cursor.jsx
@@ -0,0 +1,28 @@
+import { useEffect, useState } from "react";
+import { motion } from "framer-motion";
+import "./cursor.scss";
+
+const Cursor = () => {
+ const [position, setPosition] = useState({ x: 0, y: 0 });
+
+ useEffect(() => {
+ const mouseMove = (e) => {
+ setPosition({ x: e.clientX, y: e.clientY });
+ };
+
+ window.addEventListener("mousemove", mouseMove);
+
+ return () => {
+ window.removeEventListener("mousemove", mouseMove);
+ };
+ }, []);
+
+ return (
+
+ );
+};
+
+export default Cursor;
diff --git a/src/components/cursor/cursor.scss b/src/components/cursor/cursor.scss
new file mode 100644
index 000000000..a55b29475
--- /dev/null
+++ b/src/components/cursor/cursor.scss
@@ -0,0 +1,14 @@
+@import "../../app.scss";
+
+.cursor{
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ border: 1px solid white;
+ position: fixed;
+ z-index: 999;
+
+ @include mobile{
+ display: none;
+ }
+}
\ No newline at end of file
diff --git a/src/components/hero/Hero.jsx b/src/components/hero/Hero.jsx
new file mode 100644
index 000000000..273f91a5a
--- /dev/null
+++ b/src/components/hero/Hero.jsx
@@ -0,0 +1,83 @@
+import "./hero.scss";
+import { motion } from "framer-motion";
+
+const textVariants = {
+ initial: {
+ x: -500,
+ opacity: 0,
+ },
+ animate: {
+ x: 0,
+ opacity: 1,
+ transition: {
+ duration: 1,
+ staggerChildren: 0.1,
+ },
+ },
+ scrollButton: {
+ opacity: 0,
+ y: 10,
+ transition: {
+ duration: 2,
+ repeat: Infinity,
+ },
+ },
+};
+const sliderVariants = {
+ initial: {
+ x: 0,
+ },
+ animate: {
+ x: "-220%",
+ transition: {
+ repeat: Infinity,
+ repeatType:"mirror",
+ duration: 20,
+ },
+ },
+};
+
+const Hero = () => {
+ return (
+
+
+
+ Developer Name
+
+ Web developer, UI designer and Project Manager
+
+
+
+ See the Latest Works
+
+ Contact Me
+
+
+
+
+
+ Writer Content Creator Influencer
+
+
+
+
+
+ );
+};
+
+export default Hero;
diff --git a/src/components/hero/hero.scss b/src/components/hero/hero.scss
new file mode 100644
index 000000000..65a72b0f3
--- /dev/null
+++ b/src/components/hero/hero.scss
@@ -0,0 +1,92 @@
+@import "../../app.scss";
+
+.hero {
+ height: calc(100vh - 100px);
+ overflow: hidden;
+ background: linear-gradient(180deg, #0c0c1d, #111132);
+ position: relative;
+
+ .wrapper {
+ max-width: 1366px;
+ height: 100%;
+ margin: auto;
+
+ .textContainer {
+ width: 50%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ gap: 40px;
+
+ @include mobile {
+ height: 50%;
+ width: 100%;
+ gap: 20px;
+ align-items: center;
+ text-align: center;
+ }
+
+ h2 {
+ font-size: 30px;
+ color: rebeccapurple;
+ letter-spacing: 10px;
+ }
+
+ h1 {
+ font-size: 88px;
+
+ @include mobile {
+ font-size: 36px;
+ }
+ }
+
+ .buttons {
+ button {
+ padding: 20px;
+ border: 1px solid white;
+ border-radius: 10px;
+ background-color: transparent;
+ color: white;
+ margin-right: 20px;
+ cursor: pointer;
+ font-weight: 300;
+ }
+ }
+
+ img {
+ width: 50px;
+ }
+ }
+ }
+
+ .imageContainer {
+ height: 100%;
+ position: absolute;
+ top: 0;
+ right: 0;
+
+ @include mobile {
+ height: 50%;
+ width: 100%;
+ top: unset;
+ bottom: 0;
+ }
+
+ img{
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ }
+ }
+
+ .slidingTextContainer {
+ position: absolute;
+ font-size: 50vh;
+ bottom: -120px;
+ white-space: nowrap;
+ color: #ffffff09;
+ width: 50%;
+ font-weight: bold;
+ }
+}
diff --git a/src/components/navbar/Navbar.jsx b/src/components/navbar/Navbar.jsx
new file mode 100644
index 000000000..3dfe637be
--- /dev/null
+++ b/src/components/navbar/Navbar.jsx
@@ -0,0 +1,37 @@
+import Sidebar from "../sidebar/Sidebar";
+import "./navbar.scss";
+import { motion } from "framer-motion";
+
+const Navbar = () => {
+ return (
+
+ );
+};
+
+export default Navbar;
diff --git a/src/components/navbar/navbar.scss b/src/components/navbar/navbar.scss
new file mode 100644
index 000000000..f5a9f3996
--- /dev/null
+++ b/src/components/navbar/navbar.scss
@@ -0,0 +1,37 @@
+@import "../../app.scss";
+
+.navbar {
+ height: 100px;
+
+ .wrapper {
+ max-width: 1366px;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ height: 100%;
+
+ @include mobile {
+ justify-content: flex-end;
+ padding: 20px;
+ }
+
+ span {
+ font-weight: bold;
+
+ @include mobile {
+ display: none;
+ }
+ }
+
+ .social {
+ display: flex;
+ gap: 20px;
+
+ img {
+ width: 18px;
+ height: 18px;
+ }
+ }
+ }
+}
diff --git a/src/components/parallax/Parallax.jsx b/src/components/parallax/Parallax.jsx
new file mode 100644
index 000000000..cf6f8fddc
--- /dev/null
+++ b/src/components/parallax/Parallax.jsx
@@ -0,0 +1,45 @@
+import { useRef } from "react";
+import "./parallax.scss";
+import { motion, useScroll, useTransform } from "framer-motion";
+
+const Parallax = ({ type }) => {
+ const ref = useRef();
+
+ const { scrollYProgress } = useScroll({
+ target: ref,
+ offset: ["start start", "end start"],
+ });
+
+ const yText = useTransform(scrollYProgress, [0, 1], ["0%", "500%"]);
+ const yBg = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
+
+ return (
+
+
+ {type === "services" ? "What We Do?" : "What We Did?"}
+
+
+
+
+
+ );
+};
+
+export default Parallax;
diff --git a/src/components/parallax/parallax.scss b/src/components/parallax/parallax.scss
new file mode 100644
index 000000000..a787f8f90
--- /dev/null
+++ b/src/components/parallax/parallax.scss
@@ -0,0 +1,56 @@
+@import "../../app.scss";
+
+.parallax {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ overflow: hidden;
+
+ h1 {
+ font-size: 100px;
+
+ @include mobile {
+ font-size: 72px;
+ text-align: center;
+ }
+ }
+
+ .mountains {
+ background-image: url("/mountains.png");
+ background-size: cover;
+ background-position: bottom;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 3;
+
+ @include mobile {
+ background-size: contain;
+ background-repeat: no-repeat;
+ }
+ }
+ .planets {
+ background-size: cover;
+ background-position: bottom;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 2;
+ @include mobile {
+ background-size: contain;
+ background-repeat: no-repeat;
+ }
+ }
+ .stars {
+ background-image: url("/stars.png");
+ background-size: cover;
+ background-position: bottom;
+ width: 100%;
+ height: 100%;
+ position: absolute;
+ z-index: 1;
+ }
+}
diff --git a/src/components/portfolio/Portfolio.jsx b/src/components/portfolio/Portfolio.jsx
new file mode 100644
index 000000000..f6426bac9
--- /dev/null
+++ b/src/components/portfolio/Portfolio.jsx
@@ -0,0 +1,85 @@
+import { useRef } from "react";
+import "./portfolio.scss";
+import { motion, useScroll, useSpring, useTransform } from "framer-motion";
+
+const items = [
+ {
+ id: 1,
+ title: "React Commerce",
+ img: "https://images.pexels.com/photos/18073372/pexels-photo-18073372/free-photo-of-young-man-sitting-in-a-car-on-a-night-street.jpeg?auto=compress&cs=tinysrgb&w=1600&lazy=load",
+ desc: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores ab id ad nesciunt quo aut corporis modi? Voluptate, quos sunt dolorum facilis, id eum sequi placeat accusantium saepe eos laborum.",
+ },
+ {
+ id: 2,
+ title: "Next.js Blog",
+ img: "https://images.pexels.com/photos/18023772/pexels-photo-18023772/free-photo-of-close-up-of-a-person-holding-a-wristwatch.jpeg?auto=compress&cs=tinysrgb&w=1600&lazy=load",
+ desc: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores ab id ad nesciunt quo aut corporis modi? Voluptate, quos sunt dolorum facilis, id eum sequi placeat accusantium saepe eos laborum.",
+ },
+ {
+ id: 3,
+ title: "Vanilla JS App",
+ img: "https://images.pexels.com/photos/6894528/pexels-photo-6894528.jpeg?auto=compress&cs=tinysrgb&w=1600&lazy=load",
+ desc: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores ab id ad nesciunt quo aut corporis modi? Voluptate, quos sunt dolorum facilis, id eum sequi placeat accusantium saepe eos laborum.",
+ },
+ {
+ id: 4,
+ title: "Music App",
+ img: "https://images.pexels.com/photos/18540208/pexels-photo-18540208/free-photo-of-wood-landscape-water-hill.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2",
+ desc: "Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores ab id ad nesciunt quo aut corporis modi? Voluptate, quos sunt dolorum facilis, id eum sequi placeat accusantium saepe eos laborum.",
+ },
+];
+
+const Single = ({ item }) => {
+ const ref = useRef();
+
+ const { scrollYProgress } = useScroll({
+ target: ref,
+ });
+
+ const y = useTransform(scrollYProgress, [0, 1], [-300, 300]);
+
+ return (
+
+
+
+
+
+
+
+ {item.title}
+ {item.desc}
+ See Demo
+
+
+
+
+ );
+};
+
+const Portfolio = () => {
+ const ref = useRef();
+
+ const { scrollYProgress } = useScroll({
+ target: ref,
+ offset: ["end end", "start start"],
+ });
+
+ const scaleX = useSpring(scrollYProgress, {
+ stiffness: 100,
+ damping: 30,
+ });
+
+ return (
+
+
+
Featured Works
+
+
+ {items.map((item) => (
+
+ ))}
+
+ );
+};
+
+export default Portfolio;
diff --git a/src/components/portfolio/portfolio.scss b/src/components/portfolio/portfolio.scss
new file mode 100644
index 000000000..780c7a088
--- /dev/null
+++ b/src/components/portfolio/portfolio.scss
@@ -0,0 +1,108 @@
+@import "../../app.scss";
+
+.portfolio {
+ position: relative;
+
+ .progress {
+ position: sticky;
+ top: 0;
+ left: 0;
+ padding-top: 50px;
+ text-align: center;
+ color: orange;
+ font-size: 36px;
+
+ @include mobile {
+ padding-top: calc(100vh - 100px);
+ font-size: 24px;
+ }
+
+ .progressBar {
+ height: 10px;
+ background-color: white;
+ }
+ }
+
+ .container {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+ overflow: hidden;
+
+ .wrapper {
+ max-width: 1366px;
+ height: 100%;
+ margin: auto;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 50px;
+
+ @include mobile {
+ flex-direction: column;
+ }
+
+ .imageContainer {
+ flex: 1;
+ height: 50%;
+
+ @include mobile {
+ width: 100%;
+ max-height: 300px;
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+
+ @include mobile {
+ object-fit: contain;
+ }
+ }
+ }
+
+ .textContainer {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 30px;
+
+ @include mobile {
+ transform: none !important;
+ padding: 10px;
+ align-items: center;
+ text-align: center;
+ }
+
+ h2 {
+ font-size: 72px;
+
+ @include mobile {
+ font-size: 36px;
+ }
+ }
+
+ p {
+ color: gray;
+ font-size: 20px;
+
+ @include mobile {
+ font-size: 16px;
+ }
+ }
+
+ button {
+ background-color: orange;
+ border: none;
+ border-radius: 10px;
+ padding: 10px;
+ width: 200px;
+ cursor: pointer;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/services/Services.jsx b/src/components/services/Services.jsx
new file mode 100644
index 000000000..445249add
--- /dev/null
+++ b/src/components/services/Services.jsx
@@ -0,0 +1,116 @@
+import { useRef } from "react";
+import "./services.scss";
+import { motion, useInView } from "framer-motion";
+
+const variants = {
+ initial: {
+ x: -500,
+ y: 100,
+ opacity: 0,
+ },
+ animate: {
+ x: 0,
+ opacity: 1,
+ y: 0,
+ transition: {
+ duration: 1,
+ staggerChildren: 0.1,
+ },
+ },
+};
+
+const Services = () => {
+ const ref = useRef();
+
+ const isInView = useInView(ref, { margin: "-100px" });
+
+ return (
+
+
+
+ I focus on helping your brand grow
+ and move forward
+
+
+
+
+
+
+
+ Unique Ideas
+
+
+
+
+ For Your Business.
+
+ WHAT WE DO?
+
+
+
+
+ Branding
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum
+ libero enim nisi aliquam consectetur expedita magni eius ex corrupti
+ animi! Ad nam pariatur assumenda quae mollitia libero repellat
+ explicabo maiores?
+
+ Go
+
+
+ Branding
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum
+ libero enim nisi aliquam consectetur expedita magni eius ex corrupti
+ animi! Ad nam pariatur assumenda quae mollitia libero repellat
+ explicabo maiores?
+
+ Go
+
+
+ Branding
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum
+ libero enim nisi aliquam consectetur expedita magni eius ex corrupti
+ animi! Ad nam pariatur assumenda quae mollitia libero repellat
+ explicabo maiores?
+
+ Go
+
+
+ Branding
+
+ Lorem ipsum dolor sit amet consectetur adipisicing elit. Nostrum
+ libero enim nisi aliquam consectetur expedita magni eius ex corrupti
+ animi! Ad nam pariatur assumenda quae mollitia libero repellat
+ explicabo maiores?
+
+ Go
+
+
+
+ );
+};
+
+export default Services;
diff --git a/src/components/services/services.scss b/src/components/services/services.scss
new file mode 100644
index 000000000..f7065e736
--- /dev/null
+++ b/src/components/services/services.scss
@@ -0,0 +1,146 @@
+@import "../../app.scss";
+.services {
+ background: linear-gradient(180deg, #0c0c1d, #111132);
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ .textContainer {
+ flex: 1;
+ align-self: flex-end;
+ display: flex;
+ align-items: center;
+ gap: 20px;
+
+ @include mobile {
+ align-self: center;
+ text-align: center;
+ flex-direction: column;
+ }
+
+ p {
+ font-weight: 200;
+ font-size: 20px;
+ color: gray;
+ text-align: right;
+ }
+
+ hr {
+ width: 500px;
+ border: none;
+ border-top: 0.5px solid gray;
+
+ @include mobile {
+ width: 300px;
+ }
+ }
+ }
+ .titleContainer {
+ flex: 2;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+
+ @include mobile {
+ width: 100%;
+ }
+
+ .title {
+ display: flex;
+ align-items: center;
+ gap: 50px;
+
+ @include mobile {
+ flex-direction: column;
+ text-align: center;
+ gap: 20px;
+ }
+
+ img {
+ width: 300px;
+ height: 100px;
+ border-radius: 50px;
+ object-fit: cover;
+
+ @include mobile {
+ width: 200px;
+ height: 50px;
+ }
+ }
+
+ h1 {
+ font-size: 96px;
+ font-weight: 100;
+
+ @include mobile {
+ font-size: 36px;
+ }
+ }
+
+ button {
+ width: 300px;
+ height: 100px;
+ border-radius: 50px;
+ background-color: orange;
+ border: none;
+ font-size: 24px;
+ cursor: pointer;
+
+ @include mobile {
+ font-size: 16px;
+ width: 150px;
+ height: 50px;
+ }
+ }
+ }
+ }
+ .listContainer {
+ flex: 2;
+ display: flex;
+ max-width: 1366px;
+ margin: auto;
+
+ @include mobile {
+ flex-direction: column;
+ width: 100%;
+ }
+
+ .box {
+ padding: 50px;
+ border: 0.5px solid gray;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+
+ @include mobile {
+ border: none;
+ align-items: center;
+ gap: 20px;
+ padding: 10px;
+ }
+
+ p {
+ @include mobile {
+ display: none;
+ }
+ }
+
+ button {
+ padding: 10px;
+ background-color: orange;
+ border: none;
+ cursor: pointer;
+
+ @include mobile {
+ background-color: transparent;
+ border: 1px solid orange;
+ border-radius: 5px;
+ color: orange;
+ width: 50%;
+ padding: 5px;
+ }
+ }
+ }
+ }
+}
diff --git a/src/components/sidebar/Sidebar.jsx b/src/components/sidebar/Sidebar.jsx
new file mode 100644
index 000000000..fda341548
--- /dev/null
+++ b/src/components/sidebar/Sidebar.jsx
@@ -0,0 +1,38 @@
+import { useState } from "react";
+import { motion } from "framer-motion";
+import Links from "./links/Links";
+import "./sidebar.scss";
+import ToggleButton from "./toggleButton/ToggleButton";
+
+const variants = {
+ open: {
+ clipPath: "circle(1200px at 50px 50px)",
+ transition: {
+ type: "spring",
+ stiffness: 20,
+ },
+ },
+ closed: {
+ clipPath: "circle(30px at 50px 50px)",
+ transition: {
+ delay: 0.5,
+ type: "spring",
+ stiffness: 400,
+ damping: 40,
+ },
+ },
+};
+const Sidebar = () => {
+ const [open, setOpen] = useState(false);
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default Sidebar;
diff --git a/src/components/sidebar/links/Links.jsx b/src/components/sidebar/links/Links.jsx
new file mode 100644
index 000000000..57056bdd1
--- /dev/null
+++ b/src/components/sidebar/links/Links.jsx
@@ -0,0 +1,47 @@
+import { motion } from "framer-motion";
+
+const variants = {
+ open: {
+ transition: {
+ staggerChildren: 0.1,
+ },
+ },
+ closed: {
+ transition: {
+ staggerChildren: 0.05,
+ staggerDirection: -1,
+ },
+ },
+};
+const itemVariants = {
+ open: {
+ y: 0,
+ opacity: 1,
+ },
+ closed: {
+ y: 50,
+ opacity: 0,
+ },
+};
+
+const Links = () => {
+ const items = ["Homepage", "Services", "Portfolio", "Contact", "About"];
+
+ return (
+
+ {items.map((item) => (
+
+ {item}
+
+ ))}
+
+ );
+};
+
+export default Links;
diff --git a/src/components/sidebar/sidebar.scss b/src/components/sidebar/sidebar.scss
new file mode 100644
index 000000000..8c34531a3
--- /dev/null
+++ b/src/components/sidebar/sidebar.scss
@@ -0,0 +1,56 @@
+@import "../../app.scss";
+.sidebar {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background-color: white;
+ color: black;
+
+ .bg {
+ z-index: 999;
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 400px;
+ background: white;
+
+ @include mobile {
+ width: 200px;
+ }
+
+ .links {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 20px;
+
+ a {
+ font-size: 40px;
+
+ @include mobile {
+ font-size: 20px;
+ }
+ }
+ }
+ }
+
+ button {
+ z-index: 999;
+ position: fixed;
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+ position: fixed;
+ top: 25px;
+ left: 25px;
+ background-color: transparent;
+ border: none;
+ cursor: pointer;
+ }
+}
diff --git a/src/components/sidebar/toggleButton/ToggleButton.jsx b/src/components/sidebar/toggleButton/ToggleButton.jsx
new file mode 100644
index 000000000..012729ef6
--- /dev/null
+++ b/src/components/sidebar/toggleButton/ToggleButton.jsx
@@ -0,0 +1,40 @@
+import { motion } from "framer-motion";
+
+const ToggleButton = ({ setOpen }) => {
+ return (
+ setOpen((prev) => !prev)}>
+
+
+
+
+
+
+ );
+};
+
+export default ToggleButton;