Last active
November 16, 2020 07:10
-
-
Save mkhoussid/86bf8553eb265a692ce07a34e90c7006 to your computer and use it in GitHub Desktop.
ThemeProvider with useContext
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////////////// | |
// https://codesandbox.io/s/inspiring-thunder-dzyi8?file=/src/index.tsx:0-274 | |
///////////////////////////////////////////////////////////////////////////// | |
import * as React from "react"; | |
import { Button } from "components/ui"; | |
import { ThemeContext } from "contexts/ThemeContext"; | |
import { themes } from "utils/theme"; | |
import { Container, Label, RadioInputStyled } from "components/styled/App"; | |
import { getButtonText } from "utils"; | |
const defaultButtonText = "Switch to Theme Dark"; | |
export default function App() { | |
const { theme, setTheme } = React.useContext(ThemeContext); | |
const [buttonText, setButtonText] = React.useState(defaultButtonText); | |
const [currentThemeIndex, setCurrentThemeIndex] = React.useState(0); | |
const [disabled, toggleDisabled] = React.useReducer( | |
(disabled) => !disabled, | |
false | |
); | |
React.useEffect(() => { | |
setTheme(themes[currentThemeIndex]); | |
}, []); | |
const handleClick = React.useCallback(() => { | |
const requestedThemeIndex = | |
(themes[currentThemeIndex + 1] && currentThemeIndex + 1) ?? 0; | |
setButtonText(getButtonText(requestedThemeIndex)); | |
setCurrentThemeIndex(requestedThemeIndex); | |
setTheme(themes[requestedThemeIndex]); | |
}, [currentThemeIndex]); | |
return ( | |
<Container background={theme.palette.layout.main}> | |
<Label color={theme.palette.button.primary}> | |
<RadioInputStyled | |
onClick={toggleDisabled} | |
checked={disabled} | |
type="radio" | |
name="isDisabled" | |
/> | |
Toggle disabled | |
</Label> | |
<Button | |
onClick={handleClick} | |
buttonPalette={theme.palette.button} | |
disabled={disabled} | |
> | |
{buttonText} | |
</Button> | |
</Container> | |
); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from "react"; | |
import { render } from "react-dom"; | |
import ThemeProvider from "contexts/ThemeContext"; | |
import App from "./App"; | |
const rootElement = document.getElementById("root"); | |
render( | |
<ThemeProvider> | |
<App /> | |
</ThemeProvider>, | |
rootElement | |
); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export type TButtonPalette = { | |
primary: string; | |
disabled: string; | |
hover: string; | |
active: string; | |
text: string; | |
}; | |
export type TLayoutPalette = { | |
main: string; | |
}; | |
export type TTheme = { | |
palette: { | |
button: TButtonPalette; | |
layout: TLayoutPalette; | |
}; | |
}; | |
export const themeLight: TTheme = { | |
palette: { | |
button: { | |
primary: "rgba(0, 0, 0, 1)", | |
disabled: "rgba(191, 197, 202, 1)", | |
hover: "rgba(0, 0, 0, 0.85)", | |
active: "rgba(0, 0, 0, 0.6)", | |
text: "rgba(255, 255, 255, 1)" | |
}, | |
layout: { | |
main: "rgba(255, 255, 255, 1)" | |
} | |
} | |
}; | |
export const themeDark: TTheme = { | |
palette: { | |
button: { | |
primary: "rgba(255, 255, 255, 1)", | |
disabled: "rgba(191, 197, 202, 1)", | |
hover: "rgba(255, 255, 255, 0.85)", | |
active: "rgba(255, 255, 255, 0.5)", | |
text: "rgba(0, 0, 0, 1)" | |
}, | |
layout: { | |
main: "rgba(0, 0, 0, 1)" | |
} | |
} | |
}; | |
export const themeBlue: TTheme = { | |
palette: { | |
button: { | |
primary: "rgba(228, 228, 228, 1)", | |
disabled: "rgba(191, 197, 202, 1)", | |
hover: "rgba(228, 228, 228, 0.8)", | |
active: "rgba(194, 194, 194, 1)", | |
text: "rgba(0, 0, 0, 0.75)" | |
}, | |
layout: { | |
main: "rgba(73, 99, 230, 1)" | |
} | |
} | |
}; | |
export enum EThemes { | |
themeLight, | |
themeDark, | |
themeBlue | |
} | |
export const themes = [themeLight, themeDark, themeBlue]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import { themeLight, themeDark, themeEquilibrium, TTheme } from "utils/theme"; | |
type TThemeProviderContext = { | |
theme: TTheme; | |
setTheme: (theme: TTheme) => void; | |
}; | |
export const ThemeContext = React.createContext<TThemeProviderContext>( | |
{} as TThemeProviderContext | |
); | |
type TThemeProvider = { | |
children: React.ReactNode; | |
}; | |
const ThemeProvider = ({ children }: TThemeProvider) => { | |
const [theme, setTheme] = React.useState(themeLight); | |
return ( | |
<ThemeContext.Provider | |
value={{ | |
theme, | |
setTheme | |
}} | |
> | |
{children} | |
</ThemeContext.Provider> | |
); | |
}; | |
export default ThemeProvider; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment