Header.tsx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. import dynamic from 'next/dynamic'
  2. import Link from 'next/link'
  3. import { useRouter } from 'next/router'
  4. import { useContext, useEffect, useState } from 'react'
  5. import { ClusterContext, DEFAULT_CLUSTER } from '../../contexts/ClusterContext'
  6. import Pyth from '../../images/logomark.inline.svg'
  7. import MobileMenu from './MobileMenu'
  8. const WalletMultiButtonDynamic = dynamic(
  9. async () =>
  10. (await import('@solana/wallet-adapter-react-ui')).WalletMultiButton,
  11. { ssr: false }
  12. )
  13. export interface BurgerState {
  14. initial: boolean | null
  15. opened: boolean | null
  16. }
  17. const Header = () => {
  18. const { cluster } = useContext(ClusterContext)
  19. const router = useRouter()
  20. const [isSticky, setIsSticky] = useState(false)
  21. const navigation = [
  22. {
  23. name: 'Main',
  24. href: `/${cluster === DEFAULT_CLUSTER ? '' : `?cluster=${cluster}`}`,
  25. target: '_self',
  26. },
  27. {
  28. name: 'Pyth Network',
  29. href: 'https://pyth.network/',
  30. target: '_blank',
  31. },
  32. ]
  33. const [headerState, setHeaderState] = useState<BurgerState>({
  34. initial: false,
  35. opened: null,
  36. })
  37. // Toggle menu
  38. const handleToggleMenu = () => {
  39. if (headerState.initial === false) {
  40. setHeaderState({
  41. initial: null,
  42. opened: true,
  43. })
  44. } else {
  45. setHeaderState({
  46. ...headerState,
  47. opened: !headerState.opened,
  48. })
  49. }
  50. }
  51. useEffect(() => {
  52. window.addEventListener('scroll', ifSticky)
  53. return () => {
  54. window.removeEventListener('scroll', ifSticky)
  55. }
  56. })
  57. const ifSticky = () => {
  58. const scrollTop = window.scrollY
  59. if (!headerState.opened) {
  60. scrollTop >= 250 ? setIsSticky(true) : setIsSticky(false)
  61. }
  62. }
  63. return (
  64. <>
  65. <header
  66. className={`left-0 top-0 z-40 w-full px-1 transition-all lg:px-10
  67. ${isSticky || headerState.opened ? 'fixed' : 'absolute'}
  68. ${isSticky && !headerState.opened ? 'bg-darkGray shadow-black' : ''}
  69. `}
  70. >
  71. <div
  72. className={`relative flex items-center justify-between ${
  73. isSticky ? 'lg:py-4' : 'before:gradient-border md:py-6'
  74. } px-4 py-3 lg:px-10 lg:py-6`}
  75. >
  76. <Link href="/">
  77. <a
  78. className={`flex min-h-[45px] basis-[180px] cursor-pointer items-center`}
  79. >
  80. <Pyth />
  81. </a>
  82. </Link>
  83. <nav>
  84. <ul
  85. className={`list-none space-x-10 ${
  86. headerState.opened ? 'hidden' : 'hidden lg:flex'
  87. }`}
  88. >
  89. {navigation.map((item) => (
  90. <li key={item.name}>
  91. <Link href={item.href}>
  92. <a
  93. className={
  94. router.pathname == item.href
  95. ? 'nav-link font-bold'
  96. : 'nav-link'
  97. }
  98. >
  99. {item.name}
  100. </a>
  101. </Link>
  102. </li>
  103. ))}
  104. </ul>
  105. </nav>
  106. <div className="flex items-center justify-end space-x-2">
  107. <div className="h-[45px] w-[180px]">
  108. {headerState.opened ? null : (
  109. <WalletMultiButtonDynamic className="primary-btn float-right pt-0.5" />
  110. )}
  111. </div>
  112. <div
  113. className={`${
  114. headerState.opened
  115. ? 'relative top-0 right-5 left-0 basis-7'
  116. : 'lg:hidden'
  117. }
  118. `}
  119. onClick={handleToggleMenu}
  120. >
  121. <button
  122. className={`group ml-auto align-middle ${
  123. headerState.opened ? 'block' : 'lg:hidden'
  124. }`}
  125. >
  126. <span
  127. className={`ml-auto block h-0.5 w-3.5 rounded-sm bg-light transition-all lg:group-hover:w-5 ${
  128. headerState.opened
  129. ? 'mb-0 w-5 translate-y-1 rotate-45'
  130. : 'mb-1'
  131. }`}
  132. ></span>
  133. <span
  134. className={`mb-1 block h-0.5 w-5 rounded-sm bg-light transition-all ${
  135. headerState.opened && 'opacity-0'
  136. }`}
  137. ></span>
  138. <span
  139. className={`ml-auto block h-0.5 w-3.5 rounded-sm bg-light transition-all lg:group-hover:w-5 ${
  140. headerState.opened
  141. ? 'mb-0 w-5 -translate-y-1 -rotate-45'
  142. : 'mb-1'
  143. }`}
  144. ></span>
  145. </button>
  146. </div>
  147. </div>
  148. </div>
  149. </header>
  150. <MobileMenu headerState={headerState} setHeaderState={setHeaderState} />
  151. </>
  152. )
  153. }
  154. export default Header