diff --git a/gatsby-config.js b/gatsby-config.js index 5065438..1329ae2 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -5,7 +5,42 @@ module.exports = { title: `Abc Project Design`, description: `Easy as ABC`, keywords: `Foo bar baz`, - navData: [], + navData: [ + { + title: "Home", + to: "/" + }, + { + title: "Services", + to: "/services", + subNav: [ + { + title: "Bathrooms", + to: "/services/bathrooms" + }, + { + title: "Tiling", + to: "/services/tiling" + }, + { + title: "Electrics", + to: "/services/electrics" + }, + { + title: "Carpentry", + to: "/services/carpentry" + } + ] + }, + { + title: "About", + to: "/about" + }, + { + title: "Contact", + to: "/contact" + } + ], reviews: [ { name: "Rated People", diff --git a/src/components/card.js b/src/components/card.js index 4b80755..b2af622 100644 --- a/src/components/card.js +++ b/src/components/card.js @@ -1,11 +1,11 @@ import React from "react"; +import { Link as GatsbyLink } from "gatsby"; import Img from "gatsby-image"; import styled from "styled-components"; const Container = styled.div` display: flex; align-items: center; - overflow: hidden; margin: 0 calc(var(--spacing-x-xs) * -1) var(--spacing-y-sm); @media (max-width: 30em) { @@ -15,15 +15,34 @@ const Container = styled.div` } `; -const Media = styled.div` +const Media = styled.span` padding: 0 var(--spacing-x-xs); + transition: transform 0.15s ease-in, filter 0.15s ease-in; `; -const Content = styled.div` + +const Content = styled.span` padding: 0 var(--spacing-x-xs); `; -export default function Card({ image, children }) { - return ( +const Link = styled(GatsbyLink)` + outline: 0; + text-decoration: none; + color: var(--color-black); + + &:hover ${Media} { + transform: scale(1.1); + filter: brightness(110%) contrast(110%); + } + + @media (max-width: 30em) { + &:nth-child(even) ${Container} { + flex-direction: row-reverse; + } + } +`; + +export default function Card({ image, children, to }) { + const render = () => ( {image && ( @@ -39,4 +58,5 @@ export default function Card({ image, children }) { {children} ); + return to ? {render()} : render(); } diff --git a/src/components/footer.js b/src/components/footer.js index e77daee..c3e37e8 100644 --- a/src/components/footer.js +++ b/src/components/footer.js @@ -10,6 +10,7 @@ const Content = styled.div` max-width: var(--theme-max-width); margin: 0 auto; padding: var(--spacing-y-lg) var(--spacing-x-sm); + font-size: var(--font-size-sm); text-align: center; `; diff --git a/src/components/header-logo.js b/src/components/header-logo.js index 075a6a6..8076bed 100644 --- a/src/components/header-logo.js +++ b/src/components/header-logo.js @@ -79,7 +79,7 @@ const Slogan = styled.p` export default function HeaderLogo({ transition }) { const [visible, setVisible] = useState(!transition); - useEffect(() => transition && setVisible(true)); + useEffect(() => transition && setVisible(true), [transition]); return ( diff --git a/src/components/menu-button.js b/src/components/menu-button.js index 4f155c4..bb2b7b6 100644 --- a/src/components/menu-button.js +++ b/src/components/menu-button.js @@ -9,6 +9,15 @@ const Container = styled.button` background-color: transparent; padding: 4px 8px; border: 0; + cursor: pointer; + + &:focus { + outline: 0; + } + + @media (min-width: 30em) { + display: none; + } `; const Bar = styled.span` diff --git a/src/components/nav-item.js b/src/components/nav-item.js new file mode 100644 index 0000000..97b7d93 --- /dev/null +++ b/src/components/nav-item.js @@ -0,0 +1,47 @@ +import React from "react"; +import styled, { css } from "styled-components"; +import NavLink from "./nav-link"; + +const SubList = styled.ul` + margin: 0 0 0 var(--spacing-x-md); + padding: 0; + list-style: none; + + @media (min-width: 30em) { + display: none; + flex-direction: column; + position: absolute; + margin: 0; + padding: var(--spacing-y-xs) var(--spacing-x-xs); + background-color: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(2px); + } +`; + +const ListItem = styled.li` + position: relative; + + &:focus-within ${SubList}, &:hover ${SubList} { + @media (min-width: 30em) { + display: flex; + } + } +`; + +export default function NavItem({ children, subNav, ...other }) { + const hasChildren = subNav && subNav.length > 0; + return ( + + {children} + {hasChildren && ( + + {subNav.map((link, i) => ( + + {link.title} + + ))} + + )} + + ); +} diff --git a/src/components/nav-link.js b/src/components/nav-link.js index d1e76f1..06a1b8c 100644 --- a/src/components/nav-link.js +++ b/src/components/nav-link.js @@ -1,56 +1,30 @@ import React from "react"; -import styled, { css } from "styled-components"; import { Link as GatsbyLink } from "gatsby"; +import styled from "styled-components"; -const SubList = styled.ul` - position: absolute; - display: none; - flex-direction: column; - min-width: 120px; - margin: 0; +const Link = styled(GatsbyLink)` + display: inline-block; padding: 0; - list-style: none; -`; + margin-bottom: var(--spacing-y-sm); + color: var(--color-white); + font-size: var(--font-size-lg); + text-decoration: none; + cursor: pointer; -const ListItem = styled.li` - position: relative; - margin: 0 var(--spacing-y-xs); + &:focus { + outline: none; + } - &:hover ${SubList} { - @media (min-width: 40rem) { - display: flex; - } + @media (min-width: 30em) { + font-size: var(--font-size-sm); + margin: 0 var(--spacing-x-xs); + padding: 9px 0; + border-bottom: 2px solid + ${props => (props.active ? `var(--color-white)` : `transparent`)}; } `; -const Link = styled(GatsbyLink)` - display: block; - color: white; - text-decoration: none; - padding: 5px; - margin-top: var(--spacing-y-xs); - border-bottom: 2px solid transparent; - - ${props => - props.active && - css` - border-color: var(--color-white); - `} -`; - -export default function NavLink({ children, subLinks, ...other }) { - return ( - - {children} - {subLinks && subLinks.length > 0 && ( - - {subLinks.map((link, i) => ( - - {link.title} - - ))} - - )} - - ); +export default function NavLink({ location, children, to }) { + console.log(location); + return {children}; } diff --git a/src/components/nav.js b/src/components/nav.js index d99ab9f..7c0af59 100644 --- a/src/components/nav.js +++ b/src/components/nav.js @@ -1,60 +1,86 @@ import React from "react"; +import { Link } from "gatsby"; import styled from "styled-components"; -import NavLink from "./nav-link"; +import NavItem from "./nav-item"; import MenuButton from "./menu-button"; +import LogoArrows from "../icons/logo-arrows.svg"; const Container = styled.div` - position: ${props => (props.open ? "fixed" : "absolute")}; + position: fixed; top: 0; right: 0; bottom: 0; + left: 0; + display: flex; + flex-direction: column-reverse; z-index: 6; + background-color: ${props => + props.open ? `rgba(0, 0, 0, 0.8)` : `rgba(0, 0, 0, 0.4)`}; + backdrop-filter: blur(2px); transform: ${props => - props.open ? `translate3d(0, 0, 0)` : `translate3d(100%, 0, 0)`}; - transition: transform 0.15s; - + props.open + ? `translate3d(0, 0, 0)` + : `translate3d(0, calc(-100% + 40px), 0)`}; + transition: transform 0.3s ease-in-out, background-color 0.3s ease-in-out; @media (min-width: 30em) { - bottom: auto; - left: 0; + position: absolute; display: flex; - background-color: rgba(0, 0, 0, 0.4); - backdrop-filter: blur(2px); + flex-direction: row; + bottom: auto; + background-color: rgba(0, 0, 0, 0.6); transform: none; transition: none; } `; const Menu = styled.div` - position: absolute; - top: 0; - left: 0; - padding: var(--spacing-y-xs) var(--spacing-x-md) 0 0; - transform: translateX(-100%); + display: flex; + justify-content: space-between; + align-items: stretch; + color: white; + margin: var(--spacing-x-xs) var(--spacing-y-sm); +`; - @media (min-width: 30em) { - display: none; +const Heading = styled(Link)` + display: flex; + flex-direction: column; + justify-content: space-around; + opacity: ${props => (props.visible ? 1 : 0)}; + transform: opacity 0.3s ease-in; + + svg { + width: 24px; + height: 12px; + + &:first-of-type { + path:first-child { + fill: var(--theme-color-primary); + } + + path:last-child { + fill: var(--theme-color-secondary); + } + } + &:last-of-type { + transform: rotate(180deg); + path:first-child { + fill: var(--theme-color-dark); + } + + path:last-child { + fill: var(--theme-color-secondary); + } + } } `; const Content = styled.nav` - margin: 0 var(--spacing-x-sm); + flex-grow: 1; + margin: var(--spacing-y-lg) var(--spacing-x-md); - @media (max-width: 30em) { - background-color: rgba(0, 0, 0, 0.4); - } -`; - -const Overlay = styled.div` - @media (max-width: 30em) { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 5; - display: ${props => (props.visible ? `block` : `none`)}; - background-color: rgba(0, 0, 0, 0.75); - backdrop-filter: blur(2px); + @media (min-width: 30em) { + display: flex; + margin: 0; } `; @@ -70,25 +96,25 @@ const List = styled.ul` `; export default function Nav({ data, open, setOpen }) { - const handleOverlayClick = () => setOpen(false); const handleButtonClick = () => setOpen(!open); return ( - <> - - - - - - - {data.map((link, i) => ( - - {link.title} - - ))} - - - - - + + + + + + + + + + + {data.map((link, i) => ( + + {link.title} + + ))} + + + ); } diff --git a/src/images/bathroom2.png b/src/images/bathroom2.png new file mode 100644 index 0000000..5566608 Binary files /dev/null and b/src/images/bathroom2.png differ diff --git a/src/images/service_bathroom.png b/src/images/service_bathroom.png new file mode 100644 index 0000000..fc72906 Binary files /dev/null and b/src/images/service_bathroom.png differ diff --git a/src/images/service_carpentry.png b/src/images/service_carpentry.png new file mode 100644 index 0000000..5119f19 Binary files /dev/null and b/src/images/service_carpentry.png differ diff --git a/src/images/service_electrics.png b/src/images/service_electrics.png new file mode 100644 index 0000000..41a9b30 Binary files /dev/null and b/src/images/service_electrics.png differ diff --git a/src/images/service_tiling.png b/src/images/service_tiling.png new file mode 100644 index 0000000..82249ea Binary files /dev/null and b/src/images/service_tiling.png differ diff --git a/src/layout.js b/src/layout.js index bc701ee..a73a6b1 100644 --- a/src/layout.js +++ b/src/layout.js @@ -1,6 +1,7 @@ -import React from "react"; +import React, { useState } from "react"; import { useStaticQuery, graphql } from "gatsby"; import { Helmet } from "react-helmet"; +import Nav from "./components/nav"; import Footer from "./components/footer"; import { createGlobalStyle } from "styled-components"; import "@fontsource/cooper-hewitt/400.css"; @@ -65,6 +66,7 @@ const GlobalStyle = createGlobalStyle` box-sizing: border-box; margin: 0; font-family: 'Cooper Hewitt', sans-serif; + overflow-x: hidden; overflow-y: ${props => (props.navOpen ? "hidden" : "auto")}; } @@ -83,7 +85,8 @@ const GlobalStyle = createGlobalStyle` } `; -export default function Layout({ children }) { +export default function Layout({ location, children }) { + console.log(location); const data = useStaticQuery(graphql` query HeaderQuery { site { @@ -91,11 +94,20 @@ export default function Layout({ children }) { title description keywords + navData { + title + to + subNav { + title + to + } + } } } } `); - const { title, description, keywords } = data.site.siteMetadata; + const { title, description, keywords, navData } = data.site.siteMetadata; + const [navOpen, setNavOpen] = useState(); return ( <>
@@ -106,10 +118,11 @@ export default function Layout({ children }) { { name: "keywords", content: keywords } ]} /> - + {children}
+