nav menu wave

This commit is contained in:
2026-03-01 22:06:17 -06:00
parent 375b7d7b47
commit 62346321d7
6 changed files with 155 additions and 0 deletions

1
src/img/menu-wave.svg Normal file
View 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

30
src/nav/Menu.tsx Normal file
View 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
View 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
View 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
View 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%;
}

View 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>
}