diff --git a/package-lock.json b/package-lock.json index 0fbeeeb..bab389f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@reduxjs/toolkit": "^1.9.3", "axios": "^1.3.5", "framer-motion": "^10.12.2", + "graphql-request": "^6.1.0", "nuka-carousel": "^6.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -21,6 +22,7 @@ "react-icons": "^4.8.0", "react-intersection-observer": "^9.4.3", "react-redux": "^8.0.5", + "react-router-dom": "^6.21.0", "react-scroll-parallax": "^3.4.2", "react-use-scroll-direction": "^0.1.0", "tailwind-merge": "^1.12.0" @@ -35,6 +37,7 @@ "eslint": "^8.37.0", "eslint-config-react-app": "^7.0.1", "postcss": "^8.4.21", + "react-error-overlay": "^6.0.9", "sass": "^1.61.0", "tailwindcss": "^3.3.1", "typescript": "^4.9.3", @@ -3653,6 +3656,14 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -3838,6 +3849,14 @@ } } }, + "node_modules/@remix-run/router": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.0.tgz", + "integrity": "sha512-WOHih+ClN7N8oHk9N4JUiMxQJmRVaOxcg8w7F/oHUXzJt920ekASLI/7cYX8XkntDWRhLZtsk6LbGrkgOAvi5A==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/pluginutils": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", @@ -5007,6 +5026,14 @@ "node": ">=10" } }, + "node_modules/cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -6309,6 +6336,27 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "node_modules/graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -7121,6 +7169,25 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-releases": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", @@ -7655,6 +7722,12 @@ "react": "^18.2.0" } }, + "node_modules/react-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", + "dev": true + }, "node_modules/react-fast-compare": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.1.tgz", @@ -7837,6 +7910,36 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" }, + "node_modules/react-router": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.0.tgz", + "integrity": "sha512-hGZ0HXbwz3zw52pLZV3j3+ec+m/PQ9cTpBvqjFQmy2XVUWGn5MD+31oXHb6dVTxYzmAeaiUBYjkoNz66n3RGCg==", + "dependencies": { + "@remix-run/router": "1.14.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.0.tgz", + "integrity": "sha512-1dUdVj3cwc1npzJaf23gulB562ESNvxf7E4x8upNJycqyUm5BRRZ6dd3LrlzhtLaMrwOCO8R0zoiYxdaJx4LlQ==", + "dependencies": { + "@remix-run/router": "1.14.0", + "react-router": "6.21.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scroll-parallax": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/react-scroll-parallax/-/react-scroll-parallax-3.4.2.tgz", @@ -8550,6 +8653,11 @@ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -8871,6 +8979,20 @@ "fsevents": "~2.3.2" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -11496,6 +11618,12 @@ "integrity": "sha512-x5vzdtOOGgFVDCUs81QRB2+liax8rFg3+7hqM+QhBG0/G3F1ZsoYl97UrqgHgQ9KKT7G6c4V+aTUCgu/n22v1A==", "dev": true }, + "@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "requires": {} + }, "@humanwhocodes/config-array": { "version": "0.11.8", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", @@ -11635,6 +11763,11 @@ "reselect": "^4.1.7" } }, + "@remix-run/router": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.14.0.tgz", + "integrity": "sha512-WOHih+ClN7N8oHk9N4JUiMxQJmRVaOxcg8w7F/oHUXzJt920ekASLI/7cYX8XkntDWRhLZtsk6LbGrkgOAvi5A==" + }, "@rollup/pluginutils": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", @@ -12493,6 +12626,14 @@ "yaml": "^1.10.0" } }, + "cross-fetch": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", + "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", + "requires": { + "node-fetch": "^2.6.12" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -13479,6 +13620,21 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphql": { + "version": "16.8.1", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", + "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "peer": true + }, + "graphql-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", + "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", + "requires": { + "@graphql-typed-document-node/core": "^3.2.0", + "cross-fetch": "^3.1.5" + } + }, "has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -14067,6 +14223,14 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "node-releases": { "version": "2.0.10", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", @@ -14419,6 +14583,12 @@ "scheduler": "^0.23.0" } }, + "react-error-overlay": { + "version": "6.0.9", + "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.9.tgz", + "integrity": "sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew==", + "dev": true + }, "react-fast-compare": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.1.tgz", @@ -14535,6 +14705,23 @@ } } }, + "react-router": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.21.0.tgz", + "integrity": "sha512-hGZ0HXbwz3zw52pLZV3j3+ec+m/PQ9cTpBvqjFQmy2XVUWGn5MD+31oXHb6dVTxYzmAeaiUBYjkoNz66n3RGCg==", + "requires": { + "@remix-run/router": "1.14.0" + } + }, + "react-router-dom": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.21.0.tgz", + "integrity": "sha512-1dUdVj3cwc1npzJaf23gulB562ESNvxf7E4x8upNJycqyUm5BRRZ6dd3LrlzhtLaMrwOCO8R0zoiYxdaJx4LlQ==", + "requires": { + "@remix-run/router": "1.14.0", + "react-router": "6.21.0" + } + }, "react-scroll-parallax": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/react-scroll-parallax/-/react-scroll-parallax-3.4.2.tgz", @@ -15044,6 +15231,11 @@ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -15248,6 +15440,20 @@ } } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index e6c3e9b..3a44569 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "@reduxjs/toolkit": "^1.9.3", "axios": "^1.3.5", "framer-motion": "^10.12.2", + "graphql-request": "^6.1.0", "nuka-carousel": "^6.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -22,6 +23,7 @@ "react-icons": "^4.8.0", "react-intersection-observer": "^9.4.3", "react-redux": "^8.0.5", + "react-router-dom": "^6.21.0", "react-scroll-parallax": "^3.4.2", "react-use-scroll-direction": "^0.1.0", "tailwind-merge": "^1.12.0" @@ -36,6 +38,7 @@ "eslint": "^8.37.0", "eslint-config-react-app": "^7.0.1", "postcss": "^8.4.21", + "react-error-overlay": "^6.0.9", "sass": "^1.61.0", "tailwindcss": "^3.3.1", "typescript": "^4.9.3", diff --git a/src/App.tsx b/src/App.tsx index 81fe9e5..0ad3a38 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import Skills from './modules/Skills' import ParallaxBg from './modules/ParallaxBg'; import MyProjects from './modules/MyProjects'; import Experience from './modules/Experience'; +import ScrollToAnchor from "@/components/ScrollToAnchor"; function App() { @@ -30,6 +31,10 @@ function App() { + + {/* Scroll to anchor element solution */} + + ) } diff --git a/src/UI/Link.tsx b/src/UI/Link.tsx index 6c5f016..55e7c97 100644 --- a/src/UI/Link.tsx +++ b/src/UI/Link.tsx @@ -1,11 +1,14 @@ import React, { FC } from 'react' import { twMerge } from 'tailwind-merge' +import { Link as RouterLink } from 'react-router-dom' interface LinkProps extends React.DetailedHTMLProps, HTMLAnchorElement>{ - newTab?: boolean + newTab?: boolean, + to: string, + ref?: React.RefObject, } -const Link: FC = ({children, newTab=false, className, ...props}) => { +const Link: FC = ({children, newTab= false, className, ...props}) => { const classes = twMerge( 'text-lm-primaryText dark:text-dm-primaryText text-base hover:shadow-[0_1px_0_0_currentcolor]', 'transition ease-in-out duration-300', @@ -15,9 +18,9 @@ const Link: FC = ({children, newTab=false, className, ...props}) => { return ( {newTab? - {children} + {children} : - {children} + {children} } ) diff --git a/src/assets/api-gateway.png b/src/assets/api-gateway.png new file mode 100644 index 0000000..b767128 Binary files /dev/null and b/src/assets/api-gateway.png differ diff --git a/src/assets/cdesk-1.png b/src/assets/cdesk-1.png new file mode 100644 index 0000000..c6de37f Binary files /dev/null and b/src/assets/cdesk-1.png differ diff --git a/src/assets/cdesk-2.jpg b/src/assets/cdesk-2.jpg new file mode 100644 index 0000000..b171b93 Binary files /dev/null and b/src/assets/cdesk-2.jpg differ diff --git a/src/assets/cdesk-3.jpg b/src/assets/cdesk-3.jpg new file mode 100644 index 0000000..f1159ca Binary files /dev/null and b/src/assets/cdesk-3.jpg differ diff --git a/src/assets/cloudfront.jpg b/src/assets/cloudfront.jpg new file mode 100644 index 0000000..e4d9e53 Binary files /dev/null and b/src/assets/cloudfront.jpg differ diff --git a/src/assets/cognito.jpg b/src/assets/cognito.jpg new file mode 100644 index 0000000..62bcd3b Binary files /dev/null and b/src/assets/cognito.jpg differ diff --git a/src/assets/ec2.jpg b/src/assets/ec2.jpg new file mode 100644 index 0000000..b611ae7 Binary files /dev/null and b/src/assets/ec2.jpg differ diff --git a/src/assets/lambda.png b/src/assets/lambda.png new file mode 100644 index 0000000..9c6f8d5 Binary files /dev/null and b/src/assets/lambda.png differ diff --git a/src/assets/livesta-1.png b/src/assets/livesta-1.png index 5d2782d..c6be08b 100644 Binary files a/src/assets/livesta-1.png and b/src/assets/livesta-1.png differ diff --git a/src/assets/livesta-2.png b/src/assets/livesta-2.png index 6467789..50686c3 100644 Binary files a/src/assets/livesta-2.png and b/src/assets/livesta-2.png differ diff --git a/src/assets/route-53.png b/src/assets/route-53.png new file mode 100644 index 0000000..fbfe6d4 Binary files /dev/null and b/src/assets/route-53.png differ diff --git a/src/assets/s3.png b/src/assets/s3.png new file mode 100644 index 0000000..0888f8e Binary files /dev/null and b/src/assets/s3.png differ diff --git a/src/assets/vpc.png b/src/assets/vpc.png new file mode 100644 index 0000000..cb8f35a Binary files /dev/null and b/src/assets/vpc.png differ diff --git a/src/assets/vs1.png b/src/assets/vs1.png index b8d274e..7e1961d 100644 Binary files a/src/assets/vs1.png and b/src/assets/vs1.png differ diff --git a/src/assets/vs2.png b/src/assets/vs2.png index 32b467f..efcf3df 100644 Binary files a/src/assets/vs2.png and b/src/assets/vs2.png differ diff --git a/src/assets/vs3.png b/src/assets/vs3.png index ba6f0dc..c0d7ce7 100644 Binary files a/src/assets/vs3.png and b/src/assets/vs3.png differ diff --git a/src/components/ScrollToAnchor.tsx b/src/components/ScrollToAnchor.tsx new file mode 100644 index 0000000..b403f78 --- /dev/null +++ b/src/components/ScrollToAnchor.tsx @@ -0,0 +1,26 @@ +import { useEffect, useRef } from 'react'; +import { useLocation } from 'react-router-dom'; + +function ScrollToAnchor() { + const location = useLocation(); + const lastHash = useRef(''); + + useEffect(() => { + if (location.hash) { + lastHash.current = location.hash.slice(1); // safe hash for further use after navigation + } + + if (lastHash.current && document.getElementById(lastHash.current)) { + setTimeout(() => { + document + .getElementById(lastHash.current) + ?.scrollIntoView({ behavior: 'smooth', block: 'start' }); + lastHash.current = ''; + }, 100); + } + }, [location]); + + return null; +} + +export default ScrollToAnchor; \ No newline at end of file diff --git a/src/components/Stepper/Stepper.tsx b/src/components/Stepper/Stepper.tsx index 60dd414..3749db2 100644 --- a/src/components/Stepper/Stepper.tsx +++ b/src/components/Stepper/Stepper.tsx @@ -3,7 +3,9 @@ import classes from './Stepper.module.scss' export interface StepperItem { time: string, + range?: string, title: string, + link?: string, description: string, } @@ -21,15 +23,22 @@ const Stepper: FC = ({items, className, ...props}) => { " before:dark:bg-dm-primary-100 after:dark:bg-dm-primary-100 after:dark:border-dm-primary-100" }>

- {item.title} + + {item.title} +

{item.description}

- +
+ + +
)} diff --git a/src/components/ThemeToggle.tsx b/src/components/ThemeToggle.tsx index a93f9d5..7a8fc90 100644 --- a/src/components/ThemeToggle.tsx +++ b/src/components/ThemeToggle.tsx @@ -20,7 +20,7 @@ const ThemeToggle: FC = ({ onDarkClick, onLightClick, size='me const textSize = {small: 'text-sm', medium: 'text-base', large: 'text-lg'} return ( - +