|
1 |
| -import { useState } from 'react'; |
2 |
| -import { useSpring, animated } from 'react-spring'; |
| 1 | +import { useState, useEffect, useCallback } from 'react'; |
3 | 2 | import Link from 'next/link';
|
4 | 3 |
|
| 4 | +import FadeLeftToRight from 'components/Animations/FadeLeftToRight.component'; |
| 5 | +import FadeLeftToRightItem from 'components/Animations/FadeLeftToRightItem.component'; |
| 6 | + |
5 | 7 | import LINKS from '../../utils/constants/LINKS';
|
6 | 8 |
|
7 | 9 | /**
|
8 |
| - * Shows the mobile menu. |
| 10 | + * Hamburger component used in mobile menu. Animates to a X when clicked |
| 11 | + * @function Hamburger |
| 12 | + * @param {MouseEventHandler<HTMLButtonElement>} onClick - onClick handler to respond to clicks |
| 13 | + * @param {boolean} isExpanded - Should the hamburger animate to a X? |
| 14 | + * @returns {JSX.Element} - Rendered component |
9 | 15 | */
|
| 16 | + |
10 | 17 | const Hamburger = () => {
|
11 | 18 | const [isExpanded, setisExpanded] = useState(false);
|
12 |
| - const hamburgerSlideDownAnimation = useSpring({ |
13 |
| - to: [ |
14 |
| - { |
15 |
| - opacity: isExpanded ? 1 : 0, |
16 |
| - marginTop: isExpanded ? '170px' : '-180px', |
17 |
| - }, |
18 |
| - ], |
19 |
| - from: { |
20 |
| - opacity: isExpanded ? 1 : 0, |
21 |
| - marginTop: isExpanded ? '170px' : '-180px', |
22 |
| - }, |
23 |
| - }); |
24 |
| - const showHamburgerHideXAnimation = useSpring({ |
25 |
| - to: [ |
26 |
| - { |
27 |
| - opacity: isExpanded ? 0 : 1, |
28 |
| - display: isExpanded ? 'none' : 'inline', |
29 |
| - }, |
30 |
| - ], |
31 |
| - from: { |
32 |
| - opacity: isExpanded ? 0 : 1, |
33 |
| - }, |
34 |
| - }); |
35 |
| - const showXHideHamburgerAnimation = useSpring({ |
36 |
| - to: [ |
37 |
| - { |
38 |
| - opacity: isExpanded ? 1 : 0, |
39 |
| - display: isExpanded ? 'inline' : 'none', |
40 |
| - }, |
41 |
| - ], |
42 |
| - from: { |
43 |
| - opacity: isExpanded ? 0 : 1, |
44 |
| - display: isExpanded ? 'none' : 'inline', |
45 |
| - }, |
46 |
| - }); |
| 19 | + const [hidden, setHidden] = useState('invisible'); |
| 20 | + |
| 21 | + useEffect(() => { |
| 22 | + if (isExpanded) { |
| 23 | + //document.addEventListener("mousedown", handleClickOutside); |
| 24 | + setHidden(''); |
| 25 | + } else { |
| 26 | + setTimeout(() => { |
| 27 | + setHidden('invisible'); |
| 28 | + }, 1000); |
| 29 | + |
| 30 | + // document.removeEventListener("mousedown", handleClickOutside); |
| 31 | + } |
| 32 | + /*return () => { |
| 33 | + document.removeEventListener("mousedown", handleClickOutside); |
| 34 | + };*/ |
| 35 | + }, [isExpanded]); |
| 36 | + |
| 37 | + const handleMobileMenuClick = useCallback(() => { |
| 38 | + /** |
| 39 | + * Anti-pattern: setisExpanded(!isExpanded) |
| 40 | + * Even if your state updates are batched and multiple updates to the enabled/disabled state are made together |
| 41 | + * each update will rely on the correct previous state so that you always end up with the result you expect. |
| 42 | + */ |
| 43 | + setisExpanded((prevExpanded) => !prevExpanded); |
| 44 | + }, [setisExpanded]); |
| 45 | + |
| 46 | + const hamburgerLine = |
| 47 | + 'h-1 w-10 my-1 rounded-full bg-white transition ease transform duration-300 not-sr-only'; |
| 48 | + |
| 49 | + const opacityFull = 'opacity-100 group-hover:opacity-100'; |
| 50 | + |
47 | 51 | return (
|
48 |
| - <> |
49 |
| - <label |
50 |
| - htmlFor="menu-toggle" |
51 |
| - aria-label="Meny" |
52 |
| - className="block cursor-pointer md:hidden" |
| 52 | + <div className="z-50 md:hidden lg:hidden xl:hidden bg-gray-800"> |
| 53 | + <button |
| 54 | + className="flex flex-col w-16 rounded justify-center items-center group" |
| 55 | + data-cy="hamburger" |
| 56 | + data-testid="hamburger" |
| 57 | + onClick={handleMobileMenuClick} |
| 58 | + aria-expanded={isExpanded} |
| 59 | + type="button" |
53 | 60 | >
|
54 |
| - <animated.svg |
55 |
| - id="hamburgersvg" |
56 |
| - style={showHamburgerHideXAnimation} |
57 |
| - onClick={() => { |
58 |
| - setisExpanded((prevExpanded) => !prevExpanded); |
59 |
| - }} |
60 |
| - className="text-gray-900 fill-current" |
61 |
| - xmlns="https://www.w3.org/2000/svg" |
62 |
| - width="25" |
63 |
| - height="25" |
64 |
| - viewBox="0 0 25 25" |
65 |
| - > |
66 |
| - <path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z" /> |
67 |
| - </animated.svg> |
68 |
| - <animated.svg |
69 |
| - id="xsvg" |
70 |
| - onClick={() => { |
71 |
| - setisExpanded((prevExpanded) => !prevExpanded); |
72 |
| - }} |
73 |
| - style={showXHideHamburgerAnimation} |
74 |
| - xmlns="https://www.w3.org/2000/svg" |
75 |
| - width="25" |
76 |
| - height="25" |
77 |
| - viewBox="0 0 25 25" |
78 |
| - > |
79 |
| - <line x1="18" y1="6" x2="6" y2="18" /> |
80 |
| - <line x1="6" y1="6" x2="18" y2="18" /> |
81 |
| - </animated.svg> |
82 |
| - </label> |
83 |
| - {isExpanded && ( |
84 |
| - <animated.div |
85 |
| - style={hamburgerSlideDownAnimation} |
| 61 | + <span className="sr-only text-white text-2xl">Hamburger</span> |
| 62 | + <span |
| 63 | + data-testid="hamburgerline" |
| 64 | + className={`${hamburgerLine} ${ |
| 65 | + isExpanded |
| 66 | + ? 'rotate-45 translate-y-3 opacity-100 group-hover:opacity-100' |
| 67 | + : opacityFull |
| 68 | + }`} |
| 69 | + /> |
| 70 | + <span |
| 71 | + className={`${hamburgerLine} ${ |
| 72 | + isExpanded ? 'opacity-0' : opacityFull |
| 73 | + }`} |
| 74 | + /> |
| 75 | + <span |
| 76 | + className={`${hamburgerLine} ${ |
| 77 | + isExpanded |
| 78 | + ? '-rotate-45 -translate-y-3 opacity-100 group-hover:opacity-100' |
| 79 | + : opacityFull |
| 80 | + }`} |
| 81 | + /> |
| 82 | + </button> |
| 83 | + <FadeLeftToRight |
| 84 | + delay={0.2} |
| 85 | + staggerDelay={0.2} |
| 86 | + animateNotReverse={isExpanded} |
| 87 | + > |
| 88 | + <div |
86 | 89 | id="mobile-menu"
|
87 |
| - className="absolute right-0 z-10 w-full text-center text-black bg-white " |
| 90 | + aria-hidden={!isExpanded} |
| 91 | + className={`absolute right-0 z-10 w-full text-center text-black bg-white ${hidden}`} |
88 | 92 | >
|
89 | 93 | <ul>
|
90 | 94 | {LINKS.map(({ id, title, href }) => (
|
91 |
| - <li |
92 |
| - key={id} |
93 |
| - id="mobile-li" |
94 |
| - className="w-full p-4 border-t border-gray-400 border-solid rounded" |
95 |
| - > |
96 |
| - <Link href={href}> |
97 |
| - <a className="inline-block px-4 py-2 no-underline hover:text-black hover:underline"> |
98 |
| - {title} |
99 |
| - </a> |
100 |
| - </Link> |
101 |
| - </li> |
| 95 | + <FadeLeftToRightItem key={id} cssClass="block"> |
| 96 | + <li |
| 97 | + id="mobile-li" |
| 98 | + className="w-full p-4 border-t border-gray-400 border-solid rounded" |
| 99 | + > |
| 100 | + <Link href={href}> |
| 101 | + <a className="inline-block px-4 py-2 no-underline hover:text-black hover:underline"> |
| 102 | + {title} |
| 103 | + </a> |
| 104 | + </Link> |
| 105 | + </li> |
| 106 | + </FadeLeftToRightItem> |
102 | 107 | ))}
|
103 | 108 | </ul>
|
104 |
| - </animated.div> |
105 |
| - )} |
106 |
| - </> |
| 109 | + </div> |
| 110 | + </FadeLeftToRight> |
| 111 | + </div> |
107 | 112 | );
|
108 | 113 | };
|
109 | 114 |
|
|
0 commit comments