Compare commits

...

4 Commits

Author SHA1 Message Date
46ed382d56 links styling fix (no underline) 2026-03-04 20:29:53 -06:00
fd13b72380 wave canvas styling fix + links righthand bar 2026-03-04 20:29:38 -06:00
6d5e6b5202 canvas camera moving 2026-03-04 18:45:42 -06:00
0b66096fc2 canvas space theme 2026-03-04 17:32:19 -06:00
11 changed files with 142 additions and 122 deletions

51
package-lock.json generated
View File

@@ -81,7 +81,6 @@
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
"integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.29.0",
"@babel/generator": "^7.29.0",
@@ -731,7 +730,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.28.6.tgz",
"integrity": "sha512-D+OrJumc9McXNEBI/JmFnc/0uCM2/Y3PEBG3gfV3QIYkKv5pvnpzFrl1kYCrcHJP8nOeFB/SHi1IHz29pNGuew==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.28.6"
},
@@ -1615,7 +1613,6 @@
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.28.6.tgz",
"integrity": "sha512-61bxqhiRfAACulXSLd/GxqmAedUSrRZIu/cbaT18T1CetkTmtDN15it7i80ru4DVqRK1WMxQhXs+Lf9kajm5Ow==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.27.3",
"@babel/helper-module-imports": "^7.28.6",
@@ -2497,7 +2494,6 @@
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-7.2.0.tgz",
"integrity": "sha512-6639htZMjEkwskf3J+e6/iar+4cTNM9qhoWuRfj9F3eJD6r7iCzV1SWnQr2Mdv0QT0suuqU8BoJCZUyCtP9R4Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"@fortawesome/fontawesome-common-types": "7.2.0"
},
@@ -3039,7 +3035,6 @@
"version": "2.5.6",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz",
"integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"optional": true,
@@ -3079,7 +3074,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3100,7 +3094,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3121,7 +3114,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3142,7 +3134,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3163,7 +3154,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3184,7 +3174,6 @@
"cpu": [
"arm"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3205,7 +3194,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3226,7 +3214,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3247,7 +3234,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3268,7 +3254,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3289,7 +3274,6 @@
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3310,7 +3294,6 @@
"cpu": [
"ia32"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3331,7 +3314,6 @@
"cpu": [
"x64"
],
"dev": true,
"license": "MIT",
"optional": true,
"os": [
@@ -3349,7 +3331,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true,
"license": "MIT",
"optional": true,
"engines": {
@@ -3808,7 +3789,6 @@
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
"integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
@@ -4204,7 +4184,6 @@
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
"license": "MIT",
"peer": true,
"dependencies": {
"csstype": "^3.2.2"
}
@@ -4214,7 +4193,6 @@
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"license": "MIT",
"peer": true,
"peerDependencies": {
"@types/react": "^19.2.0"
}
@@ -4367,7 +4345,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
"integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/regexpp": "^4.4.0",
"@typescript-eslint/scope-manager": "5.62.0",
@@ -4421,7 +4398,6 @@
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
"integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
"license": "BSD-2-Clause",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "5.62.0",
"@typescript-eslint/types": "5.62.0",
@@ -4798,7 +4774,6 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
"integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -4897,7 +4872,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz",
"integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==",
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -5830,7 +5804,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.9.0",
"caniuse-lite": "^1.0.30001759",
@@ -7109,7 +7082,6 @@
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
"integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
"dev": true,
"license": "Apache-2.0",
"optional": true,
"engines": {
@@ -7705,7 +7677,6 @@
"integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==",
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
@@ -9732,7 +9703,6 @@
"resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
"integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
"license": "MIT",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/immer"
@@ -10523,7 +10493,6 @@
"resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
"integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@jest/core": "^27.5.1",
"import-local": "^3.0.2",
@@ -11421,7 +11390,6 @@
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
"integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
"license": "MIT",
"peer": true,
"bin": {
"jiti": "bin/jiti.js"
}
@@ -12190,7 +12158,6 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
"dev": true,
"license": "MIT",
"optional": true
},
@@ -12842,7 +12809,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -13977,7 +13943,6 @@
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
"license": "MIT",
"peer": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -14337,7 +14302,6 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
"integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -14469,7 +14433,6 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
"integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.27.0"
},
@@ -14494,7 +14457,6 @@
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz",
"integrity": "sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -14956,7 +14918,6 @@
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.80.0.tgz",
"integrity": "sha512-cIFJOD1DESzpjOBl763Kp1AH7UE/0fcdHe6rZXUdQ9c50uvgigvW97u3IcSeBwOkgqL/PXPBktBCh0KEu5L8XQ==",
"license": "MIT",
"peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
@@ -15119,7 +15080,6 @@
"integrity": "sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==",
"devOptional": true,
"license": "MIT",
"peer": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
@@ -15251,7 +15211,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
@@ -16580,8 +16539,7 @@
"version": "0.183.2",
"resolved": "https://registry.npmjs.org/three/-/three-0.183.2.tgz",
"integrity": "sha512-di3BsL2FEQ1PA7Hcvn4fyJOlxRRgFYBpMTcyOgkwJIaDOdJMebEFPA+t98EvjuljDx4hNulAGwF6KIjtwI5jgQ==",
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/throat": {
"version": "6.0.2",
@@ -16633,7 +16591,6 @@
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12"
},
@@ -16802,7 +16759,6 @@
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
"integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
"license": "(MIT OR CC0-1.0)",
"peer": true,
"engines": {
"node": ">=10"
},
@@ -16911,7 +16867,6 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -17084,7 +17039,6 @@
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
"license": "MIT",
"peer": true,
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
@@ -17236,7 +17190,6 @@
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.3.tgz",
"integrity": "sha512-LLBBA4oLmT7sZdHiYE/PeVuifOxYyE2uL/V+9VQP7YSYdJU7bSf7H8bZRRxW8kEPMkmVjnrXmoR3oejIdX0xbg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.8",
@@ -17308,7 +17261,6 @@
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz",
"integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==",
"license": "MIT",
"peer": true,
"dependencies": {
"@types/bonjour": "^3.5.9",
"@types/connect-history-api-fallback": "^1.3.5",
@@ -17722,7 +17674,6 @@
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz",
"integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==",
"license": "MIT",
"peer": true,
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",

View File

@@ -1,46 +1,42 @@
import {motion} from "framer-motion";
import "./canvas.scss";
import {Canvas as ThreeCanvas, useFrame} from "@react-three/fiber";
import {useRef} from "react";
import {Mesh} from "three";
import React, {useMemo, useRef, useState} from "react";
import {Mesh, Vector3} from "three";
import {Moon} from "./Moon";
import {Stars} from "./Stars";
export default function Canvas() {
return (
<main>
<ThreeCanvas>
<ThreeCanvas gl={{antialias: true, alpha: true}} >
<Sphere/>
<mesh position={[1,2,-10]}>
<sphereGeometry args={[0.1,0.1,0.1]}/>
<meshBasicMaterial />
</mesh>
<mesh position={[1,-2,-10]}>
<sphereGeometry args={[0.1,0.1,0.1]} />
<meshBasicMaterial />
</mesh>
<directionalLight color="red" position={[5, 5, 5]} />
<directionalLight color="blue" position={[5, 0, 5]} />
<directionalLight color="yellow" position={[-5, 0, 5]} />
<Moon radius={8} color="pink" step={0.01}/>
<Moon radius={6} color="grey" step={0.02}/>
<Moon radius={4} color="green" step={0.03}/>
<Stars/>
<directionalLight color="#E3A857" args={[1,10]} position={[100,10,100]} />
</ThreeCanvas>
<motion.h1 className="welcome" animate={{ rotate: 360 }}>
<motion.h2 className="welcome" animate={{ rotate: 360 }}>
Welcome to my blog
</motion.h1>
</motion.h2>
</main>
)
}
function Sphere() {
const meshRef = useRef<Mesh>(null);
useFrame(state => {
const { x, y } = state.pointer
// Smoothly interpolate the camera position
// We multiply by a factor (e.g., 5) to increase the range of movement
state.camera.position.lerp(new Vector3(x * 10, y * 10, 5), 0.1)
// Always keep the camera looking at the center
state.camera.lookAt(0, 0, 0)
})
useFrame(() => {
if(meshRef.current) {
meshRef.current.rotation.y += 0.01
}
});
return (
<mesh ref={meshRef} position={[0,0,0]}>
<sphereGeometry args={[1, 1, 1]} />
<meshStandardMaterial />
</mesh>
)
return <mesh position={[0,0,0]}>
<sphereGeometry />
<meshPhysicalMaterial color="blue" iridescence={.5} />
</mesh>
}

28
src/index/Moon.tsx Normal file
View File

@@ -0,0 +1,28 @@
import {useMemo, useRef, useState} from "react";
import {Mesh} from "three";
import {useFrame} from "@react-three/fiber";
export function Moon(props: {radius: number, color: string, step: number}) {
const {radius, color, step} = props;
const moonRef = useRef<Mesh>(null);
const [theta, setTheta] = useState(0);
useFrame(() => {
if(!moonRef.current) return;
moonRef.current.position.set(
radius * Math.sin(theta),
0,
radius * Math.cos(theta),
)
setTheta(theta + step);
})
return (
<mesh ref={moonRef} position={[0,0,0]}>
<sphereGeometry args={[.5]} />
<meshPhysicalMaterial color={color} iridescence={0.2} />
</mesh>
)
}

33
src/index/Stars.tsx Normal file
View File

@@ -0,0 +1,33 @@
import {useMemo} from "react";
const RADIUS = 20;
const COUNT = 100;
type Coordinate = [number, number, number];
export function Stars() {
const positions = useMemo(() => {
const positions: Coordinate[] = [];
for(let i = 0; i < COUNT; i++) {
const u = Math.random();
const v = Math.random();
const theta = 2 * Math.PI * u;
const phi = Math.acos(2 * v - 1);
// x = r*sin(theta)*cos(phi)
// x = r*sin(theta)*sin(phi)
// z = r*cos(phi)
positions.push([
RADIUS * Math.sin(phi) * Math.cos(theta),
RADIUS * Math.sin(phi) * Math.sin(theta),
RADIUS * Math.cos(phi),
])
}
return positions;
}, []);
return positions.map(coord => <mesh position={coord}>
<sphereGeometry args={[.1]} />
<meshBasicMaterial />
</mesh>
)
}

View File

@@ -6,17 +6,11 @@ main {
align-items: center;
background: black;
color: white;
position: absolute;
top: 0;
z-index: -999;
}
.welcome {
text-align: center;
z-index: 99;
position: absolute;
top: 50%;
}
.canvas {
top: calc(50% + 50px);
}

21
src/nav/Links.tsx Normal file
View File

@@ -0,0 +1,21 @@
import React, {useState} from "react";
import {Link} from "../router/Link";
import {motion} from "framer-motion";
export function Links() {
const [links, setLinks] = useState(["About", "Articles"]);
return <div className="links">
{ links.map(() => /* add spacers for flexbox */ <div/> )}
<Title/>
{ links.map(link => <Link href={`/${link}`}><h3>{link}</h3></Link>) }
</div>
}
function Title() {
return (
<Link href="/" className="name">
<motion.h1 className="name">Tymur Arsentiev</motion.h1>
</Link>
);
}

View File

@@ -6,15 +6,16 @@ import wave from "../img/menu-wave.svg";
import "./nav.scss";
import {motion} from "framer-motion";
import {Link} from "../router/Link";
import {Path} from "../router/router";
import {Links} from "./Links";
export default function Nav() {
const [active, setActive] = useState(false);
return <>
<nav className="header">
<nav>
<MenuButton active={active} setActive={setActive}/>
<Title/>
<Link href="/about" className="nav-item">About</Link>
<Links/>
</nav>
<Menu active={active}/>
<img className="wave" alt="wave" src={wave}/>
@@ -34,11 +35,3 @@ function MenuButton(props : { active: boolean, setActive: (_:boolean) => void })
</div>
);
}
function Title() {
return (
<Link href="/" className="name">
<motion.h1>Tymur Arsentiev</motion.h1>
</Link>
);
}

View File

@@ -1,16 +1,16 @@
$padding: 15px;
$menu: #282c34;
.menu-btn:hover {
.menu-btn>button:hover {
opacity: 90%;
}
.menu-btn:active {
.menu-btn>button:active {
opacity: 80%;
}
.menu-btn {
justify-self: center;
align-self: center;
display: flex;
flex-direction: column;
align-items: center;
@@ -19,32 +19,35 @@ $menu: #282c34;
}
}
.name {
position: absolute;
font-weight: bold;
left: 50%;
transform: translateX(-50%);
}
.header {
nav {
background-color: $menu;
padding: $padding;
display: flex;
font-size: calc(10px + 2vmin);
color: white;
min-height: 3 * $padding;
justify-content: center;
}
nav>a{
text-align: center;
}
.name>h1 {
margin: 0;
font-size: 40px;
}
.name {
align-self: center;
flex-grow: 1;
margin: auto;
position: relative;
}
.wave {
position: absolute;
z-index: 999;
user-select: none;
pointer-events: none;
left: -10%;
width: 110%;
position: absolute;
}
.links {
display: flex;
flex-grow: 1;
gap: 15px;
}

View File

@@ -4,7 +4,7 @@ import React, {PropsWithChildren} from "react";
import {useRouter} from "./RouterContext";
import {Path} from "./router";
export function Link(props: {className: string, href: Path, replace?: boolean } & PropsWithChildren) {
export function Link(props: {className?: string, href: Path, replace?: boolean } & PropsWithChildren) {
const {children, className, href, replace} = props;
const router = useRouter();
@@ -17,5 +17,5 @@ export function Link(props: {className: string, href: Path, replace?: boolean }
}
}
return <a onClick={onClick} href={href} className={`${className} link click`}>{children}</a>
return <a onClick={onClick} href={href} className={`${className} link`}>{children}</a>
}

View File

@@ -6,5 +6,5 @@ export function Route(props: PropsWithChildren & {path: Path}) {
const {path, children} = props;
const router = useRouter();
return router.current === path ? <>{children}</> : <></>
return router.current.toLowerCase() === path ? <>{children}</> : <></>
}

View File

@@ -1,6 +1,7 @@
.link {
color: white;
text-decoration: underline;
text-decoration: none;
text-align: center;
}
.link:hover {