├── src ├── utils │ ├── theme.js │ ├── index.js │ ├── scroll.js │ ├── typography.js │ ├── GlobalStyles.styled.js │ └── colors.js ├── pages │ ├── About │ │ ├── index.js │ │ ├── AboutItem.jsx │ │ ├── About.styled.js │ │ ├── SkillBall.jsx │ │ ├── AboutItem.styled.js │ │ └── About.jsx │ ├── home │ │ ├── index.js │ │ ├── Dog.jsx │ │ ├── Home.jsx │ │ └── Home.styled.js │ ├── Contact │ │ ├── index.js │ │ ├── Contact.styled.js │ │ └── Contact.jsx │ ├── Experience │ │ ├── index.js │ │ ├── ExperienceLayout.styled.js │ │ ├── ExperienceItem.jsx │ │ ├── Experience.jsx │ │ └── ExperienceItem.styled.js │ └── Projects │ │ ├── index.js │ │ ├── Projects.styled.js │ │ ├── Projects.jsx │ │ ├── ProjectItem.jsx │ │ ├── carasoulButton.jsx │ │ └── ProjectItem.styled.js ├── context │ ├── index.js │ └── NavbarContext.js ├── data │ ├── index.js │ ├── experiences.js │ └── projects.js ├── hooks │ ├── index.js │ ├── useScreenWidth.js │ └── useIsMobile.js ├── assets │ ├── 3d │ │ └── dog3.glb │ ├── images │ │ ├── RBL.png │ │ ├── dyp.png │ │ ├── sos.png │ │ ├── draic.png │ │ ├── genio.jpeg │ │ ├── get-v.jpg │ │ ├── image2.png │ │ ├── scroll.jpg │ │ ├── stonks.png │ │ ├── sendform.jpg │ │ ├── stealth.jpeg │ │ ├── highschool.jpeg │ │ └── semicolon.png │ └── index.css ├── components │ ├── form │ │ ├── index.js │ │ ├── CloseButton.js │ │ ├── Input.styled.js │ │ ├── Textarea.js │ │ └── Button.styled.js │ ├── ui │ │ ├── index.js │ │ ├── Grid.js │ │ ├── NavbarItem.styled.js │ │ ├── Logo.jsx │ │ ├── PageHeader.jsx │ │ └── peguin.jsx │ ├── Navbar.styled.js │ ├── Page.jsx │ └── Navbar.jsx ├── main.jsx └── App.jsx ├── public ├── logo.png ├── favicon.ico ├── favicon-16x16.png ├── favicon-32x32.png ├── apple-touch-icon.png ├── android-chrome-192x192.png ├── android-chrome-512x512.png ├── site.webmanifest └── vite.svg ├── vite.config.js ├── .gitignore ├── package.json ├── README.md ├── index.html └── LICENSE /src/utils/theme.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/pages/About/index.js: -------------------------------------------------------------------------------- 1 | export * from "./About"; 2 | -------------------------------------------------------------------------------- /src/pages/home/index.js: -------------------------------------------------------------------------------- 1 | export * from "./Home"; 2 | -------------------------------------------------------------------------------- /src/context/index.js: -------------------------------------------------------------------------------- 1 | export * from "./NavbarContext"; 2 | -------------------------------------------------------------------------------- /src/pages/Contact/index.js: -------------------------------------------------------------------------------- 1 | export * from "./Contact"; 2 | -------------------------------------------------------------------------------- /src/pages/Experience/index.js: -------------------------------------------------------------------------------- 1 | export * from "./Experience"; 2 | -------------------------------------------------------------------------------- /src/pages/Projects/index.js: -------------------------------------------------------------------------------- 1 | export * from "./Projects"; 2 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/public/logo.png -------------------------------------------------------------------------------- /src/data/index.js: -------------------------------------------------------------------------------- 1 | export * from "./experiences"; 2 | export * from "./projects"; 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /src/hooks/index.js: -------------------------------------------------------------------------------- 1 | export * from "./useIsMobile"; 2 | export * from "./useScreenWidth"; 3 | -------------------------------------------------------------------------------- /src/assets/3d/dog3.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/3d/dog3.glb -------------------------------------------------------------------------------- /public/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/public/favicon-16x16.png -------------------------------------------------------------------------------- /public/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/public/favicon-32x32.png -------------------------------------------------------------------------------- /src/assets/images/RBL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/RBL.png -------------------------------------------------------------------------------- /src/assets/images/dyp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/dyp.png -------------------------------------------------------------------------------- /src/assets/images/sos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/sos.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/public/apple-touch-icon.png -------------------------------------------------------------------------------- /src/assets/images/draic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/draic.png -------------------------------------------------------------------------------- /src/assets/images/genio.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/genio.jpeg -------------------------------------------------------------------------------- /src/assets/images/get-v.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/get-v.jpg -------------------------------------------------------------------------------- /src/assets/images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/image2.png -------------------------------------------------------------------------------- /src/assets/images/scroll.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/scroll.jpg -------------------------------------------------------------------------------- /src/assets/images/stonks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/stonks.png -------------------------------------------------------------------------------- /src/assets/images/sendform.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/sendform.jpg -------------------------------------------------------------------------------- /src/assets/images/stealth.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/stealth.jpeg -------------------------------------------------------------------------------- /public/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/public/android-chrome-192x192.png -------------------------------------------------------------------------------- /public/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/public/android-chrome-512x512.png -------------------------------------------------------------------------------- /src/assets/images/highschool.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/highschool.jpeg -------------------------------------------------------------------------------- /src/assets/images/semicolon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teshank2137/portfolio/HEAD/src/assets/images/semicolon.png -------------------------------------------------------------------------------- /src/context/NavbarContext.js: -------------------------------------------------------------------------------- 1 | import { createContext } from "react"; 2 | 3 | export const NavbarContext = createContext(); 4 | -------------------------------------------------------------------------------- /src/utils/index.js: -------------------------------------------------------------------------------- 1 | export * from "./colors"; 2 | export * from "./GlobalStyles.styled"; 3 | export * from "./scroll"; 4 | export * from "./typography"; 5 | -------------------------------------------------------------------------------- /src/components/form/index.js: -------------------------------------------------------------------------------- 1 | export * from "./Button.styled"; 2 | export * from "./CloseButton"; 3 | export * from "./Input.styled"; 4 | export * from "./Textarea"; 5 | -------------------------------------------------------------------------------- /src/utils/scroll.js: -------------------------------------------------------------------------------- 1 | import ASScroll from "@ashthornton/asscroll"; 2 | 3 | export const scroll = () => { 4 | const asscroll = new ASScroll(); 5 | asscroll.enable(); 6 | }; 7 | -------------------------------------------------------------------------------- /src/components/ui/index.js: -------------------------------------------------------------------------------- 1 | export * from "./Grid"; 2 | export * from "./Logo"; 3 | export * from "./NavbarItem.styled"; 4 | export * from "./PageHeader"; 5 | export * from "./peguin"; 6 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import react from "@vitejs/plugin-react"; 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | assetsInclude: ["**/*.glb"], 8 | }); 9 | -------------------------------------------------------------------------------- /src/hooks/useScreenWidth.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | export const useScreenWidth = () => { 4 | const [width, setWidth] = useState(window.innerWidth); 5 | 6 | window.addEventListener("resize", () => { 7 | setWidth(window.innerWidth); 8 | }); 9 | 10 | return { width }; 11 | }; 12 | -------------------------------------------------------------------------------- /src/components/ui/Grid.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const Grid = styled.div` 4 | display: grid; 5 | grid-template-columns: repeat( 6 | ${(props) => (props.columns ? props.columns : "12")}, 7 | 1fr 8 | ); 9 | grid-gap: ${(props) => (props.gap ? props.gap : "1rem")}; 10 | `; 11 | -------------------------------------------------------------------------------- /src/components/form/CloseButton.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const CloseButton = styled.button` 4 | all: unset; 5 | padding: 0.5rem; 6 | position: absolute; 7 | right: 1rem; 8 | cursor: pointer; 9 | @media screen and (min-width: 720px) { 10 | display: none; 11 | } 12 | `; 13 | -------------------------------------------------------------------------------- /src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App"; 4 | import "./assets/index.css"; 5 | import { GlobalStyles } from "./utils"; 6 | 7 | ReactDOM.createRoot(document.getElementById("root")).render( 8 | 9 | 10 | 11 | 12 | ); 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /src/utils/typography.js: -------------------------------------------------------------------------------- 1 | export const typeScale = { 2 | bigDisplay: "5.61rem", 3 | display: "4.209rem", 4 | headline: "3.157rem", 5 | title: "2.369rem", 6 | subtitle: "1.777rem", 7 | text: "1.333rem", 8 | paragraph: "1rem", 9 | helperText: "0.75rem", 10 | copyrightText: "0.563rem", 11 | }; 12 | 13 | export const primaryFont = "'Roboto Mono', monospace;"; 14 | -------------------------------------------------------------------------------- /src/hooks/useIsMobile.js: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | import { useScreenWidth } from "./useScreenWidth"; 3 | 4 | export const useIsMobile = () => { 5 | const { width } = useScreenWidth(); 6 | const [isMobile, setIsMobile] = useState(width < 720); 7 | 8 | useEffect(() => { 9 | if (width < 720) { 10 | setIsMobile(true); 11 | } else { 12 | setIsMobile(false); 13 | } 14 | }, [width]); 15 | 16 | return { isMobile }; 17 | }; 18 | -------------------------------------------------------------------------------- /src/pages/About/AboutItem.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { AboutItemWrapper } from "./AboutItem.styled"; 3 | 4 | export const AboutItem = ({ color, active, data }) => { 5 | return ( 6 | 7 |
8 | {data.title} 9 |
10 |
11 |

{data.title}

12 |

{data.p}

13 |
14 |
15 | ); 16 | }; 17 | -------------------------------------------------------------------------------- /public/site.webmanifest: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Teshank Raut Portfolio", 3 | "short_name": "Teshank Raut", 4 | "icons": [ 5 | { 6 | "src": "/android-chrome-192x192.png", 7 | "sizes": "192x192", 8 | "type": "image/png" 9 | }, 10 | { 11 | "src": "/android-chrome-512x512.png", 12 | "sizes": "512x512", 13 | "type": "image/png" 14 | } 15 | ], 16 | "start_url": ".", 17 | "display": "standalone", 18 | "theme_color": "#000000", 19 | "background_color": "#ffffff" 20 | } -------------------------------------------------------------------------------- /src/pages/Experience/ExperienceLayout.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledExperienceLayout = styled.div` 4 | grid-column: 2/ 12; 5 | align-self: start; 6 | display: flex; 7 | justify-content: center; 8 | align-items: center; 9 | gap: 1.2rem; 10 | height: 100%; 11 | @media screen and (max-width: 720px) { 12 | grid-column: 1 / 7; 13 | padding-inline: 1rem; 14 | display: grid; 15 | grid-template-columns: repeat(3, 1fr); 16 | grid-template-rows: 2fr 1fr 1fr; 17 | align-items: start; 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /src/components/form/Input.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { typeScale } from "../../utils"; 3 | 4 | export const Input = styled.input` 5 | padding: 0.75rem 1rem; 6 | font-size: ${typeScale.paragraph}; 7 | background-color: #eef2; 8 | width: ${(props) => (props.full ? "100%" : "auto")}; 9 | outline: none; 10 | border: 3px solid black; 11 | box-shadow: 8px 8px 0 black; 12 | border-radius: 0.5rem; 13 | transition: all 0.1s ease; 14 | &:focus, 15 | &:active { 16 | background-color: #eef3; 17 | box-shadow: 6px 6px 0 black; 18 | } 19 | `; 20 | -------------------------------------------------------------------------------- /src/App.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Navbar } from "./components/Navbar"; 3 | import { About } from "./pages/About"; 4 | import { Contact } from "./pages/Contact"; 5 | import { Experience } from "./pages/Experience"; 6 | import { Home } from "./pages/home"; 7 | import { Projects } from "./pages/Projects"; 8 | 9 | function App() { 10 | return ( 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | ); 21 | } 22 | 23 | export default App; 24 | -------------------------------------------------------------------------------- /src/components/form/Textarea.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { typeScale } from "../../utils"; 3 | 4 | export const Textarea = styled.textarea` 5 | resize: none; 6 | padding: 0.75rem 1rem; 7 | font-size: ${typeScale.paragraph}; 8 | background-color: #eef2; 9 | width: ${(props) => (props.full ? "100%" : "auto")}; 10 | height: ${(props) => 11 | props.lines ? `calc(${props.lines}*${typeScale.paragraph})` : "auto"}; 12 | outline: none; 13 | border: 3px solid black; 14 | box-shadow: 8px 8px 0 black; 15 | border-radius: 0.5rem; 16 | transition: all 0.1s ease; 17 | &:focus, 18 | &:active { 19 | background-color: #eef3; 20 | box-shadow: 6px 6px 0 black; 21 | } 22 | `; 23 | -------------------------------------------------------------------------------- /src/pages/Experience/ExperienceItem.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { StyledExperienceItem } from "./ExperienceItem.styled"; 3 | 4 | export const ExperienceItem = (props) => { 5 | const { data } = props; 6 | return ( 7 | 8 |
9 |
10 |
11 | logo 12 |
13 |
14 |
15 |

{data.name}

16 |

{data.title}

17 |
18 |
19 |
20 | {data.joined} - {data.end} 21 |
22 |

{data.bio}

23 |
24 | ); 25 | }; 26 | -------------------------------------------------------------------------------- /src/utils/GlobalStyles.styled.js: -------------------------------------------------------------------------------- 1 | import { normalize } from "polished"; 2 | import { createGlobalStyle } from "styled-components"; 3 | import { primaryFont } from "./typography"; 4 | 5 | export const GlobalStyles = createGlobalStyle` 6 | ${normalize()} 7 | :root { 8 | font-size: 16px; 9 | line-height: 24px; 10 | font-family: ${primaryFont}; 11 | color-scheme: light dark; 12 | color: rgba(255, 255, 255, 0.87); 13 | background-color: #1f1f1f; 14 | 15 | font-synthesis: none; 16 | text-rendering: optimizeLegibility; 17 | -webkit-font-smoothing: antialiased; 18 | -moz-osx-font-smoothing: grayscale; 19 | -webkit-text-size-adjust: 100%; 20 | } 21 | 22 | *, *::after, *::before{ 23 | box-sizing: border-box; 24 | margin: 0; 25 | padding:0; 26 | text-decoration: none; 27 | } 28 | 29 | body { 30 | margin: 0; 31 | min-height: 100vh; 32 | } 33 | `; 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-app", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@ashthornton/asscroll": "^2.0.11", 13 | "@react-three/drei": "^9.43.3", 14 | "@react-three/fiber": "^8.9.1", 15 | "gsap": "^3.11.3", 16 | "polished": "^4.2.2", 17 | "react": "^18.2.0", 18 | "react-dom": "^18.2.0", 19 | "react-icons": "^4.6.0", 20 | "react-intersection-observer": "^9.4.1", 21 | "styled-components": "^5.3.6", 22 | "three": "^0.146.0", 23 | "three-spritetext": "^1.6.5" 24 | }, 25 | "devDependencies": { 26 | "@types/react": "^18.0.24", 27 | "@types/react-dom": "^18.0.8", 28 | "@vitejs/plugin-react": "^2.2.0", 29 | "vite": "^3.2.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/components/Navbar.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const StyledNavbar = styled.nav` 4 | position: fixed; 5 | top: 0; 6 | left: 50%; 7 | transform: translateX(-50%); 8 | padding: 1rem; 9 | z-index: 100; 10 | ul { 11 | display: flex; 12 | list-style: none; 13 | gap: 2rem; 14 | align-items: center; 15 | justify-content: center; 16 | } 17 | 18 | @media screen and (max-width: 720px) { 19 | left: 0; 20 | transform: translateX(-150%); 21 | width: 70vw; 22 | height: 100%; 23 | background-color: #12121233; 24 | backdrop-filter: blur(5px); 25 | transition: transform 0.2s ease-in-out; 26 | ul { 27 | flex-direction: column; 28 | align-items: flex-start; 29 | 30 | .home_navbar-item { 31 | order: -1; 32 | } 33 | } 34 | 35 | &.active { 36 | transform: translateX(0%); 37 | } 38 | } 39 | `; 40 | -------------------------------------------------------------------------------- /src/assets/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@100;200;300;400;500;600;700&family=Roboto:wght@400;500;700;900&display=swap'); 2 | :root { 3 | font-family: 'Roboto Mono', monospace; 4 | font-size: 16px; 5 | line-height: 24px; 6 | font-weight: 400; 7 | 8 | color-scheme: light dark; 9 | color: rgba(255, 255, 255, 0.87); 10 | background-color: #242424; 11 | 12 | font-synthesis: none; 13 | text-rendering: optimizeLegibility; 14 | -webkit-font-smoothing: antialiased; 15 | -moz-osx-font-smoothing: grayscale; 16 | -webkit-text-size-adjust: 100%; 17 | } 18 | 19 | *, *::after, *::before{ 20 | box-sizing: border-box; 21 | margin: 0; 22 | padding:0; 23 | text-decoration: none; 24 | } 25 | 26 | body { 27 | margin: 0; 28 | min-height: 100vh; 29 | } 30 | 31 | img{ 32 | width: 100%; 33 | } 34 | 35 | canvas { 36 | cursor: grab; 37 | } 38 | 39 | canvas:active{ 40 | cursor: grabbing; 41 | } -------------------------------------------------------------------------------- /src/pages/home/Dog.jsx: -------------------------------------------------------------------------------- 1 | import { OrbitControls } from "@react-three/drei"; 2 | import { useFrame, useLoader } from "@react-three/fiber"; 3 | import { useRef } from "react"; 4 | import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; 5 | import dog from "../../assets/3d/dog3.glb"; 6 | import { useIsMobile } from "../../hooks"; 7 | 8 | const Dog = () => { 9 | const { isMobile } = useIsMobile(); 10 | const gltf = useLoader(GLTFLoader, dog); 11 | const ref = useRef(); 12 | useFrame(() => { 13 | ref.current.rotation.y += 0.002; 14 | }); 15 | return ( 16 | <> 17 | 18 | 19 | 20 | {isMobile ? null : } 21 | 22 | 23 | ); 24 | }; 25 | 26 | export default Dog; 27 | -------------------------------------------------------------------------------- /src/pages/About/About.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { typeScale } from "../../utils"; 3 | 4 | export const Paragraph = styled.p` 5 | font-size: ${typeScale.text}; 6 | grid-column: 2/ 7; 7 | line-height: 2rem; 8 | padding-block: 2rem; 9 | @media screen and (max-width: 720px) { 10 | grid-column: 1 / 7; 11 | font-size: ${typeScale.paragraph}; 12 | line-height: 1.2rem; 13 | padding-block: 0rem; 14 | } 15 | `; 16 | 17 | export const Educations = styled.section` 18 | grid-column: 2/7; 19 | display: flex; 20 | gap: 0.75rem; 21 | align-self: start; 22 | padding-top: 1rem; 23 | `; 24 | 25 | export const Text = styled.aside` 26 | grid-column: 2/7; 27 | width: 100%; 28 | @media screen and (max-width: 720px) { 29 | grid-column: 1 / 7; 30 | padding-inline: 1rem; 31 | } 32 | `; 33 | 34 | export const SkillsWrapper = styled.aside` 35 | grid-column: 7/ 13; 36 | width: 100%; 37 | @media screen and (max-width: 720px) { 38 | grid-column: 1 / 7; 39 | } 40 | `; 41 | -------------------------------------------------------------------------------- /src/components/ui/NavbarItem.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { blue, typeScale } from "../../utils"; 3 | 4 | export const NavbarItem = styled.a` 5 | font-size: ${typeScale.text}; 6 | font-weight: semibold; 7 | color: #fff4; 8 | transition: all 0.2 ease-out; 9 | cursor: pointer; 10 | display: flex; 11 | flex-direction: column; 12 | align-items: center; 13 | position: relative; 14 | user-select: none; 15 | text-transform: capitalize; 16 | .dot { 17 | width: 8px; 18 | height: 8px; 19 | background-color: ${blue["60"]}; 20 | border-radius: 50%; 21 | position: absolute; 22 | bottom: -10px; 23 | left: 50%; 24 | transform: translateX(-50%); 25 | } 26 | &:hover, 27 | &:focus { 28 | color: #fffa; 29 | } 30 | 31 | &:active, 32 | &.active { 33 | color: #fff; 34 | } 35 | 36 | @media screen and (max-width: 720px) { 37 | margin-left: 0.5rem; 38 | color: #fff7; 39 | .dot { 40 | left: -15px; 41 | bottom: 50%; 42 | transform: translateY(50%); 43 | } 44 | } 45 | `; 46 | -------------------------------------------------------------------------------- /src/pages/Projects/Projects.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | 3 | export const ProjectContainer = styled.section` 4 | grid-column: 1/ 13; 5 | width: 100%; 6 | transition: transform 1s cubic-bezier(0.46, 0.35, 0, 1.27); 7 | align-self: center; 8 | .wrapper { 9 | scroll-behavior: smooth; 10 | flex-shrink: 0; 11 | display: flex; 12 | overflow-x: auto; 13 | justify-content: start; 14 | align-items: center; 15 | overflow-y: hidden; 16 | padding-inline-end: 2rem; 17 | background: linear-gradient(180deg); 18 | &::-webkit-scrollbar { 19 | display: none; 20 | } 21 | } 22 | @media screen and (max-width: 720px) { 23 | grid-column: 1 / 7; 24 | } 25 | `; 26 | 27 | export const Carasoul = styled.div` 28 | grid-column: 1/13; 29 | display: flex; 30 | justify-content: center; 31 | gap: 1rem; 32 | 33 | button { 34 | all: unset; 35 | cursor: pointer; 36 | padding: 0.5rem; 37 | } 38 | 39 | svg { 40 | width: 60px; 41 | } 42 | @media screen and (max-width: 720px) { 43 | grid-column: 1 / 7; 44 | } 45 | `; 46 | -------------------------------------------------------------------------------- /src/pages/Projects/Projects.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import { Page } from "../../components/Page"; 3 | import { projects } from "../../data"; 4 | import { NextButton } from "./carasoulButton"; 5 | import { ProjectItem } from "./ProjectItem"; 6 | import { Carasoul, ProjectContainer } from "./Projects.styled"; 7 | 8 | export const Projects = () => { 9 | const ref = useRef(null); 10 | 11 | const moveLeft = (e) => { 12 | console.log(ref.current.scrollLeft); 13 | document.querySelector(".wrapper").scrollLeft += 600; 14 | }; 15 | const moveRight = (e) => { 16 | document.querySelector(".wrapper").scrollLeft -= 650; 17 | }; 18 | 19 | return ( 20 | 21 | 22 |
23 | {projects.map((data, index) => ( 24 | 25 | ))} 26 |
27 |
28 | 29 | 30 | 31 | 32 |
33 | ); 34 | }; 35 | -------------------------------------------------------------------------------- /src/components/Page.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import styled from "styled-components"; 3 | import { Grid, PageHeader } from "./ui"; 4 | 5 | const StyledLayout = styled(Grid)` 6 | min-height: 100vh; 7 | padding-top: 120px; 8 | grid-template-rows: min-content auto; 9 | position: relative; 10 | overflow: hidden; 11 | .bg-text { 12 | position: absolute; 13 | top: 200px; 14 | font-size: 8rem; 15 | opacity: 0.2; 16 | font-weight: 800; 17 | right: 0; 18 | z-index: -10; 19 | transform: translateX(30%); 20 | text-transform: uppercase; 21 | font-family: "Roboto"; 22 | } 23 | 24 | @media screen and (max-width: 720px) { 25 | grid-template-columns: repeat(6, 1fr); 26 | padding-inline-start: 1rem; 27 | .bg-text { 28 | font-size: 5.5rem; 29 | } 30 | } 31 | `; 32 | 33 | export const Page = ({ children, header }) => { 34 | return ( 35 | 36 | <> 37 | {header.toUpperCase()} 38 | {children} 39 | 40 |
{header}
41 |
42 | ); 43 | }; 44 | -------------------------------------------------------------------------------- /src/pages/Projects/ProjectItem.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useInView } from "react-intersection-observer"; 3 | import { Button } from "../../components/form/"; 4 | import { Cube, Face } from "./ProjectItem.styled"; 5 | 6 | export const ProjectItem = ({ data, index }) => { 7 | const { ref, inView } = useInView(); 8 | return ( 9 | 10 | 11 |
12 |
13 |

{data.title}

14 |

{data.description}

15 |
16 | {data.github && ( 17 | 18 | 19 | 20 | )} 21 | {data.link && ( 22 | 23 | 24 | 25 | )} 26 |
27 |
28 |
29 | 30 |
{data.description}
31 |
32 | 33 |
{data.title}
34 |
35 |
36 | ); 37 | }; 38 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/utils/colors.js: -------------------------------------------------------------------------------- 1 | export const blue = { 2 | "00": "#071019", 3 | 10: "#14314C", 4 | 20: "#1A4165", 5 | 30: "#286198", 6 | 40: "#3582CA", 7 | 50: "#3B92E4", 8 | 60: "#42A2FD", 9 | 70: "#55ABFD", 10 | 80: "#68B5FD", 11 | 90: "#8EC7FE", 12 | 100: "#B3DAFE", 13 | 110: "#ECF6FF", 14 | }; 15 | 16 | export const red = { 17 | "00": "#120003", 18 | 10: "#35000A", 19 | 20: "#46000D", 20 | 30: "#6A0013", 21 | 40: "#8D001A", 22 | 50: "#9E001D", 23 | 60: "#B00020", 24 | 70: "#B81A36", 25 | 80: "#C0334D", 26 | 90: "#D06679", 27 | 100: "#DF99A6", 28 | 110: "#F7E6E9", 29 | }; 30 | 31 | export const green = { 32 | "00": "#061708", 33 | 10: "#114517", 34 | 20: "#165C1F", 35 | 30: "#22892E", 36 | 40: "#2DB73E", 37 | 50: "#2DB73E", 38 | 60: "#38E54D", 39 | 70: "#4CE85F", 40 | 80: "#60EA71", 41 | 90: "#88EF94", 42 | 100: "#AFF5B8", 43 | 110: "#EBFCED", 44 | }; 45 | 46 | export const yellow = { 47 | "00": "#191900", 48 | 10: "#4C4C00", 49 | 20: "#656600", 50 | 30: "#989900", 51 | 40: "#CACC00", 52 | 50: "#E4E600", 53 | 60: "#FDFF00", 54 | 70: "#FDFF1A", 55 | 80: "#FDFF33", 56 | 90: "#FEFF66", 57 | 100: "#FEFF99", 58 | 110: "#FFFFE6", 59 | }; 60 | 61 | export const pink = { 62 | "00": "#190C12", 63 | 10: "#4B2536", 64 | 20: "#643248", 65 | 30: "#974A6B", 66 | 40: "#C9638F", 67 | 50: "#E270A1", 68 | 60: "#FB7CB3", 69 | 70: "#FB89BB", 70 | 80: "#FC96C2", 71 | 90: "#FDB0D1", 72 | 100: "#FDCBE1", 73 | 110: "#FFF2F7", 74 | }; 75 | -------------------------------------------------------------------------------- /src/pages/Experience/Experience.jsx: -------------------------------------------------------------------------------- 1 | import gsap from "gsap"; 2 | import Flip from "gsap/Flip"; 3 | import React, { useEffect } from "react"; 4 | import { Page } from "../../components/Page"; 5 | import { experiences } from "../../data"; 6 | import { useScreenWidth } from "../../hooks"; 7 | import { ExperienceItem } from "./ExperienceItem"; 8 | import { StyledExperienceLayout } from "./ExperienceLayout.styled"; 9 | 10 | export const Experience = () => { 11 | const { width } = useScreenWidth(); 12 | 13 | useEffect(() => { 14 | gsap.registerPlugin(Flip); 15 | let cards = document.querySelectorAll(".experience-item"); 16 | cards.forEach((card, i) => { 17 | card.classList.remove("active"); 18 | if (i === 0) { 19 | card.classList.add("active"); 20 | } 21 | card.addEventListener(width < 720 ? "click" : "mouseenter", (e) => { 22 | if (card.classList.contains("active")) { 23 | return; 24 | } 25 | const state = Flip.getState(cards); 26 | cards.forEach((c) => { 27 | c.classList.remove("active"); 28 | }); 29 | card.classList.add("active"); 30 | Flip.from(state, { 31 | duration: 0.5, 32 | ease: "elastic.out(1,0.9)", 33 | absolute: true, 34 | }); 35 | }); 36 | }); 37 | }, [width]); 38 | return ( 39 | 40 | 41 | {experiences.map((exp, index) => ( 42 | 43 | ))} 44 | 45 | 46 | ); 47 | }; 48 | -------------------------------------------------------------------------------- /src/pages/home/Home.jsx: -------------------------------------------------------------------------------- 1 | import { Canvas } from "@react-three/fiber"; 2 | import React, { useContext, useEffect } from "react"; 3 | import { useInView } from "react-intersection-observer"; 4 | import { NavbarContext } from "../../context"; 5 | import Dog from "./Dog"; 6 | import { 7 | AnimatedSpan, 8 | DogContainer, 9 | HomeWrapper, 10 | Name, 11 | Position, 12 | TextContainer, 13 | } from "./Home.styled"; 14 | 15 | export const Home = () => { 16 | const { ref, inView } = useInView({ 17 | threshold: 1, 18 | }); 19 | 20 | const setPage = useContext(NavbarContext); 21 | 22 | useEffect(() => { 23 | if (inView) { 24 | setPage("home"); 25 | } 26 | }, [inView]); 27 | 28 | const produceSpans = (name) => { 29 | return name.split("").map((letter, index) => ( 30 | 38 | )); 39 | }; 40 | return ( 41 | 42 | 43 | Teshank Raut 44 | 45 |
46 | {produceSpans("Full Stack Developer")} 47 |
48 |
49 | {produceSpans("UI/UX Enthusiast")} 50 |
51 |
52 |
53 | 54 | 55 | 56 | 57 | 58 |
59 | ); 60 | }; 61 | -------------------------------------------------------------------------------- /src/pages/About/SkillBall.jsx: -------------------------------------------------------------------------------- 1 | import { useFrame, extend } from "@react-three/fiber"; 2 | import SpriteText from "three-spritetext"; 3 | import { OrbitControls } from "@react-three/drei"; 4 | import { useRef } from "react"; 5 | import { useIsMobile } from "../../hooks"; 6 | extend({ SpriteText }); 7 | 8 | const Skills = () => { 9 | const { isMobile } = useIsMobile(); 10 | const getPos = (k) => { 11 | let a = Math.random(); 12 | let b = Math.random(); 13 | return b > 0.5 ? a * k : a * -1 * k; 14 | }; 15 | const skills = [ 16 | "Python", 17 | "JavaScript", 18 | "TypeScript", 19 | "Dart", 20 | "HTML", 21 | "CSS", 22 | "Django", 23 | "Flutter", 24 | "ReactJs", 25 | "NextJS", 26 | "NodeJs", 27 | "ExpressJS", 28 | "ThreeJs", 29 | "Redux", 30 | ]; 31 | const g = useRef(); 32 | useFrame(() => { 33 | g.current.rotation.x += 0.00053; 34 | g.current.rotation.y += 0.00053; 35 | // g.current.rotation.z += 0.001; 36 | }); 37 | return ( 38 | <> 39 | {isMobile ? null : } 40 | 41 | 42 | {skills.map((a, i) => { 43 | return ( 44 | 52 | ); 53 | })} 54 | 55 | 56 | ); 57 | }; 58 | 59 | export default Skills; 60 | -------------------------------------------------------------------------------- /src/data/experiences.js: -------------------------------------------------------------------------------- 1 | import genio from "../assets/images/genio.jpeg"; 2 | import draic from "../assets/images/image2.png"; 3 | import rbl from "../assets/images/RBL.png"; 4 | import stealth from "../assets/images/stealth.jpeg"; 5 | 6 | import { blue, green, pink, yellow } from "../utils"; 7 | 8 | export const experiences = [ 9 | { 10 | logo: stealth, 11 | name: "Stealth Startup", 12 | joined: "Sept'22", 13 | end: "Feb'23", 14 | title: "Full Stack Developer", 15 | bio: "Utilized ExpressJS for backend authentication and rate limitation. The frontend ReactJS code was optimized, eliminating re-renders to enhance performance and user experience. A ReactJS and ExpressJS-based admin panel was developed for data visualization and transaction management.", 16 | color: blue, 17 | }, 18 | { 19 | logo: rbl, 20 | name: "RBL Bank", 21 | joined: "June'22", 22 | end: "July'22", 23 | title: "Summer Intern", 24 | bio: "Brainstormed various ideas with mentors and teammates for MoBank app. Developed HR portal backend using Django", 25 | color: green, 26 | }, 27 | { 28 | logo: genio, 29 | name: "GenioBits", 30 | joined: "Dec'21", 31 | end: "Mar'22", 32 | title: "Full Stack Developer", 33 | bio: "Worked on various projects from basic static sites to dynamic complex websites using ReactJS, Built Rest API's for various use cases", 34 | color: yellow, 35 | }, 36 | { 37 | logo: draic, 38 | name: "DRAIC", 39 | joined: "Sept'19", 40 | end: "Jan'22", 41 | title: "Team Member", 42 | bio: "In D.Y. Patil Robotics and A.I. club we developed collaborative skills. Built amazing projects and brainstormed on various problem statements", 43 | color: pink, 44 | }, 45 | ]; 46 | -------------------------------------------------------------------------------- /src/components/ui/Logo.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const Logo = ({ className }) => { 4 | return ( 5 |
6 | 7 | 12 | 13 | 21 | 29 | 30 | 35 | 43 | 51 | 52 | 53 | 54 |
55 | ); 56 | }; 57 | 58 | export default Logo; 59 | -------------------------------------------------------------------------------- /src/components/form/Button.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { blue, typeScale } from "../../utils"; 3 | 4 | export const Button = styled.button` 5 | all: unset; 6 | background-color: ${(props) => (props.bg ? props.bg["60"] : blue["60"])}; 7 | font-size: ${(props) => 8 | props.sm ? typeScale.helperText : typeScale.paragraph}; 9 | font-weight: bold; 10 | padding: ${(props) => (props.sm ? "0.1rem 1.2rem" : "0.15rem 1.8rem")}; 11 | 12 | min-width: 50px; 13 | min-height: 40px; 14 | border: 3px solid ${(props) => (props.bg ? props.bg["00"] : blue["00"])}; 15 | border-radius: 0.5rem; 16 | color: ${(props) => (props.bg ? props.bg["00"] : blue["00"])}; 17 | box-shadow: 8px 8px 0 ${(props) => (props.bg ? props.bg["00"] : blue["00"])}; 18 | cursor: pointer; 19 | transition: all 0.1s ease-in; 20 | display: flex; 21 | justify-content: center; 22 | align-items: center; 23 | 24 | &:hover { 25 | background-color: ${(props) => (props.bg ? props.bg["70"] : blue["70"])}; 26 | box-shadow: 10px 10px 0 27 | ${(props) => (props.bg ? props.bg["00"] : blue["00"])}; 28 | } 29 | 30 | &:active, 31 | &:focus { 32 | background-color: ${(props) => (props.bg ? props.bg["80"] : blue["80"])}; 33 | box-shadow: 4px 4px 0 ${(props) => (props.bg ? props.bg["00"] : blue["00"])}; 34 | } 35 | 36 | &:disabled { 37 | cursor: not-allowed; 38 | opacity: 0.5; 39 | box-shadow: 2px 2px 0 ${(props) => (props.bg ? props.bg["00"] : blue["00"])}; 40 | } 41 | `; 42 | 43 | export const MenuButton = styled.button` 44 | all: unset; 45 | cursor: pointer; 46 | position: fixed; 47 | z-index: 101; 48 | top: 0; 49 | left: 0; 50 | padding: 0.5rem; 51 | transition: 0.2s ease-in-out; 52 | transform: translateX(-150%); 53 | &.active { 54 | transform: translateX(0%); 55 | } 56 | @media screen and (min-width: 720px) { 57 | display: none; 58 | } 59 | `; 60 | -------------------------------------------------------------------------------- /src/pages/About/AboutItem.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { blue, typeScale } from "../../utils"; 3 | 4 | export const AboutItemWrapper = styled.div` 5 | overflow: hidden; 6 | background-color: ${(props) => 7 | props.color ? props.color["60"] : blue["60"]}; 8 | 9 | color: ${(props) => (props.color ? props.color["00"] : blue["00"])}; 10 | border: 4px solid ${(props) => (props.color ? props.color["00"] : blue["00"])}; 11 | box-shadow: 6px 6px 0 12 | ${(props) => (props.color ? props.color["00"] : blue["00"])}; 13 | border-radius: 1rem; 14 | width: 90px; 15 | height: 90px; 16 | aspect-ratio: 1/1; 17 | display: flex; 18 | justify-content: center; 19 | align-items: center; 20 | position: relative; 21 | cursor: pointer; 22 | 23 | .logo { 24 | min-width: 50px; 25 | width: 50px; 26 | height: 50px; 27 | border-radius: 50%; 28 | overflow: hidden; 29 | margin: 0.75rem; 30 | } 31 | .text { 32 | display: none; 33 | } 34 | 35 | &.active { 36 | width: 400px; 37 | justify-content: start; 38 | .text { 39 | min-width: max-content; 40 | display: block; 41 | overflow-wrap: break-word; 42 | min-width: unset; 43 | line-height: 1; 44 | h3 { 45 | font-size: ${typeScale.paragraph}; 46 | } 47 | p { 48 | margin-top: 4px; 49 | font-size: ${typeScale.helperText}; 50 | } 51 | } 52 | } 53 | @media screen and (max-width: 720px) { 54 | width: 70px; 55 | height: 70px; 56 | .logo { 57 | min-width: 45px; 58 | width: 45px; 59 | height: 45px; 60 | } 61 | &.active { 62 | width: 300px; 63 | .text { 64 | overflow-wrap: break-word; 65 | min-width: unset; 66 | line-height: 0.8rem; 67 | h3 { 68 | font-size: ${typeScale.helperText}; 69 | } 70 | p { 71 | font-size: ${typeScale.copyrightText}; 72 | } 73 | } 74 | } 75 | } 76 | `; 77 | -------------------------------------------------------------------------------- /src/pages/Contact/Contact.styled.js: -------------------------------------------------------------------------------- 1 | import styled from "styled-components"; 2 | import { Button } from "../../components/form"; 3 | 4 | export const ContactWrapper = styled.section` 5 | grid-column: 2/ 13; 6 | display: grid; 7 | grid-template-columns: repeat(11, 1fr); 8 | grid-gap: 1rem; 9 | .buttons { 10 | display: flex; 11 | grid-row: 2; 12 | grid-column: span 6; 13 | justify-content: space-between; 14 | align-items: flex-start; 15 | width: 100%; 16 | .socials { 17 | display: flex; 18 | gap: 0.5rem; 19 | } 20 | } 21 | @media screen and (max-width: 1024px) { 22 | grid-column: 2/ 10; 23 | .buttons { 24 | grid-column: 1/ 12; 25 | } 26 | } 27 | @media screen and (max-width: 720px) { 28 | grid-template-columns: repeat(6, 1fr); 29 | grid-column: 1/7; 30 | padding-inline: 1rem; 31 | .buttons { 32 | grid-column: span 6; 33 | } 34 | .socials { 35 | flex-wrap: wrap; 36 | } 37 | } 38 | `; 39 | 40 | export const ContactForm = styled.form` 41 | display: grid; 42 | grid-template-columns: 1fr 1fr; 43 | align-self: center; 44 | grid-column: 1/ 7; 45 | grid-gap: 1rem; 46 | grid-template-rows: min-content; 47 | height: min-content; 48 | input { 49 | grid-column: span 1; 50 | } 51 | textarea { 52 | grid-column: span 2; 53 | } 54 | @media screen and (max-width: 1024px) { 55 | grid-column: 1/ 12; 56 | } 57 | @media screen and (max-width: 720px) { 58 | grid-column: 1/ 7; 59 | input { 60 | grid-column: span 2; 61 | } 62 | } 63 | `; 64 | 65 | export const IconButton = styled(Button)` 66 | padding: 0; 67 | width: 60px; 68 | height: 60px; 69 | 70 | @media screen and (max-width: 720px) { 71 | width: 45px; 72 | height: 45px; 73 | } 74 | `; 75 | 76 | export const DownloadButton = styled(Button)` 77 | padding-block: 0; 78 | display: flex; 79 | gap: 0.5rem; 80 | height: 60px; 81 | 82 | @media screen and (max-width: 720px) { 83 | height: 45px; 84 | } 85 | `; 86 | -------------------------------------------------------------------------------- /src/components/ui/PageHeader.jsx: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { useEffect } from "react"; 3 | import { useLayoutEffect } from "react"; 4 | import { useState } from "react"; 5 | import { useRef } from "react"; 6 | import { useInView } from "react-intersection-observer"; 7 | import styled from "styled-components"; 8 | import { NavbarContext } from "../../context"; 9 | import { blue, typeScale } from "../../utils"; 10 | 11 | export const PageHeaderStyled = styled.h2` 12 | grid-column: 2 / 13; 13 | font-size: ${typeScale.headline}; 14 | font-weight: bold; 15 | color: ${blue["110"]}; 16 | padding-block: 1.25rem; 17 | background: white; 18 | background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, #ddd 100%); 19 | line-height: 1; 20 | -webkit-background-clip: text; 21 | -webkit-text-fill-color: transparent; 22 | width: fit-content; 23 | 24 | @media screen and (max-width: 720px) { 25 | grid-column: 1 / 7; 26 | padding-left: 1rem; 27 | } 28 | `; 29 | const ALPHABETS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); 30 | 31 | export const PageHeader = ({ children: text }) => { 32 | const { ref, inView } = useInView({ 33 | threshold: 1, 34 | }); 35 | const [header, setHeader] = useState(text); 36 | const setPage = useContext(NavbarContext); 37 | 38 | function animate() { 39 | let iteration = 0; 40 | let interval = setInterval(() => { 41 | setHeader(""); 42 | let newStr = ""; 43 | text.split("").forEach((element, index) => { 44 | let char = ALPHABETS[Math.round(Math.random() * 26)] ?? "M"; 45 | if (index < iteration) { 46 | char = text[index]; 47 | } 48 | newStr += char; 49 | }); 50 | setHeader(newStr); 51 | iteration += 1; 52 | if (iteration > text.length) { 53 | clearInterval(interval); 54 | } 55 | }, 60); 56 | } 57 | 58 | useEffect(() => { 59 | if (inView) { 60 | setPage(text.toLowerCase()); 61 | animate(); 62 | } 63 | }, [inView]); 64 | 65 | return ( 66 | 67 | {header} 68 | 69 | ); 70 | }; 71 | -------------------------------------------------------------------------------- /src/pages/Projects/carasoulButton.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | export const NextButton = ({ flip, onClick }) => { 4 | return ( 5 | 65 | ); 66 | }; 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # My Portfolio 2 | 3 | ## Description 4 | Welcome to my Software Engineering Portfolio! This project showcases my skills and projects in software engineering, built with ReactJS and ThreeJS. It's designed to provide an interactive and engaging user experience, highlighting my proficiency in modern web development technologies. 5 | 6 | ## Features 7 | - **Interactive 3D Elements**: Utilizing ThreeJS for dynamic and responsive 3D graphics. 8 | - **Responsive Design**: Crafted to provide a seamless experience on various devices and screen sizes. 9 | - **Project Showcase**: Detailed information about my software engineering projects, including descriptions, technologies used, and links to live demos or code repositories. 10 | 11 | ## Getting Started 12 | 13 | ### Prerequisites 14 | - Node.js and npm (Node Package Manager) installed on your system. You can download them from [Node.js official website](https://nodejs.org/). 15 | 16 | ### Installing 17 | To get a local copy up and running, follow these simple steps: 18 | 19 | ```bash 20 | # Clone the repository 21 | git clone https://github.com/teshank2137/portfolio.git 22 | 23 | # Navigate to the project directory 24 | cd portfolio 25 | 26 | # Install dependencies 27 | npm install 28 | 29 | # Run the application 30 | npm run dev 31 | ``` 32 | 33 | ## Usage 34 | After running the application, you can navigate through the portfolio to explore my software engineering projects. The interactive 3D elements powered by ThreeJS can be interacted with to gain a dynamic view of my skills and experiences. 35 | 36 | ## Credit/Attribution 37 | If you are using this code or any part of it in your projects, I kindly request that you give proper credit by linking back to my portfolio or GitHub repository. Please include the following line in your project's documentation or credits section: 38 | 39 | "Portions of this code were developed by Teshank Raut. You can find the original project at https://teshank.dev or https://github.com/teshank2137/portfolio." 40 | 41 | ## License 42 | This project is licensed under the Apache License 2.0 - see the LICENSE file for details. 43 | 44 | 45 | For more information about the Apache License 2.0, please visit [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). 46 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | Teshank Raut 38 | 39 | 40 | 44 | 53 | 54 | 55 |
56 | 57 |
58 | 59 | 60 | -------------------------------------------------------------------------------- /src/data/projects.js: -------------------------------------------------------------------------------- 1 | import stonks from "../assets/images/stonks.png"; 2 | import sendfrom from "../assets/images/sendform.jpg"; 3 | import semicolon from "../assets/images/semicolon.png"; 4 | import scroll from "../assets/images/scroll.jpg"; 5 | import getv from "../assets/images/get-v.jpg"; 6 | 7 | export const projects = [ 8 | { 9 | title: "Get Vulnerable", 10 | image: getv, 11 | link: "https://get-vulnerable.teshank.dev", 12 | description: 13 | "Game which encourages the players to open up by asking questions", 14 | }, 15 | { 16 | title: "Semicolon", 17 | image: semicolon, 18 | link: "https://github.com/teshank2137/semicolon.md", 19 | description: 20 | "Mental health support by predicting and offering activities for mood upliftment.", 21 | }, 22 | { 23 | title: "Send form to me", 24 | image: sendfrom, 25 | link: "https://sendformto.me", 26 | description: 27 | "Backend-as-a-service for creating forms with unique URLs and email notifications.", 28 | }, 29 | { 30 | title: "Fan Merch", 31 | image: 32 | "https://raw.githubusercontent.com/teshank2137/portfolio/v1/src/assets/images/fanmerch.png", 33 | github: "https://github.com/teshank2137/fanMerch", 34 | link: "https://fan-merch.vercel.app/", 35 | description: 36 | "A conceptual website for social media influence's to sell their merch.", 37 | }, 38 | { 39 | title: "Find Techie", 40 | description: 41 | "A Twitter bot that scans Twitter for job/intern posting and retweets top tweets daily.", 42 | image: 43 | "https://raw.githubusercontent.com/teshank2137/portfolio/v1/src/assets/images/Techie.png", 44 | link: "https://twitter.com/FindTechie", 45 | }, 46 | { 47 | title: "React Infinite scroll", 48 | description: "Infinite scrolling using custom hook and ObservableAPI", 49 | image: scroll, 50 | link: "https://react-infinite-scroll-nu.vercel.app/", 51 | github: "https://github.com/teshank2137/react-infinite-scroll", 52 | }, 53 | { 54 | title: "Smart Attendance App", 55 | description: 56 | "A mobile app in which the user can track and mark attendance using face verification.", 57 | image: 58 | "https://raw.githubusercontent.com/teshank2137/portfolio/v1/src/assets/images/smartattendance.png", 59 | github: "https://github.com/teshank2137/smartAtendence", 60 | }, 61 | { 62 | title: "Stock Market Prediction API", 63 | description: 64 | "An API Which predicts the next day's closing price of a stock.", 65 | image: stonks, 66 | github: "https://github.com/teshank2137/stockprediction", 67 | }, 68 | { 69 | title: "Algorithm Visualizer", 70 | description: "Web App to visualize the searching and sorting algorithms", 71 | image: 72 | "https://raw.githubusercontent.com/teshank2137/portfolio/v1/src/assets/images/sort.JPG", 73 | link: "https://teshank2137.github.io/#/", 74 | }, 75 | { 76 | title: "Portfolio v1", 77 | description: "Built using ReactJS, ThreeJS, CSS3 and lots of ❤️ love.", 78 | image: 79 | "https://raw.githubusercontent.com/teshank2137/portfolio/v1/src/assets/images/port.JPG", 80 | link: "https://www.v1.teshank.dev/", 81 | }, 82 | ]; 83 | -------------------------------------------------------------------------------- /src/pages/About/About.jsx: -------------------------------------------------------------------------------- 1 | import { Canvas } from "@react-three/fiber"; 2 | import gsap from "gsap"; 3 | import Flip from "gsap/Flip"; 4 | import React, { useEffect } from "react"; 5 | import { Page } from "../../components/Page"; 6 | import { blue, green, yellow } from "../../utils"; 7 | import { Educations, Paragraph, SkillsWrapper, Text } from "./About.styled"; 8 | import { AboutItem } from "./AboutItem"; 9 | import Skills from "./SkillBall"; 10 | import dyp from "../../assets/images/dyp.png"; 11 | import highschool from "../../assets/images/highschool.jpeg"; 12 | import sos from "../../assets/images/sos.png"; 13 | import { useInView } from "react-intersection-observer"; 14 | import { useState } from "react"; 15 | 16 | export const About = () => { 17 | const { ref, inView } = useInView({}); 18 | const [show, setShow] = useState(inView); 19 | useEffect(() => { 20 | setShow(inView); 21 | }, [inView]); 22 | 23 | useEffect(() => { 24 | gsap.registerPlugin(Flip); 25 | let cards = document.querySelectorAll(".about-item"); 26 | cards.forEach((card, i) => { 27 | if (i === 0) { 28 | card.classList.add("active"); 29 | } 30 | card.addEventListener("mouseenter", (e) => { 31 | if (card.classList.contains("active")) { 32 | return; 33 | } 34 | const state = Flip.getState(cards); 35 | cards.forEach((c) => { 36 | c.classList.remove("active"); 37 | }); 38 | card.classList.add("active"); 39 | Flip.from(state, { 40 | duration: 0.5, 41 | ease: "elastic.out(1,0.9)", 42 | absolute: true, 43 | }); 44 | }); 45 | }); 46 | }, []); 47 | return ( 48 |
49 | 50 | 51 | 52 | I'm a passionate programmer, who is always looking for new 53 | challenges to improve myself, also a team player, who is always 54 | ready to learn new things and help others. 55 |
I was born and raised in Nagpur, India. I love to play guitar 56 | and ukulele and in my free time I like to read books, watch movies 57 | and play video games. 58 |
59 | 60 | 69 | 77 | 85 | 86 |
87 | 88 | {show ? ( 89 | 90 | 91 | 92 | ) : ( 93 | `${inView}` 94 | )} 95 | 96 |
97 |
98 | ); 99 | }; 100 | -------------------------------------------------------------------------------- /src/pages/Contact/Contact.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { 3 | AiFillGithub, 4 | AiFillLinkedin, 5 | AiOutlineDownload, 6 | AiOutlineInstagram, 7 | AiOutlineMail, 8 | } from "react-icons/ai"; 9 | import { Button, Input, Textarea } from "../../components/form"; 10 | import { Page } from "../../components/Page"; 11 | import { blue, green, pink, red, yellow } from "../../utils"; 12 | import { 13 | ContactForm, 14 | ContactWrapper, 15 | DownloadButton, 16 | IconButton, 17 | } from "./Contact.styled"; 18 | 19 | export const Contact = () => { 20 | const [form, setFormState] = useState({ name: "", email: "", message: "" }); 21 | return ( 22 | 23 | 24 | 30 | { 35 | setFormState((prev) => ({ ...prev, name: e.target.value })); 36 | }} 37 | value={form.name} 38 | /> 39 | { 44 | setFormState((prev) => ({ ...prev, email: e.target.value })); 45 | }} 46 | value={form.email} 47 | /> 48 |