Skip to content

Commit 21c1ac6

Browse files
authored
Merge pull request #118 from w3bdesign/development
Improve design
2 parents 86cae70 + 281ac51 commit 21c1ac6

File tree

4 files changed

+104
-66
lines changed

4 files changed

+104
-66
lines changed

src/components/Layout/Header.component.tsx

+65-46
Original file line numberDiff line numberDiff line change
@@ -2,90 +2,109 @@
22

33
import React from "react";
44
import Link from "next/link";
5-
import clsx from "clsx";
65
import { usePathname } from "next/navigation";
6+
import { motion } from "framer-motion";
77

8-
import { MotionDiv, MotionLi } from "@/lib/framer/client";
8+
import { MotionDiv, MotionLi, MotionUl } from "@/lib/framer/client";
99

1010
import MobileMenu from "./MobileMenu.component";
1111

12-
export default function Header() {
12+
const Header = () => {
1313
const pathname = usePathname();
1414

1515
const links = [
16-
{
17-
title: "Home",
18-
name: "Hjem",
19-
hash: "#hjem",
20-
href: "/",
21-
},
16+
{ title: "Home", name: "Hjem", hash: "#hjem", href: "/" },
2217
{
2318
title: "Prosjekter",
2419
name: "Prosjekter",
2520
hash: "#prosjekter",
2621
href: "/prosjekter",
2722
},
28-
{
29-
title: "CV",
30-
name: "CV",
31-
hash: "#cv",
32-
href: "/cv",
33-
},
23+
{ title: "CV", name: "CV", hash: "#cv", href: "/cv" },
3424
{
3525
title: "Github",
3626
name: "Github",
3727
hash: "#github",
3828
href: "https://github.com/w3bdesign",
3929
},
40-
{
41-
title: "Kontakt",
42-
name: "Kontakt",
43-
hash: "#kontakt",
44-
href: "/kontakt",
45-
},
30+
{ title: "Kontakt", name: "Kontakt", hash: "#kontakt", href: "/kontakt" },
4631
];
4732

4833
return (
4934
<header className="z-[999] relative">
5035
<MotionDiv
5136
className="bg-slate-800 bg-opacity-80 fixed top-0 left-1/2 h-[4.5rem] w-full shadow rounded-none shadow-lg shadow-black/[0.03] backdrop-blur-[0.5rem] sm:top-6 sm:h-[3.25rem] sm:w-[36rem] sm:rounded-full dark:bg-gray-900 dark:border-black/40 dark:bg-opacity-75"
52-
initial={{ y: -50, x: "-50%", opacity: 0 }}
53-
animate={{ y: 0, x: "-50%", opacity: 1, transition: { duration: 0.6 } }}
54-
></MotionDiv>
55-
37+
initial={{ y: -100, x: "-50%", opacity: 0 }}
38+
animate={{
39+
y: 0,
40+
x: "-50%",
41+
opacity: 1,
42+
transition: {
43+
y: { duration: 0.6, ease: "easeOut" },
44+
opacity: { duration: 0.6, ease: "easeOut" },
45+
},
46+
}}
47+
/>
5648
<nav className="flex fixed top-[0.65rem] left-1/2 h-12 -translate-x-1/2 py-2 sm:top-[1.7rem] sm:h-[initial] sm:py-0 w-full max-w-[370px] justify-end md:justify-between items-center">
57-
<ul className="hidden md:flex md:w-[22rem] flex-wrap items-center justify-center gap-y-1 text-[0.9rem] font-medium text-slate-200 sm:w-[initial] sm:flex-nowrap sm:gap-5">
49+
<MotionUl
50+
className="hidden md:flex md:w-[22rem] flex-wrap items-center justify-center gap-y-1 text-[0.9rem] font-medium text-slate-200 sm:w-[initial] sm:flex-nowrap sm:gap-5"
51+
variants={{
52+
hidden: { opacity: 0 },
53+
visible: {
54+
opacity: 1,
55+
transition: {
56+
staggerChildren: 0.1,
57+
delayChildren: 0.3,
58+
},
59+
},
60+
}}
61+
initial="hidden"
62+
animate="visible"
63+
>
5864
{links.map((link) => (
5965
<MotionLi
6066
className="h-3/4 flex items-center justify-center relative"
6167
key={link.hash}
62-
initial={{ y: -50, opacity: 0 }}
63-
animate={{ y: 0, opacity: 1, transition: { duration: 0.6 } }}
68+
variants={{
69+
hidden: { y: -20, opacity: 0 },
70+
visible: { y: 0, opacity: 1 },
71+
}}
72+
transition={{ duration: 0.3 }}
6473
>
65-
<Link
66-
prefetch={true}
67-
className={`flex w-full items-center justify-center px-2 py-2 hover:text-white transition font-semibold text-lg ${
68-
pathname === link.href ? "text-green-400" : ""
69-
}`}
70-
href={link.href}
71-
>
72-
<div
73-
className={clsx("glitch", {
74-
"underline underline-offset-4 decoration-2":
75-
pathname === link.href,
76-
})}
77-
data-text={link.name}
74+
<MotionDiv className="relative" whileHover="hover">
75+
<Link
76+
prefetch={true}
77+
className={`flex w-full items-center justify-center px-2 py-2 hover:text-white transition font-semibold text-lg ${
78+
pathname === link.href ? "text-green-400" : ""
79+
}`}
80+
href={link.href}
7881
>
79-
{link.name}
80-
</div>
81-
</Link>
82+
<div className="glitch relative" data-text={link.name}>
83+
{link.name}
84+
<motion.span
85+
className={`absolute bottom-0 left-0 h-0.5 bg-current ${
86+
pathname === link.href ? "bg-green-400" : "bg-white"
87+
}`}
88+
initial={{
89+
width: pathname === link.href ? "100%" : "0%",
90+
}}
91+
variants={{
92+
hover: { width: "100%" },
93+
}}
94+
transition={{ duration: 0.3 }}
95+
/>
96+
</div>
97+
</Link>
98+
</MotionDiv>
8299
</MotionLi>
83100
))}
84-
</ul>
101+
</MotionUl>
85102
<div id="hamburger-div" data-cy="hamburger-div" className="md:hidden">
86103
<MobileMenu links={links} />
87104
</div>
88105
</nav>
89106
</header>
90107
);
91-
}
108+
};
109+
110+
export default Header;

src/components/Layout/MobileMenu.component.tsx

+20-20
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,12 @@ const MobileMenu = ({ links }: IMobileMenuProps) => {
5656
};
5757

5858
const itemVariants = {
59-
/**
60-
* Returns an object with the CSS properties for a closed animation.
61-
*
62-
* @param {number} i - The index of the item being animated.
63-
* @return {Object} An object with CSS properties for the closed animation.
64-
*/
59+
/**
60+
* Returns an object with the CSS properties for a closed animation.
61+
*
62+
* @param {number} i - The index of the item being animated.
63+
* @return {Object} An object with CSS properties for the closed animation.
64+
*/
6565
closed: (i: number) => ({
6666
x: i % 2 === 0 ? "-100%" : "100%",
6767
opacity: 0,
@@ -72,19 +72,19 @@ const MobileMenu = ({ links }: IMobileMenuProps) => {
7272
duration: 0.15,
7373
},
7474
}),
75-
/**
76-
* Returns an object representing the animation properties for opening an item.
77-
*
78-
* @param {number} i - The index of the item.
79-
* @return {object} An object with the following properties:
80-
* - x: The x-coordinate of the item.
81-
* - opacity: The opacity of the item.
82-
* - transition: An object representing the animation properties.
83-
* - type: The type of the animation.
84-
* - stiffness: The stiffness of the animation.
85-
* - damping: The damping of the animation.
86-
* - delay: The delay of the animation.
87-
*/
75+
/**
76+
* Returns an object representing the animation properties for opening an item.
77+
*
78+
* @param {number} i - The index of the item.
79+
* @return {object} An object with the following properties:
80+
* - x: The x-coordinate of the item.
81+
* - opacity: The opacity of the item.
82+
* - transition: An object representing the animation properties.
83+
* - type: The type of the animation.
84+
* - stiffness: The stiffness of the animation.
85+
* - damping: The damping of the animation.
86+
* - delay: The delay of the animation.
87+
*/
8888
open: (i: number) => ({
8989
x: 0,
9090
opacity: 1,
@@ -111,7 +111,7 @@ const MobileMenu = ({ links }: IMobileMenuProps) => {
111111
data-testid="mobile-menu"
112112
data-cy="mobile-menu"
113113
aria-hidden={!isExpanded}
114-
className="fixed top-0 right-0 w-screen h-screen bg-gray-800 flex items-center justify-center -z-10"
114+
className="fixed top-0 right-0 w-screen h-screen bg-gray-800 flex items-center justify-center -z-10 -mt-4"
115115
initial="closed"
116116
animate="open"
117117
exit="closed"

src/hooks/useMobile.tsx

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { useState, useEffect } from "react";
2+
3+
export function useMobile(): boolean {
4+
const [isMobile, setIsMobile] = useState<boolean>(false);
5+
6+
useEffect(() => {
7+
const checkIfMobile = (): void => {
8+
setIsMobile(window.innerWidth < 640);
9+
};
10+
11+
checkIfMobile();
12+
window.addEventListener("resize", checkIfMobile);
13+
14+
return () => window.removeEventListener("resize", checkIfMobile);
15+
}, []);
16+
17+
return isMobile;
18+
}

src/lib/framer/client.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ import { motion } from "framer-motion";
44

55
export const MotionDiv = motion.div;
66
export const MotionLi = motion.li;
7+
export const MotionUl = motion.ul;

0 commit comments

Comments
 (0)