Skip to content

Commit

Permalink
✨ navbar design upgraded
Browse files Browse the repository at this point in the history
  • Loading branch information
yuancong-liu committed Apr 25, 2024
1 parent 06a636c commit 1e65aa5
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 78 deletions.
4 changes: 2 additions & 2 deletions src/app/about-me/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReactNode } from 'react';

import { NavBarCommon } from '~/components/common/navBarCommon';
import { NavBar } from '~/components/common/navBar';

import styles from './layout.module.scss';

Expand All @@ -10,7 +10,7 @@ type Props = {

const AboutMeLayout = ({ children }: Props) => (
<div className={styles['page-wrapper']}>
<NavBarCommon />
<NavBar />
{children}
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions src/app/and/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ReactNode } from 'react';

import { NavBarCommon } from '~/components/common/navBarCommon';
import { NavBar } from '~/components/common/navBar';

import styles from './layout.module.scss';

Expand All @@ -10,7 +10,7 @@ type Props = {

const AboutMeLayout = ({ children }: Props) => (
<div className={styles['page-wrapper']}>
<NavBarCommon />
<NavBar />
{children}
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions src/app/blog/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ReactNode } from 'react';

import { Footer } from '~/components/common/footer';
import { NavBarCommon } from '~/components/common/navBarCommon';
import { NavBar } from '~/components/common/navBar';

import styles from './layout.module.scss';

Expand All @@ -11,7 +11,7 @@ type Props = {

const BlogLayout = ({ children }: Props) => (
<div className={styles['page-wrapper']}>
<NavBarCommon />
<NavBar />
{children}
<Footer />
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/app/portfolio/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { ReactNode } from 'react';

import { NavBarCommon } from '~/components/common/navBarCommon';
import { NavBar } from '~/components/common/navBar';

type Props = {
children: ReactNode;
};

const AboutMeLayout = ({ children }: Props) => (
<div>
<NavBarCommon />
<NavBar />
{children}
</div>
);
Expand Down
131 changes: 131 additions & 0 deletions src/components/common/navBar/index.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
@use 'sass:color';

.nav-bar {
position: fixed;
top: 0;
right: 0;
left: 0;
z-index: 1000;
width: min(100%, 700px);
padding: 8px;
margin: 10px auto;
overflow: hidden;
font-family: utils.$font-serif;
font-size: 16px;
font-weight: 600;
color: #fff;
background: utils.$color-pink-bd;
backdrop-filter: blur(10px);
border: 1px solid #fff2;
border-radius: 100px;
box-shadow: 0 0 20px 0 utils.$color-pink-bd;
transition: box-shadow 0.3s ease-in-out;

@include sp {
top: unset;
bottom: 0;
width: fit-content;
padding: 8px;
font-size: 12px;
}

&::after {
position: absolute;
top: var(--y, 0);
left: var(--x, 0);
z-index: -1;
width: 40px;
height: 40px;
content: '';
background: color.adjust(utils.$color-pink, $alpha: 0.5);
filter: blur(16px);
opacity: 0;
transition: opacity 0.3s ease-in-out;
}

@include hover {
box-shadow: 0 0 30px 0 color.adjust(utils.$color-pink-bd, $alpha: 0.05);

&::after {
opacity: 0.8;
animation: hover-glow 2s infinite;
}
}
}

@keyframes hover-glow {
0% {
scale: 1;
}

50% {
scale: 1.1;
}

100% {
scale: 1;
}
}

.nav-items {
@extend %center-items-grid;

z-index: 100;
grid-template-columns: 1fr 1fr 40px 1fr 1fr;
gap: 8px;
padding: 0;
margin: 0 auto;
list-style: none;
}

.nav-item {
@extend %center-items-grid;

position: relative;
width: 100%;
height: 100%;
border-radius: 100px;

&::after {
position: absolute;
width: 100%;
height: 100%;
content: '';
background: radial-gradient(circle at 40%, #fff 0%, transparent 20%),
radial-gradient(circle at 60%, #ace 0%, transparent 40%);
filter: blur(10px);
opacity: 0;
transition: opacity 0.5s ease-in-out;
}

@include hover {
&::after {
opacity: 0.8;
animation: hover-glow 2s infinite;
}
}
}

.c-mark-nav {
height: 32px;

.stroke {
stroke: #fff;
stroke-width: 1px;
}
}

.text-link {
position: relative;
transition: text-shadow 0.3s ease-in-out;

&.-active {
// layer won't work for this
text-decoration: underline;
text-underline-offset: 4px;
}

.nav-item:hover & {
text-shadow: 0 0 10px utils.$color-navy;
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
'use client';

import { MouseEventHandler, useRef, useState } from 'react';

import classNames from 'classnames';
import { motion, useScroll, useSpring, useTransform } from 'framer-motion';
import Link from 'next/link';
import { usePathname } from 'next/navigation';

import { sqrtAnyNum } from '~/utils/math';

import styles from './index.module.scss';

export const NavBarCommon = () => {
export const NavBar = () => {
/**
* Scroll animation for the navbar
*/
const { scrollYProgress } = useScroll();

const pathLength = useSpring(useTransform(scrollYProgress, [0, 1], [1, 0]));
Expand All @@ -24,8 +31,52 @@ export const NavBarCommon = () => {
const currentPath = usePathname();
const isActive = (path: string) => currentPath.startsWith(path);

/**
* Hover effect for the navbar
*/
const navBarRef = useRef<HTMLElement>(null);

type NavTranslate = {
x: number;
y: number;
};

const [navTranslate, setNavTranslate] = useState<NavTranslate>({
x: 0,
y: 0,
});

const handleMouseMove: MouseEventHandler = (event) => {
if (!navBarRef.current) return;
const rect = navBarRef.current?.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;

setNavTranslate({
x: sqrtAnyNum(event.clientX - centerX) / 2,
y: sqrtAnyNum(event.clientY - centerY) / 2,
});

navBarRef.current.style.setProperty(
'--x',
`${event.clientX - rect.left - 20}px`,
);
navBarRef.current.style.setProperty(
'--y',
`${event.clientY - rect.top - 20}px`,
);
};

return (
<nav className={styles['nav-bar']}>
<motion.nav
className={styles['nav-bar']}
ref={navBarRef}
onMouseMove={handleMouseMove}
whileHover={{
translateX: navTranslate.x,
translateY: navTranslate.y,
}}
>
<ul className={styles['nav-items']}>
<li className={styles['nav-item']}>
<Link
Expand Down Expand Up @@ -101,6 +152,6 @@ export const NavBarCommon = () => {
</Link>
</li>
</ul>
</nav>
</motion.nav>
);
};
65 changes: 0 additions & 65 deletions src/components/common/navBarCommon/index.module.scss

This file was deleted.

4 changes: 2 additions & 2 deletions src/components/pages/home/homeDynamic/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

// import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { NavBarCommon } from '~/components/common/navBarCommon';
import { NavBar } from '~/components/common/navBar';
import { useDeviceDetect } from '~/hooks';

import { IconsPc } from '../IconsPc';
Expand All @@ -18,7 +18,7 @@ export const HomeDynamic = () => {

return (
<>
<NavBarCommon />
<NavBar />
<main>{content()}</main>
</>
);
Expand Down
17 changes: 17 additions & 0 deletions src/utils/math.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @file math.ts
* @brief Math utility functions
*/

/**
* Get the square root of a number with the sign of the number preserved
*
* @param x number
* @returns the square root of the number with the sign of the number preserved
*/
export const sqrtAnyNum = (x: number) => {
if (x < 0) {
return -Math.sqrt(Math.abs(x));
}
return Math.sqrt(x);
};

0 comments on commit 1e65aa5

Please sign in to comment.