diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/components/base-layout.js | 55 | ||||
-rw-r--r-- | src/components/layout.js | 148 |
2 files changed, 133 insertions, 70 deletions
diff --git a/src/components/base-layout.js b/src/components/base-layout.js new file mode 100644 index 0000000..cb95f70 --- /dev/null +++ b/src/components/base-layout.js @@ -0,0 +1,55 @@ +import React from 'react' +import { ThemeProvider } from 'emotion-theming' +import Helmet from 'react-helmet' +import { Global, css } from '@emotion/core' + +import { Container } from './container' + +const globalStyles = ({ colours, transitions, fontStack, baseFontSize }) => css` + *, + html, + body { + margin: 0; + padding: 0; + } + p, + a, + h1, + h2, + h3, + h4, + h5, + div, + button { + font-family: ${fontStack}; + color: ${colours.main}; + } + p, + li { + line-height: 2em; + } + li { + list-style-position: outside; + margin-left: 20px; + } + a { + border-bottom: 1px dotted; + text-decoration: none; + &: hover { + transition: ${transitions.hover}; + } + } + body { + background: ${colours.background}; + } +` + +export const BaseLayout = ({ helmetData, children, height, theme }) => ( + <ThemeProvider theme={theme}> + <Global styles={globalStyles} /> + <Helmet {...helmetData}> + <html lang="en" /> + </Helmet> + <Container height={height}>{children}</Container> + </ThemeProvider> +) diff --git a/src/components/layout.js b/src/components/layout.js index 5e8ce25..fcc942e 100644 --- a/src/components/layout.js +++ b/src/components/layout.js @@ -1,7 +1,5 @@ -import React from 'react' -import Helmet from 'react-helmet' -import { css, Global } from '@emotion/core' -import { colours, fontStack, transitions } from './globals' +import React, { Component } from 'react' +import { themes } from './globals' import { faSpotify, faGithub, @@ -9,50 +7,26 @@ import { faKeybase } from '@fortawesome/free-brands-svg-icons' -import { Container } from './container' import { Header } from './header' import { FontAwesome } from './font-awesome' +import { ThemeSwitcher } from './theme-switcher' +import { BaseLayout } from './base-layout' +import { parseQuery, writeQuery } from '../lib/url' -const globalStyles = css` - *, - html, - body { - margin: 0; - padding: 0; - } - path { - fill: ${colours.main}; - } - p, - a, - h1, - h2, - h3, - h4, - h5, - div { - font-family: ${fontStack}; - color: ${colours.main}; - } - p, - li { - line-height: 2em; - } - li { - list-style-position: outside; - margin-left: 20px; - } - a { - border-bottom: 1px dotted; - text-decoration: none; - &: hover { - transition: ${transitions.hover}; +const helmetData = { + title: 'Nicholas Van Doorn', + meta: [ + { + name: 'description', + content: 'Portfolio for Nicholas Van Doorn' + }, + { + name: 'keywords', + content: 'software, engineer, development, web' } - } - body { - background: ${colours.background}; - } -` + ] +} + const siteData = { siteName: 'Nicholas Van Doorn', navLinks: [ @@ -71,47 +45,81 @@ const siteData = { ], socialEntries: [ { - href: '//github.com/nvandoorn', + href: 'https://github.com/nvandoorn', name: 'GitHub', icon: <FontAwesome icon={faGithub} size="30px" /> }, { - href: '//twitter.com/nickvandoorn', + href: 'https://twitter.com/nickvandoorn', name: 'Twitter', icon: <FontAwesome icon={faTwitter} size="30px" /> }, { - href: '//keybase.io/nvandoorn', + href: 'https://keybase.io/nvandoorn', name: 'Keybase', icon: <FontAwesome icon={faKeybase} size="30px" /> }, { - href: '//open.spotify.com/user/pontonn', + href: 'https://open.spotify.com/user/pontonn', name: 'Spotify', icon: <FontAwesome icon={faSpotify} size="30px" /> } ] } -export default ({ children, height }) => ( - <> - <Global styles={globalStyles} /> - <Helmet - title="Nicholas Van Doorn" - meta={[ - { name: 'description', content: 'Portfolio for Nicholas Van Doorn' }, - { name: 'keywords', content: 'software, engineer, development, web' } - ]} - > - <html lang="en" /> - </Helmet> - <Container height={height}> - <Header - siteName={siteData.siteName} - links={siteData.navLinks} - socialEntries={siteData.socialEntries} - /> - {children} - </Container> - </> -) +const getThemeKeyFromUrl = () => { + const queryObj = parseQuery() + return queryObj && queryObj.themeKey +} + +const initState = () => { + let currentThemeKey = getThemeKeyFromUrl() || 'mainTheme' + return { + theme: themes[currentThemeKey], + currentThemeKey + } +} + +// persist state globally +// (theme should stay +// across page changes) +let lastState = initState() + +export default class Layout extends Component { + state = lastState + + changeTheme = themeKey => { + const theme = themes[themeKey] + const newState = { theme, currentThemeKey: themeKey } + lastState = newState + this.setState(newState) + writeQuery({ themeKey }) + } + + render() { + const { children, height } = this.props + return ( + <BaseLayout + height={height} + theme={this.state.theme} + helmetData={helmetData} + > + <Header + siteName={siteData.siteName} + links={siteData.navLinks} + socialEntries={siteData.socialEntries} + /> + + {children} + <ThemeSwitcher + currentTheme={this.state.currentThemeKey} + themes={[ + { name: '👔', key: 'mainTheme' }, + { name: '📰', key: 'highContrastTheme' } + ]} + onClick={t => this.changeTheme(t)} + /> + </BaseLayout> + ) + } +} |