Advertisement
Guest User

src/ui/Header.js

a guest
Jul 23rd, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.56 KB | None | 0 0
  1. import React, { useEffect, useState } from "react"
  2. import styled from "styled-components"
  3. import { Plus, Menu, X } from "react-feather"
  4. import { Box, Flex, Image, Button } from "rebass"
  5. import { Link, StaticQuery, graphql } from "gatsby"
  6.  
  7. import { isWindow } from "src/utils/checks"
  8. import { Search } from "src/ui/Search"
  9. import { Container } from "src/ui/Container"
  10. import logo from "src/images/logo.png"
  11.  
  12. const isWindowPresent = isWindow()
  13.  
  14.  
  15. const disableScroll = () => {
  16. if (isWindowPresent) {
  17. const scrollbarWidth =
  18. window.innerWidth - window.document.documentElement.clientWidth
  19. window.document.body.classList.add('modal-open')
  20. window.document.body.style.paddingRight = `${scrollbarWidth}px`
  21. }
  22. }
  23.  
  24. const enableScroll = () => {
  25. if (isWindowPresent) {
  26. window.document.body.classList.remove('modal-open')
  27. window.document.body.style.paddingRight = `0px`
  28. }
  29. }
  30.  
  31. export const Header = ({ hideSearch }) => {
  32. const [isBurgerMenuOpen, setIsBurgerMenu] = useState(false)
  33. const [isScrolledTop, setHeaderVisibility] = useState(true)
  34. let prevScrollPosition = isWindowPresent && window.scrollY
  35.  
  36. const handleScrollDirection = () => {
  37. if (prevScrollPosition > window.scrollY && window.scrollY > 100) {
  38. setHeaderVisibility(true)
  39. }
  40. if (prevScrollPosition < window.scrollY && window.scrollY > 150) {
  41. setHeaderVisibility(false)
  42. }
  43. prevScrollPosition = window.scrollY
  44. }
  45.  
  46. useEffect(() => {
  47. isWindowPresent && window.addEventListener("scroll", handleScrollDirection)
  48. isBurgerMenuOpen ? disableScroll() : enableScroll()
  49. return () =>
  50. isWindowPresent && window.removeEventListener("scroll", handleScrollDirection)
  51. }, [isBurgerMenuOpen])
  52.  
  53. const handleBurgerMenuClick = e => {
  54. e.preventDefault()
  55. setIsBurgerMenu(!isBurgerMenuOpen)
  56. }
  57.  
  58. return (
  59. <StaticQuery
  60. query={query}
  61. render={({ allDatoCmsCategory: { nodes } }) => (
  62. <StyledHeader isVisible={isScrolledTop}>
  63. {isBurgerMenuOpen && (
  64. <BurgerMenuBackground
  65. alignItems={"center"}
  66. flexDirection={"column"}
  67. justifyContent={"space-around"}
  68. backgroundColor="black"
  69. >
  70. <Links
  71. flexDirection={"column"}
  72. alignItems={"center"}
  73. justifyContent={"space-between"}
  74. >
  75. {nodes.map(({ slug, title, id }) => (
  76. <Link
  77. key={id}
  78. to={`/category/${slug}`}
  79. css={{
  80. display: "block",
  81. marginBottom: "24px",
  82. fontSize: "3.0vh",
  83. }}
  84. >
  85. {title}
  86. </Link>
  87. ))}
  88. {[...serviceLinks, ...mobileLinks].map(({ slug, title }) => (
  89. <Link
  90. key={slug}
  91. to={`/${slug}`}
  92. css={{
  93. display: "block",
  94. marginBottom: "24px",
  95. fontSize: "3.0vh",
  96. }}
  97. >
  98. {title}
  99. </Link>
  100. ))}
  101. </Links>
  102. </BurgerMenuBackground>
  103. )}
  104. <Container>
  105. <Flex
  106. alignItems={"center"}
  107. justifyContent={"space-between"}
  108. mb={[0, 0, 0, 3]}
  109. >
  110. <Link to="/">
  111. <Image
  112. src={logo}
  113. alt="logo"
  114. width={["120px"]}
  115. css={{
  116. zIndex: "20",
  117. position: "relative",
  118. }}
  119. ></Image>
  120. </Link>
  121. {!hideSearch && <StyledSearch position="header" />}
  122. <SubmitVideoButton variant="primary">
  123. <Plus size={"16"}></Plus>
  124. <span>Submit video</span>
  125. </SubmitVideoButton>
  126. <BurgerMenu onClick={handleBurgerMenuClick}>
  127. {!isBurgerMenuOpen && <Menu size={"32"} color={"white"}></Menu>}
  128. {isBurgerMenuOpen && <X size={"32"} color={"white"}></X>}
  129. </BurgerMenu>
  130. </Flex>
  131. <Flex justifyContent={"space-between"}>
  132. <Navigation>
  133. <Box as="ul" m={"0"} pl={"0"}>
  134. {nodes.map(({ slug, title, id }) => (
  135. <Box as="li" key={id} mr={"6"}>
  136. <Link to={`/category/${slug}`}>{title}</Link>
  137. </Box>
  138. ))}
  139. </Box>
  140. </Navigation>
  141. <Navigation>
  142. <Box as="ul" m={"0"} pl={"0"}>
  143. {serviceLinks.map(({ slug, title }) => (
  144. <Box as="li" key={slug} mr={"6"}>
  145. <Link to={`/${slug}`}>{title}</Link>
  146. </Box>
  147. ))}
  148. </Box>
  149. </Navigation>
  150. </Flex>
  151. </Container>
  152. </StyledHeader>
  153. )}
  154. />
  155. )
  156. }
  157.  
  158. const query = graphql`
  159. query Categories {
  160. allDatoCmsCategory {
  161. nodes {
  162. title
  163. slug
  164. id
  165. }
  166. }
  167. }
  168. `
  169.  
  170. const serviceLinks = [
  171. { slug: "blog", title: "Blog" },
  172. { slug: "about-us", title: "About us" },
  173. { slug: "contact", title: "Contact us" },
  174. ]
  175.  
  176. const mobileLinks = [{ slug: "search", title: "Search" }]
  177.  
  178. const StyledHeader = styled.header`
  179. background-color: ${({ theme }) => theme.colors.black};
  180. padding-top: 16px;
  181. padding-bottom: 16px;
  182. transition: all 0.2s;
  183. position: sticky;
  184. z-index: 100;
  185. top: -110px;
  186. transition: top 0.55s ease-in-out;
  187.  
  188. ${({ isVisible }) =>
  189. isVisible &&
  190. `
  191. top:0;
  192. `}
  193. `
  194.  
  195. const Navigation = styled.nav`
  196. ul {
  197. display: flex;
  198. }
  199.  
  200. li {
  201. list-style: none;
  202. &:last-child {
  203. margin-right: 0;
  204. }
  205. }
  206.  
  207. a {
  208. transition: all 0.3s;
  209. text-decoration: none;
  210. font-weight: 500;
  211. color: ${({ theme }) => theme.colors.white};
  212.  
  213. &:hover {
  214. color: ${({ theme }) => theme.colors.red};
  215. }
  216. }
  217.  
  218. @media (max-width: ${({ theme }) => theme.breakpoints[2]}) {
  219. display: none;
  220. }
  221. `
  222.  
  223. const SubmitVideoButton = styled(Button)`
  224. display: flex;
  225. align-items: center;
  226.  
  227. span {
  228. margin-left: 4px;
  229. }
  230.  
  231. @media (max-width: ${({ theme }) => theme.breakpoints[2]}) {
  232. display: none;
  233. }
  234. `
  235.  
  236. const BurgerMenu = styled.button`
  237. position: relative;
  238. width: 40px;
  239. height: 40px;
  240. border: 0;
  241. background-color: transparent;
  242. display: none;
  243. outline: none;
  244. &:hover {
  245. cursor: pointer;
  246. }
  247. svg {
  248. position: absolute;
  249. top: 50%;
  250. left: 50%;
  251. transform: translate(-50%, -50%);
  252. }
  253.  
  254. @media (max-width: ${({ theme }) => theme.breakpoints[2]}) {
  255. display: block;
  256. }
  257. `
  258.  
  259. const StyledSearch = styled(Search)`
  260. transition: all 0.2s;
  261.  
  262. @media (max-width: ${({ theme }) => theme.breakpoints[2]}) {
  263. display: none;
  264. }
  265. `
  266. const BurgerMenuBackground = styled(Flex)`
  267. position: fixed;
  268. height: calc(100% + 72px);
  269. width: 100%;
  270. top: 0;
  271. left: 0;
  272. right: 0;
  273. bottom: 0;
  274. a {
  275. transition: all 0.3s;
  276. text-decoration: none;
  277. font-weight: 500;
  278. color: ${({ theme }) => theme.colors.white};
  279. &:hover {
  280. color: ${({ theme }) => theme.colors.red};
  281. }
  282. }
  283. `
  284. const Links = styled(Flex)`
  285. position: absolute;
  286. top: 50%;
  287. left: 50%;
  288. transform: translate(-50%, -50%);
  289. `
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement