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*
|
||||
yarn-debug.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/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"motion": "^12.34.3",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-scripts": "5.0.1",
|
||||
"three": "^0.183.2",
|
||||
"typescript": "^4.9.5",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
@@ -8699,6 +8701,33 @@
|
||||
"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": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
@@ -11800,6 +11829,47 @@
|
||||
"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": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
@@ -16242,6 +16312,12 @@
|
||||
"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": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz",
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
"@types/node": "^16.18.126",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"motion": "^12.34.3",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-scripts": "5.0.1",
|
||||
"three": "^0.183.2",
|
||||
"typescript": "^4.9.5",
|
||||
"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 {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
@@ -11,3 +14,10 @@ code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
|
||||
button {
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,15 +1,18 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import {Canvas} from "./index/Canvas";
|
||||
import {Nav} from "./nav/Nav";
|
||||
|
||||
const root = ReactDOM.createRoot(
|
||||
document.getElementById('root') as HTMLElement
|
||||
);
|
||||
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
<Nav/>
|
||||
<Canvas/>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
import {motion} from "framer-motion";
|
||||
import "./canvas.scss";
|
||||
|
||||
export function Canvas() {
|
||||
return (
|
||||
<>
|
||||
<main className="main">
|
||||
<h1>Welcome to my blog</h1>
|
||||
</main>
|
||||
</>
|
||||
<main>
|
||||
<motion.h1 className="welcome" animate={{ rotate: 360 }}>
|
||||
Welcome to my blog
|
||||
</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