Skip to content

Instantly share code, notes, and snippets.

@mkhoussid
Last active November 16, 2020 07:10
Show Gist options
  • Save mkhoussid/86bf8553eb265a692ce07a34e90c7006 to your computer and use it in GitHub Desktop.
Save mkhoussid/86bf8553eb265a692ce07a34e90c7006 to your computer and use it in GitHub Desktop.
ThemeProvider with useContext
/////////////////////////////////////////////////////////////////////////////
// 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>
);
}
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
);
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];
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