Skip to content

Instantly share code, notes, and snippets.

@phunkren
Last active October 29, 2020 22:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save phunkren/e16771da3e19f5351aa4d038241c7fd2 to your computer and use it in GitHub Desktop.
Save phunkren/e16771da3e19f5351aa4d038241c7fd2 to your computer and use it in GitHub Desktop.
My custom Theme provider for ajames.dev
import React from 'react';
import styled from 'styled-components';
const Container = styled.div(({ theme }) => css`
background-color: ${theme.background};
background-color: ${theme.copyColor};
border-color: ${theme.borderColor};
`);
export const Component = ({ children, ...props }) => {
return (
<Container {...props}>
{ children }
</Container>
);
};
import React, { useState, useEffect, useContext, createContext } from 'react';
import styled, { ThemeProvider } from 'styled-components';
import { CustomCheckboxContainer, CustomCheckboxInput } from '@reach/checkbox';
import '@reach/checkbox/styles.css';
import { THEMES, DEFAULT_THEME } from '../styles/themes';
import { LightIcon } from './icons/LightIcon';
export const ThemeContext = createContext(null);
export const Theme = props => {
const localTheme = retrieve();
const [theme, setTheme] = useState(localTheme);
useEffect(theme ? persist : init, [theme]);
function validate(t) {
return Object.keys(THEMES).includes(t);
}
function update(t) {
validate(t) && setTheme(t);
}
function retrieve() {
return window.localStorage.getItem('theme');
}
function persist() {
window.localStorage.setItem('theme', theme);
}
function init() {
setTheme(validate(localTheme) ? localTheme : DEFAULT_THEME);
}
return validate(theme) ? (
<ThemeContext.Provider value={{ theme, update }}>
<ThemeProvider theme={THEMES[theme]} {...props} />
</ThemeContext.Provider>
) : null;
};
export const ThemeToggle = props => {
const { theme, update } = useContext(ThemeContext) || {};
const checked = theme === 'light';
function handleChange(e) {
update(e.target.checked ? 'light' : 'dark');
}
return (
<CustomCheckboxContainer
checked={checked}
onChange={handleChange}
{...props}
>
<label htmlFor="theme-toggle">
<LightIcon on={!checked} aria-label="Theme toggle" />
<CustomCheckboxInput
id="theme-toggle"
checked={checked}
onChange={handleChange}
{...props}
/>
</label>
</CustomCheckboxContainer>
);
};
import { mix } from 'polished';
const LIGHT_THEME = {
background: 'var(--color-white)',
headerColor: 'var(--color-charcoal)',
copyColor: 'var(--color-black)',
linkColor: 'var(--color-blue-700)',
highlightColor: 'var(--color-blue-600)',
auxiliaryColor: 'var(--color-gray-700)',
borderColor: 'var(--color-charcoal)',
overlay5: `${mix(0.95, 'rgb(255,255,255)', 'rgb(0, 0, 0)')}`,
overlay10: `${mix(0.9, 'rgb(255,255,255)', 'rgba(,0,0,0)')}`,
};
const DARK_THEME = {
background: 'var(--color-black)',
headerColor: 'var(--color-gray-200)',
copyColor: 'var(--color-white)',
linkColor: 'var(--color-blue-400)',
highlightColor: 'var(--color-orange-400)',
auxiliaryColor: 'var(--color-gray-400)',
borderColor: 'var(--color-charcoal)',
overlay5: `${mix(0.95, 'rgb(0,0,0)', 'rgb(255, 255, 255)')}`,
overlay10: `${mix(0.9, 'rgb(0,0,0)', 'rgb(255,255,255)')}`,
};
export const THEMES = {
light: LIGHT_THEME,
dark: DARK_THEME,
};
export const DEFAULT_THEME = 'dark';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment