Compare commits
3 Commits
1f1bf2540d
...
0713ad7521
| Author | SHA1 | Date | |
|---|---|---|---|
| 0713ad7521 | |||
| 62346321d7 | |||
| 375b7d7b47 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -21,4 +21,4 @@
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
.tar
|
*.tar
|
||||||
|
|||||||
7
.idea/compiler.xml
generated
Normal file
7
.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="TypeScriptCompiler">
|
||||||
|
<option name="memoryAutoIncrease" value="true" />
|
||||||
|
<option name="useServicePoweredTypesEnabledManually" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
76
package-lock.json
generated
76
package-lock.json
generated
@@ -21,9 +21,11 @@
|
|||||||
"@types/node": "^16.18.126",
|
"@types/node": "^16.18.126",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
|
"motion": "^12.34.3",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
"three": "^0.183.2",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
@@ -8699,6 +8701,33 @@
|
|||||||
"url": "https://github.com/sponsors/rawify"
|
"url": "https://github.com/sponsors/rawify"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/framer-motion": {
|
||||||
|
"version": "12.34.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.34.3.tgz",
|
||||||
|
"integrity": "sha512-v81ecyZKYO/DfpTwHivqkxSUBzvceOpoI+wLfgCgoUIKxlFKEXdg0oR9imxwXumT4SFy8vRk9xzJ5l3/Du/55Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-dom": "^12.34.3",
|
||||||
|
"motion-utils": "^12.29.2",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/fresh": {
|
"node_modules/fresh": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||||
@@ -11800,6 +11829,47 @@
|
|||||||
"mkdirp": "bin/cmd.js"
|
"mkdirp": "bin/cmd.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/motion": {
|
||||||
|
"version": "12.34.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion/-/motion-12.34.3.tgz",
|
||||||
|
"integrity": "sha512-xZIkBGO7v/Uvm+EyaqYd+9IpXu0sZqLywVlGdCFrrMiaO9JI4Kx51mO9KlHSWwll+gZUVY5OJsWgYI5FywJ/tw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^12.34.3",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/is-prop-valid": "*",
|
||||||
|
"react": "^18.0.0 || ^19.0.0",
|
||||||
|
"react-dom": "^18.0.0 || ^19.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@emotion/is-prop-valid": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-dom": {
|
||||||
|
"version": "12.34.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.34.3.tgz",
|
||||||
|
"integrity": "sha512-sYgFe+pR9aIM7o4fhs2aXtOI+oqlUd33N9Yoxcgo1Fv7M20sRkHtCmzE/VRNIcq7uNJ+qio+Xubt1FXH3pQ+eQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"motion-utils": "^12.29.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/motion-utils": {
|
||||||
|
"version": "12.29.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.29.2.tgz",
|
||||||
|
"integrity": "sha512-G3kc34H2cX2gI63RqU+cZq+zWRRPSsNIOjpdl9TN4AQwC4sgwYPl/Q/Obf/d53nOm569T0fYK+tcoSV50BWx8A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
@@ -16242,6 +16312,12 @@
|
|||||||
"node": ">=0.8"
|
"node": ">=0.8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/three": {
|
||||||
|
"version": "0.183.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/three/-/three-0.183.2.tgz",
|
||||||
|
"integrity": "sha512-di3BsL2FEQ1PA7Hcvn4fyJOlxRRgFYBpMTcyOgkwJIaDOdJMebEFPA+t98EvjuljDx4hNulAGwF6KIjtwI5jgQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/throat": {
|
"node_modules/throat": {
|
||||||
"version": "6.0.2",
|
"version": "6.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz",
|
||||||
|
|||||||
@@ -16,9 +16,11 @@
|
|||||||
"@types/node": "^16.18.126",
|
"@types/node": "^16.18.126",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
|
"motion": "^12.34.3",
|
||||||
"react": "^19.2.4",
|
"react": "^19.2.4",
|
||||||
"react-dom": "^19.2.4",
|
"react-dom": "^19.2.4",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
"three": "^0.183.2",
|
||||||
"typescript": "^4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
|
|||||||
34
src/App.scss
34
src/App.scss
@@ -1,34 +0,0 @@
|
|||||||
$padding: 15px;
|
|
||||||
|
|
||||||
.header {
|
|
||||||
background-color: #282c34;
|
|
||||||
padding: $padding;
|
|
||||||
display: flex;
|
|
||||||
justify-items: center;
|
|
||||||
font-size: calc(10px + 2vmin);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu {
|
|
||||||
position: absolute;
|
|
||||||
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
color: white;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.main {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
15
src/App.tsx
15
src/App.tsx
@@ -1,15 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import './App.scss';
|
|
||||||
import {Canvas} from "./index/Canvas";
|
|
||||||
import {Nav} from "./Nav";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div className="App">
|
|
||||||
<Nav/>
|
|
||||||
<Canvas/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
13
src/Nav.tsx
13
src/Nav.tsx
@@ -1,13 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
|
||||||
import {faBars} from "@fortawesome/free-solid-svg-icons/faBars";
|
|
||||||
|
|
||||||
export function Nav() {
|
|
||||||
return <nav className="header">
|
|
||||||
|
|
||||||
<button className="menu">
|
|
||||||
<FontAwesomeIcon icon={faBars}/>
|
|
||||||
</button>
|
|
||||||
<div className="name">Tymur Arsentiev</div>
|
|
||||||
</nav>;
|
|
||||||
}
|
|
||||||
1
src/img/menu-wave.svg
Normal file
1
src/img/menu-wave.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320"><path fill="#282c34" fill-opacity="1" d="M0,32L60,37.3C120,43,240,53,360,64C480,75,600,85,720,106.7C840,128,960,160,1080,160C1200,160,1320,128,1380,112L1440,96L1440,0L1380,0C1320,0,1200,0,1080,0C960,0,840,0,720,0C600,0,480,0,360,0C240,0,120,0,60,0L0,0Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 330 B |
@@ -1,5 +1,8 @@
|
|||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
sans-serif;
|
sans-serif;
|
||||||
@@ -11,3 +14,10 @@ code {
|
|||||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
monospace;
|
monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
@@ -1,15 +1,18 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.css';
|
import './index.css';
|
||||||
import App from './App';
|
|
||||||
import reportWebVitals from './reportWebVitals';
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
import {Canvas} from "./index/Canvas";
|
||||||
|
import {Nav} from "./nav/Nav";
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(
|
||||||
document.getElementById('root') as HTMLElement
|
document.getElementById('root') as HTMLElement
|
||||||
);
|
);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<App />
|
<Nav/>
|
||||||
|
<Canvas/>
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
|
import {motion} from "framer-motion";
|
||||||
|
import "./canvas.scss";
|
||||||
|
|
||||||
export function Canvas() {
|
export function Canvas() {
|
||||||
return (
|
return (
|
||||||
<>
|
<main>
|
||||||
<main className="main">
|
<motion.h1 className="welcome" animate={{ rotate: 360 }}>
|
||||||
<h1>Welcome to my blog</h1>
|
Welcome to my blog
|
||||||
</main>
|
</motion.h1>
|
||||||
</>
|
<canvas>
|
||||||
|
|
||||||
|
</canvas>
|
||||||
|
</main>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
16
src/index/canvas.scss
Normal file
16
src/index/canvas.scss
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
main {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 10%;
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welcome {
|
||||||
|
text-align: center;
|
||||||
|
top: 25%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
30
src/nav/Menu.tsx
Normal file
30
src/nav/Menu.tsx
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import "./menu.scss";
|
||||||
|
import {motion, animate} from "framer-motion";
|
||||||
|
import {useEffect} from "react";
|
||||||
|
|
||||||
|
const articles = [
|
||||||
|
"Test 123",
|
||||||
|
"Hello",
|
||||||
|
"Title of Album"
|
||||||
|
];
|
||||||
|
const hidden = -999;
|
||||||
|
|
||||||
|
export function Menu({active} : {active: boolean}) {
|
||||||
|
useEffect(() => {
|
||||||
|
if(active) {
|
||||||
|
animate(".menu", {left : 0})
|
||||||
|
} else {
|
||||||
|
animate(".menu", {left : hidden})
|
||||||
|
}
|
||||||
|
}, [active]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.section className="menu">
|
||||||
|
{
|
||||||
|
articles.map(title => <div>
|
||||||
|
{title}
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
</motion.section>
|
||||||
|
)
|
||||||
|
}
|
||||||
42
src/nav/Nav.tsx
Normal file
42
src/nav/Nav.tsx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import React, {useState} from "react";
|
||||||
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
|
||||||
|
import {faBars} from "@fortawesome/free-solid-svg-icons/faBars";
|
||||||
|
import {Menu} from "./Menu";
|
||||||
|
import wave from "../img/menu-wave.svg";
|
||||||
|
import "./nav.scss";
|
||||||
|
import {motion} from "framer-motion";
|
||||||
|
|
||||||
|
export function Nav() {
|
||||||
|
const [active, setActive] = useState(false);
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<nav className="header">
|
||||||
|
<MenuButton active={active} setActive={setActive}/>
|
||||||
|
<Title/>
|
||||||
|
</nav>
|
||||||
|
<Menu active={active}/>
|
||||||
|
<img className="wave" alt="wave" src={wave}/>
|
||||||
|
</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function MenuButton(props : { active: boolean, setActive: (_:boolean) => void }) {
|
||||||
|
const {active, setActive} = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="menu-btn click">
|
||||||
|
<button>
|
||||||
|
<FontAwesomeIcon icon={faBars} onClick={function() {
|
||||||
|
setActive(!active);
|
||||||
|
}} />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Title() {
|
||||||
|
return (
|
||||||
|
<a href="/" className="name click">
|
||||||
|
<motion.h1>Tymur Arsentiev</motion.h1>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
16
src/nav/menu.scss
Normal file
16
src/nav/menu.scss
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
@import "./nav";
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
background: $menu;
|
||||||
|
z-index: 10;
|
||||||
|
color: white;
|
||||||
|
width: 25%;
|
||||||
|
height: 100vh;
|
||||||
|
|
||||||
|
div {
|
||||||
|
padding: $padding;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/nav/nav.scss
Normal file
52
src/nav/nav.scss
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
$padding: 15px;
|
||||||
|
$menu: #282c34;
|
||||||
|
|
||||||
|
.click:hover {
|
||||||
|
opacity: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.click:active {
|
||||||
|
opacity: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu-btn {
|
||||||
|
justify-self: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
button {
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
position: absolute;
|
||||||
|
font-weight: bold;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background-color: $menu;
|
||||||
|
padding: $padding;
|
||||||
|
display: flex;
|
||||||
|
font-size: calc(10px + 2vmin);
|
||||||
|
color: white;
|
||||||
|
min-height: 3 * $padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
align-self: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.wave {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
left: -10%;
|
||||||
|
width: 110%;
|
||||||
|
}
|
||||||
14
src/router/RouterContext.tsx
Normal file
14
src/router/RouterContext.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import {createContext, PropsWithChildren, useContext, useSyncExternalStore} from "react";
|
||||||
|
|
||||||
|
const RouterContext = createContext<{}>({});
|
||||||
|
|
||||||
|
export function useRouter() {
|
||||||
|
return useContext(RouterContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RouterProvider(props : PropsWithChildren) {
|
||||||
|
|
||||||
|
return <RouterContext.Provider value={{}}>
|
||||||
|
{props.children}
|
||||||
|
</RouterContext.Provider>
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user