feat: app level theming

This commit is contained in:
Kyle Gill
2019-05-19 19:28:09 -06:00
parent a67744c31d
commit f3030d8091
11 changed files with 206 additions and 105 deletions

View File

@@ -1,15 +1,21 @@
import React from "react"
import { ThemeProvider } from "emotion-theming"
import Firebase, { FirebaseContext } from "./src/components/firebase"
import theme from "./src/styles/theme"
const selectedTheme =
new Date().getHours() >= 7 && new Date().getHours() <= 21 ? "LIGHT" : "DARK"
import { ThemeProvider as EmotionThemeProvider } from "emotion-theming"
import Firebase, { FirebaseContext } from "components/firebase"
import theme from "styles/theme"
import ThemeTogglerContext, { ThemeToggler } from "components/context/theme"
export const wrapRootElement = ({ element }) => {
return (
<FirebaseContext.Provider value={new Firebase()}>
<ThemeProvider theme={theme[selectedTheme]}>{element}</ThemeProvider>
<ThemeToggler>
<ThemeTogglerContext.Consumer>
{({ themeName }) => (
<EmotionThemeProvider theme={theme[themeName]}>
{element}
</EmotionThemeProvider>
)}
</ThemeTogglerContext.Consumer>
</ThemeToggler>
</FirebaseContext.Provider>
)
}

View File

@@ -2,11 +2,11 @@ import React, { Component } from "react"
import { Router } from "@reach/router"
import { compose } from "recompose"
import styled from "@emotion/styled"
import { ThemeProvider } from "emotion-theming"
import { withTheme } from "emotion-theming"
import { SIZES } from "./styles/constants"
import theme from "./styles/theme"
// import theme from "./styles/theme"
import Navbar from "./components/Navbar"
import Day from "routes/Day"
import Month from "routes/Month"
@@ -19,6 +19,7 @@ import PrivateRoute from "./components/PrivateRoute"
import { OnlineContext } from "./components/context/online"
import { withAuthentication } from "./components/session"
import { withFirebase } from "./components/firebase"
import ThemeTogglerContext from "components/context/theme"
const FullscreenLayout = styled.div`
background-color: ${props => props.theme.colors.bodyBackground};
@@ -36,10 +37,7 @@ const RouteLayout = styled.div`
class App extends Component {
state = {
selectedTheme:
new Date().getHours() >= 7 && new Date().getHours() <= 21
? "LIGHT"
: "DARK",
selectedTheme: this.props.theme.name,
}
componentDidMount() {
@@ -57,28 +55,17 @@ class App extends Component {
})
}
onChangeTheme = () => {
const { selectedTheme } = this.state
const body = document.body
const newTheme = selectedTheme === "LIGHT" ? "DARK" : "LIGHT"
body.style.setProperty(
"background-color",
theme[newTheme].colors.bodyBackground
)
this.setState({ selectedTheme: newTheme })
}
render() {
const { selectedTheme, authUser, online } = this.state
const { authUser: propAuthUser } = this.props
const { authUser, online } = this.state
const { authUser: propAuthUser, theme } = this.props
const authed = !!propAuthUser || !!authUser
const currentTheme = theme[selectedTheme]
return (
<ThemeProvider theme={currentTheme}>
<ThemeTogglerContext.Consumer>
{({ toggle }) => (
<OnlineContext.Provider value={online}>
<FullscreenLayout>
<Navbar toggleTheme={this.onChangeTheme} />
<Navbar toggleTheme={toggle} />
<RouteLayout>
<Router>
<PrivateRoute
@@ -116,12 +103,14 @@ class App extends Component {
</RouteLayout>
</FullscreenLayout>
</OnlineContext.Provider>
</ThemeProvider>
)}
</ThemeTogglerContext.Consumer>
)
}
}
export default compose(
withAuthentication,
withFirebase
withFirebase,
withTheme
)(App)

View File

@@ -13,6 +13,7 @@ import { todayUrl, yearUrl } from "utils/date"
import Logo from "components/Logo"
import Icon from "components/Icon"
import { withAuthentication } from "components/session"
import ThemeTogglerContext from "components/context/theme"
const Header = styled.div`
background-color: ${props => props.theme.colors.headerBackground};
@@ -93,16 +94,24 @@ const Navbar = ({ authUser, theme, toggleTheme }) => (
/>
</React.Fragment>
) : (
<>
<Link to={"/login"} style={{ textDecoration: "none" }}>
<Icon name="ArrowRight" label="Login" size={20} />
</Link>
<Icon
tabindex={0}
onClick={() => toggleTheme()}
onKeyPress={() => toggleTheme()}
name={theme.name === "Dark" ? "Sun" : "Moon"}
/>
</>
)}
</NavIcons>
</Nav>
</Header>
)
const SimpleNav = ({ theme, toggleTheme }) => (
const SimpleNav = ({ authUser, theme }) => (
<Header>
<Nav>
<LogoSection onClick={() => navigate("/")}>
@@ -111,17 +120,34 @@ const SimpleNav = ({ theme, toggleTheme }) => (
<LogoText color={theme.colors.secondary}>JOURNAL</LogoText>
</LogoSection>
<NavIcons>
{/* <Tooltip title="Login"> */}
{authUser ? (
<StyledLink to={"/"}>
<Icon name="Circle" />
</StyledLink>
) : (
<Link to={"/login"} style={{ textDecoration: "none" }}>
<Icon name="ArrowRight" label="Login" size={20} />
</Link>
{/* </Tooltip> */}
)}
<ThemeTogglerContext.Consumer>
{({ toggle }) => (
<Icon
tabindex={0}
onClick={() => toggle()}
onKeyPress={() => toggle()}
name={theme.name === "Dark" ? "Sun" : "Moon"}
/>
)}
</ThemeTogglerContext.Consumer>
</NavIcons>
</Nav>
</Header>
)
const SimpleNavbar = withTheme(SimpleNav)
const SimpleNavbar = compose(
withAuthentication,
withTheme
)(SimpleNav)
export { SimpleNavbar }

View File

@@ -0,0 +1,46 @@
import React from "react"
import theme from "styles/theme"
const ThemeTogglerContext = React.createContext({
themeName: "LIGHT",
toggle: () => {},
})
class ThemeToggler extends React.Component {
state = {
themeName:
new Date().getHours() >= 7 && new Date().getHours() <= 21
? "LIGHT"
: "DARK",
}
toggle = () => {
const { themeName } = this.state
const body = document.body
const newTheme = themeName === "LIGHT" ? "DARK" : "LIGHT"
body.style.setProperty(
"background-color",
theme[newTheme].colors.bodyBackground
)
this.setState({ themeName: newTheme })
}
render() {
const { children } = this.props
const { themeName } = this.state
return (
<ThemeTogglerContext.Provider
value={{
themeName,
toggle: this.toggle,
}}
>
{children}
</ThemeTogglerContext.Provider>
)
}
}
export default ThemeTogglerContext
export { ThemeToggler }

View File

@@ -11,6 +11,18 @@ export const H1 = styled.h1`
color: ${props => props.color};
`
export const SimpleH1 = styled.h1`
color: ${props => props.color};
`
export const SimpleH2 = styled.h1`
color: ${props => props.color};
`
export const Em = styled.em`
color: ${props => props.color};
`
export const Input = styled.input`
color: ${props => props.colors.primary};
background-color: ${props => props.colors.headerBackground};

View File

@@ -30,7 +30,10 @@ const LoginPage = ({ theme }) => (
{firebase => <LoginForm firebase={firebase} />}
</FirebaseContext.Consumer>
<P colors={theme.colors} style={{ fontStyle: "italic" }}>
Don't have an account? <Link to={"/register"}>Sign Up</Link>
Don't have an account?{" "}
<Link style={{ color: theme.colors.primary }} to={"/register"}>
Sign Up
</Link>
</P>
</LoginLayout>
</Layout>
@@ -91,7 +94,7 @@ class LoginFormBase extends Component {
Login
</Button>
</LoginGrid>
{error && <p>{error.message}</p>}
{error && <P colors={theme.colors}>{error.message}</P>}
</form>
)
}

View File

@@ -1,19 +1,22 @@
import React from "react"
import { P } from "components/elements"
import { SimpleH1, SimpleH2, P, Em } from "components/elements"
import Layout from "components/Layout"
import Container from "components/container"
import { SimpleNavbar } from "components/Navbar"
import { withTheme } from "emotion-theming"
const Terms = () => (
const Terms = ({ theme }) => (
<Layout>
<SimpleNavbar />
<Container>
<h1>Privacy Policy</h1>
<em>Last update: April 30, 2019</em>
<SimpleH1 color={theme.colors.primary}>Privacy Policy</SimpleH1>
<Em color={theme.colors.secondary}>Last update: April 30, 2019</Em>{" "}
<P>
Sol Journal supports the following browsers: Chrome (latest), Safari
(latest), Firefox (50+)
</P>
<h2>Rights</h2>
<SimpleH2 color={theme.colors.secondary}>Rights</SimpleH2>
<P>
You don't have to provide your real name when you register to an
account, but you need to use a valid/verifiable email address.
@@ -43,7 +46,7 @@ const Terms = () => (
<br />
Any new features that affect privacy will be strictly opt-in.
</P>
<h2>Responsibilites</h2>
<SimpleH2 color={theme.colors.secondary}>Responsibilites</SimpleH2>
<P>
You will not use the site to store illegal information or data under
United States law (or any law).
@@ -68,7 +71,7 @@ const Terms = () => (
(millions of entries or overloading services with requests) or use it in
an unreasonable manner.
</P>
<h2>Other</h2>
<SimpleH2 color={theme.colors.secondary}>Other</SimpleH2>
<P>
Other important legal stuff Though I want to provide a great service,
there are certain things about the service I cannot promise. For
@@ -88,4 +91,4 @@ const Terms = () => (
</Layout>
)
export default Terms
export default withTheme(Terms)

View File

@@ -29,7 +29,10 @@ const RegisterPage = ({ theme }) => (
{firebase => <RegisterForm firebase={firebase} />}
</FirebaseContext.Consumer>
<P colors={theme.colors} style={{ fontStyle: "italic" }}>
Already have an account? <Link to={"/login"}>Login</Link>
Already have an account?{" "}
<Link style={{ color: theme.colors.primary }} to={"/login"}>
Login
</Link>
</P>
</RegisterLayout>
</Layout>
@@ -133,7 +136,7 @@ class RegisterFormBase extends Component {
</Button>
</RegisterGrid>
{error && <p>{error.message}</p>}
{error && <P colors={theme.colors}>{error.message}</P>}
</form>
)
}

View File

@@ -1,20 +1,23 @@
import React from "react"
import { P } from "components/elements"
import { SimpleH1, SimpleH2, P, Em } from "components/elements"
import Layout from "components/Layout"
import Container from "components/container"
import { SimpleNavbar } from "components/Navbar"
import { withTheme } from "emotion-theming"
const Terms = () => (
const Terms = ({ theme }) => (
<Layout>
<SimpleNavbar />
<Container>
<h1>Terms of Service</h1>
<em>Last update: April 30, 2019</em>
<h2>Scope of Service</h2>
<SimpleH1 color={theme.colors.primary}>Terms of Service</SimpleH1>
<Em color={theme.colors.secondary}>Last update: April 30, 2019</Em>
<SimpleH2 color={theme.colors.secondary}>Scope of Service</SimpleH2>
<P>
Sol Journal supports the following browsers: Chrome (latest), Safari
(latest), Firefox (50+)
</P>
<h2>Rights</h2>
<SimpleH2 color={theme.colors.secondary}>Rights</SimpleH2>
<P>
You don't have to provide your real name when you register to an
account, but you need to use a valid/verifiable email address.
@@ -37,7 +40,7 @@ const Terms = () => (
<br />
Any new features that affect privacy will be strictly opt-in.
</P>
<h2>Responsibilites</h2>
<SimpleH2 color={theme.colors.secondary}>Responsibilites</SimpleH2>
<P>
You will not use the site to store illegal information or data under
United States law (or any law).
@@ -62,7 +65,7 @@ const Terms = () => (
(millions of entries or overloading services with requests) or use it in
an unreasonable manner.
</P>
<h2>Other</h2>
<SimpleH2 color={theme.colors.secondary}>Other</SimpleH2>
<P>
Other important legal stuff Though I want to provide a great service,
there are certain things about the service I cannot promise. For
@@ -82,4 +85,4 @@ const Terms = () => (
</Layout>
)
export default Terms
export default withTheme(Terms)

View File

@@ -120,7 +120,7 @@ class Start extends Component {
}
`}
render={data => {
return theme.name === "Light" ? (
return theme.name === "LIGHT" ? (
<Img
style={{
maxWidth: 320,
@@ -131,7 +131,15 @@ class Start extends Component {
fluid={data.landingGraphicLight.childImageSharp.fluid}
/>
) : (
<Img fluid={data.LandingGraphicDark.childImageSharp.fluid} />
<Img
style={{
maxWidth: 320,
width: "100%",
maxHeight: 350,
height: "100%",
}}
fluid={data.landingGraphicDark.childImageSharp.fluid}
/>
)
}}
/>

View File

@@ -1,6 +1,6 @@
const theme = {
LIGHT: {
name: "Light",
name: "LIGHT",
colors: {
logo: "#344157",
primary: "#2E3136",
@@ -11,10 +11,11 @@ const theme = {
bodyBackground: "#FFF",
inputBackground: "#FAFBFC",
hover: "hsla(233, 5%, 31%, 0.12)",
button: "#f2f3f5",
},
},
DARK: {
name: "Dark",
name: "DARK",
colors: {
logo: "#EAEAEA",
primary: "#F3F6F8",
@@ -25,6 +26,7 @@ const theme = {
bodyBackground: "#262B34",
inputBackground: "#272f3d",
hover: "hsla(233, 100%, 96%, 0.12)",
button: "#464d5d",
},
},
}