diff --git a/src/assets/theme/index.js b/src/assets/theme/index.js index ef0287f..28fb8ed 100644 --- a/src/assets/theme/index.js +++ b/src/assets/theme/index.js @@ -26,6 +26,13 @@ export const textSizes = { hg: 200, } +export const screenSizes = { + xs: 670, + sm: 800, + md: 1000, + lg: 1500, +} + export const defaultTheme = { background: colours.midnightDarker, foreground: colours.rose, highlight: colours.highlight } diff --git a/src/components/Header/index.js b/src/components/Header/index.js index 85b5ab1..3df1d1b 100644 --- a/src/components/Header/index.js +++ b/src/components/Header/index.js @@ -1,36 +1,66 @@ import { h } from 'preact' import { Link as ReactLink } from 'react-router-dom' -import { RightBox, StyledRow as Row } from './styles' +import { RightBox, StyledRow as Row, Modal } from './styles' import { ImageLogo } from '../Logo' +import { useWindowSize } from '../../hooks/dom' import Link from '../Link' +import { Span } from '../Text' +import CrossSvg from '../Svg/Cross' import navigation from '../../data/navigation' -import { colours, textSizes } from '../../assets/theme' +import { colours, screenSizes, textSizes } from '../../assets/theme' +import { useToggle } from '../../hooks/utility' -const Navigation = ({ theme = {}, lang = 'en' }) => ( - - {navigation[lang].map(navItem => {navItem.label})} - -) +const Navigation = ({ theme = {}, lang = 'en', headerTheme }) => navigation[lang].map(navItem => ( + + {navItem.label} + +)) - -const BigHeader = ({ theme = {}, lang = 'en', ...rest }) => ( - +const NavigationModal = ({ theme = {}, lang = 'en', headerTheme, toggleMenuOpen, ...rest }) => ( + - + +
+ +
+
+) + +const FullHeader = ({ theme = {}, headerTheme = {}, lang = 'en', miniHeader, isMobile, toggleMenuOpen, ...rest }) => ( + + {!miniHeader ? + + : null} + {!isMobile ? ( + + + + ) : Menu} ) -const MiniHeader = ({ theme = {}, lang = 'en', ...rest }) => ( - - - -) -const Header = ({ miniHeader, ...rest }) => miniHeader ? : + +const Header = ({ miniHeader, theme, ...rest }) => { + const headerTheme = { foreground: theme.background, background: 'transparent', } + const { width: screenWidth } = useWindowSize() + const [menuOpen, toggleMenuOpen] = useToggle(false) + const isMobile = screenWidth < screenSizes.lg + + if (menuOpen) return + + return +} export default Header diff --git a/src/components/Header/styles.js b/src/components/Header/styles.js index dda927f..2382ef6 100644 --- a/src/components/Header/styles.js +++ b/src/components/Header/styles.js @@ -1,5 +1,7 @@ import styled from 'styled-components' +import { screenSizes } from '../../assets/theme' import { Row } from '../Flex' +import CrossSvg from '../Svg/Cross' export const StyledRow = styled(Row)` @@ -19,12 +21,56 @@ export const StyledRow = styled(Row)` padding: 1em; } - a:hover { - opacity: 0.5; + + a, span { + margin-right: 2em; + cursor: pointer; + + @media screen and (max-width: ${screenSizes.md}px) { + margin-right: 1em; + } + + &:hover { + opacity: 0.5; + } } ` export const RightBox = styled(Row)` - a { - margin-right: 4em; +` + +export const Modal = styled.div` + z-index: 100; + background-color: ${({ theme }) => theme.background}; + color: ${({ theme }) => theme.foreground}; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + pointer-events: all; + + + img { + max-height: 80px; + mix-blend-mode: exclusion; + padding: 1em; } + + div { + padding: 3em; + display: flex; + flex-direction: column; + } + + div a { + margin-bottom: 1em; + font-size: 6vh; + display: inline-block; + line-height: 0.8; + } +` +export const PositionedCross = styled(CrossSvg)` + position: fixed; + right: 1em; + top: 1em; ` \ No newline at end of file diff --git a/src/components/Link/index.js b/src/components/Link/index.js index 18de9f8..51df15d 100644 --- a/src/components/Link/index.js +++ b/src/components/Link/index.js @@ -11,8 +11,6 @@ const Link = ({ children, to, activeOnlyWhenExact = true, href, textProps: { col exact: activeOnlyWhenExact }) - console.log({ colour }) - return href ? {children} : ( {children} diff --git a/src/helpers/string.js b/src/helpers/string.js index e41aa5a..d9b40c4 100644 --- a/src/helpers/string.js +++ b/src/helpers/string.js @@ -1,5 +1,8 @@ export const slugify = (title) => { - let str = title.replace(/^\s+|\s+$/g, '') // trim + let str = title ? title.replace(/^\s+|\s+$/g, '') : null // trim + + if (!str) return title; + str = str.toLowerCase() // remove accents, swap ñ for n, etc @@ -22,11 +25,11 @@ export const capitaliseFirstLetter = word => word ? `${word?.charAt(0).toUpperCase()}${word?.slice(1)}` : ''; export const camelise = str => { - return str + return str ? str .replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => { return index === 0 ? letter.toLowerCase() : letter.toUpperCase(); }) - .replace(/\s+/g, ''); + .replace(/\s+/g, '') : str }; /** diff --git a/src/hooks/dom.js b/src/hooks/dom.js index 0d0f8fc..06abda4 100644 --- a/src/hooks/dom.js +++ b/src/hooks/dom.js @@ -35,3 +35,31 @@ export const useWindowDimensions = () => { return { width, height } } + + +export const useWindowSize = () => { + // Initialize state with undefined width/height so server and client renders match + // Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/ + const [windowSize, setWindowSize] = useState({ + width: undefined, + height: undefined, + }) + + useEffect(() => { + // Handler to call on window resize + function handleResize() { + // Set window width/height to state + setWindowSize({ + width: window.innerWidth, + height: window.innerHeight, + }) + } + // Add event listener + window.addEventListener('resize', handleResize) + // Call handler right away so state gets updated with initial window size + handleResize() + // Remove event listener on cleanup + return () => window.removeEventListener('resize', handleResize) + }, []) // Empty array ensures that effect is only run on mount + return windowSize +} \ No newline at end of file diff --git a/src/layouts/InfoLayout/index.js b/src/layouts/InfoLayout/index.js index 4184505..9d546ca 100644 --- a/src/layouts/InfoLayout/index.js +++ b/src/layouts/InfoLayout/index.js @@ -23,7 +23,7 @@ const InfoLayout = ({ title, subtitle, image, children, theme }) => ( {children} -
+

{title}

{ pastSeries.push(series) return false - }) @@ -32,12 +31,14 @@ const Series = () => { -

{strings.en.currentSeries}

- - {currentSeries.map(series => ( - - ))} - + {currentSeries.map(series => ( + +

{strings.en.currentSeries}

+ + + +
+ ))}

{strings.en.pastSeries}

{pastSeries.map(series => ( diff --git a/src/pages/SeriesPage/index.js b/src/pages/SeriesPage/index.js index c3ade91..7dbc6e3 100644 --- a/src/pages/SeriesPage/index.js +++ b/src/pages/SeriesPage/index.js @@ -16,18 +16,14 @@ import { TrailerContainer, } from './styles' -import config from '../../data/config' import Page from '../../layouts/Page' import { splitArray } from '../../helpers/utils' -import Header from '../../components/Header' -import theme from '../../assets/theme' const SeriesPage = ({ data }) => { - - const credits = ` + const credits = data.credits ? ` ## Credits ${data.credits} - ` + ` : null const dateString = `${new Date()}` let tzShort = @@ -52,7 +48,7 @@ const SeriesPage = ({ data }) => {

{data.title}:

{data.subtitle}

- {data.description} + {data.description ? {data.description} : null} {data.trailer ? ( @@ -101,7 +97,7 @@ const SeriesPage = ({ data }) => { ))} ) : null} - {data.credits ? + {credits ? Credits {credits} : null}