Create a blank react typescript application, set it up with MUI.
Switch theme mode between Night and Dark (default value taken from user system, also reacts to user system theme changes).
Create 3 different Themes (red, blue and green) other than default MUI theme. We will use external tool to help us create colour palette. Each theme has dark and light colour palette.
Extend default theme with our own custom variables, so we can do <Button color=’google’ /> and button knows what background and text colour to use.
Shuffle between these theme modes.
Common ways to use the theme in our app.
Checkout common mistakes to avoid that waste dev time on forums and stack.
Create a blank React Typescript application
Create a new react typescript app with create-react-app by running
NOTE: this will create an app named awesome as given in the command… you can go ahead and give it whatever name you like for ex npx create-react-app spiderman --template typescript will create an app named spiderman (reference: https://create-react-app.dev/docs/adding-typescript/ )
Great, now CD into the newly created app. (use whatever app name you gave instead of my-app)
cd ./awesome
Now open the repo in an IDE, for example if you’re using VSCode and you’ve setup it’s command in your PATH, run
code .
(notice the full-stop that tells VSCode to open project in current directory, i.e. the directory we CDed into)
your project should look similar to this
Go ahead and enter the following command in terminal to start the project and have our react app run in live reload mode in the browser
npm run start
or yarn
yarn start
If all worked properly, you should be seeing a Pop culture atom symbol of React!
next, we are going to install MUI packages that uses ‘styled’ as its theming engine.
Done, that should be all the packages we need to build our theming demo.
next, we are going to create a theme provider (sort of a store that will have our theme to use anywhere in our app and provide us functions to change theme from anywhere in our app).
Creating the Context
Now we are going to create a Context Provider component, which will provide our various themes (red blue default green - light/dark) to our entire app. This works on react context api under the hood. More on react context api: https://reactjs.org/docs/context.html
As the react docs say: Context provides a way to pass data through the component tree without having to pass props down manually at every level.
So now once we provide our theme at the top most level, we can directly use it anywhere in our app. You’ll see more of its working later in this tutorial.
Create a file called MyThemeProvider.tsx in the following path: src/theme/MyThemeProvider.tsx
Add the following code to it:
1import React, { useEffect } from "react";
2import CssBaseline from "@mui/material/CssBaseline";
3import GlobalStyles from "@mui/material/GlobalStyles";
4import { ThemeProvider, createTheme, ThemeOptions } from "@mui/material/styles";
5import useMediaQuery from "@mui/material/useMediaQuery";
13export default function MyThemeProvider(props: MyThemeProviderProps) {
14 return (
15 <ThemeContext.Provider value={{}}> {/* We **WILL** provide functions to change theme here */}
16 <ThemeProvider theme={{}}> {/* We **WILL** provide theme here */}
17 <GlobalStyles styles={{}} />
18 <CssBaseline enableColorScheme />
19 {props.children}
20 </ThemeProvider>
21 </ThemeContext.Provider>
22 );
23}
This is our boilerplate for our Theme Context Provider
We will supply our theme (that we will use everywhere) into this
We will supply our functions to change theme into this
typical flow: MUI renders components with default theme → User changes theme → new theme is sent to MUI → MUI re renders it’s components with new theme
ℹ️ note: do not miss GlobalStyles and CssBaseLine components.
Sure we will use our theme to provide colours to buttons and various components but we can’t change our App’s background and font color dynamically (technically that can be done but this is the MUI way). CssBaseline provides this functionality to manage background and text color of our app automatically based on what theme we provide it. (ex body html tag)
GlobalStyles just retains the page’s default css that gets reset/removed by CssBaseline. (ex body has a margin of 8px by default .. or something)
Don’t worry if you are not understanding this, once we are done building our demo, you can try remove those components to see what difference does it make to our app.
note: we still haven’t provided
theme
functions to change theme
to our context above, so it’s essentially useless at the moment. first we will connect this to our app and then we will add functionality to it so we don’t have to deal with connecting stuff later.
Now be a good human and head over to src/index.tsx
It must look similar to this as of now:
1import React from 'react';
2import ReactDOM from 'react-dom/client';
3import './index.css';
4import App from './App';
5import reportWebVitals from './reportWebVitals';
6
7const root = ReactDOM.createRoot(
8 document.getElementById('root') as HTMLElement
9);
10root.render(
11 <React.StrictMode>
12 <App />
13 </React.StrictMode>
14);
15
16// If you want to start measuring performance in your app, pass a function
17// to log results (for example: reportWebVitals(console.log))
18// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
19reportWebVitals();
1import React from 'react';
2import ReactDOM from 'react-dom/client';
3import './index.css';
4import App from './App';
5import reportWebVitals from './reportWebVitals';
6
7const root = ReactDOM.createRoot(
8 document.getElementById('root') as HTMLElement
9);
10root.render(
11 <React.StrictMode>
12 <App />
13 </React.StrictMode>
14);
15
16// If you want to start measuring performance in your app, pass a function
17// to log results (for example: reportWebVitals(console.log))
18// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
19reportWebVitals();
We are going to provide our Context store here by wrapping <App /> with ThemeProvider that we exportedearlier and StyledEngineProvider from @mui/material/styles package
Below is the updated code in this file src/index.tsx, follow along the comments to know what is done:
1import React from "react";
2import ReactDOM from "react-dom/client";
3import "./index.css";
4import App from "./App";
5import reportWebVitals from "./reportWebVitals";
6// 1. Import StyledEngineProvider from MUI
7import { StyledEngineProvider } from "@mui/material/styles";
8// 2. Import ThemeProvider that we just created
9import MyThemeProvider from "./theme/MyThemeProvider";
10
11const root = ReactDOM.createRoot(
12 document.getElementById("root") as HTMLElement
13);
14
15root.render(
16 <React.StrictMode>
17 {/* 4. Wrap Theme provider with MUI Styled engine */}
18 <StyledEngineProvider injectFirst>
19 {/* 5. Wrap your app with the Theme Provider */}
20 <MyThemeProvider>
21 <App />
22 </MyThemeProvider>
23 </StyledEngineProvider>
24 </React.StrictMode>
25);
26
27// If you want to start measuring performance in your app, pass a function
28// to log results (for example: reportWebVitals(console.log))
29// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
30reportWebVitals();
1import React from "react";
2import ReactDOM from "react-dom/client";
3import "./index.css";
4import App from "./App";
5import reportWebVitals from "./reportWebVitals";
6// 1. Import StyledEngineProvider from MUI
7import { StyledEngineProvider } from "@mui/material/styles";
8// 2. Import ThemeProvider that we just created
9import MyThemeProvider from "./theme/MyThemeProvider";
10
11const root = ReactDOM.createRoot(
12 document.getElementById("root") as HTMLElement
13);
14
15root.render(
16 <React.StrictMode>
17 {/* 4. Wrap Theme provider with MUI Styled engine */}
18 <StyledEngineProvider injectFirst>
19 {/* 5. Wrap your app with the Theme Provider */}
20 <MyThemeProvider>
21 <App />
22 </MyThemeProvider>
23 </StyledEngineProvider>
24 </React.StrictMode>
25);
26
27// If you want to start measuring performance in your app, pass a function
28// to log results (for example: reportWebVitals(console.log))
29// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
30reportWebVitals();
Now that we have connected out Context provider, let’s add in our functions to change theme and also the theme itself that’s to be used by our components
Providing theme and functions to change theme
head over to src/theme/ThemeProvider.tsx
we are going to have two react states: theme (0=red,1=blue,2=green,3=default) and mode (light, dark)
Below is the updated code in this file, follow along the comments to know what is done:
1import CssBaseline from "@mui/material/CssBaseline";
2import GlobalStyles from "@mui/material/GlobalStyles";
3import { ThemeProvider, createTheme, ThemeOptions } from "@mui/material/styles";
4import useMediaQuery from "@mui/material/useMediaQuery";
5import React from "react";
6import { useEffect } from "react";
7
8// 1. create context with default values. This context will be used in places where we need to
9// change themes and modes. we will update the context vaules below to actual functions
68 7. finally, provide the colorMode constant to our theme context provider
69 later in the components where we need to call the toggleColorMode and shuffleColorTheme methods
70 we will do something like colorMode.toggleColorMode() and toggleColorMode.shuffleColorTheme()
71 */}
72 <ThemeContext.Provider value={colorMode}>
73 {/*
74 8. we still haven't provided any theme object to material ui's theme provider. this part is still pending and
75 we will do this after we have craeted various light and dark themes, combined them into an object and export
76 then import it in this file, use current value of mode and theme to pick the right theme object and supply
77 to the ThemeProvider like <ThemeProvider theme={theme}>
78 */}
79 <ThemeProvider theme={{}}>
80 <GlobalStyles styles={{}} />
81 <CssBaseline enableColorScheme />
82 {props.children}
83 </ThemeProvider>
84 </ThemeContext.Provider>
85 );
86}
Once this is done, now all that’s left is
create theme objects and export them in a format so we can use theme and mode values to pick the proper theme
add logic of importing theme and supplying it to MUI’s ThemeProvider
Themes
How material UI’s theming works is, there is a theme palette object that contains colours for everything. App background, text that’ll appear on app background, primary colours, text colours to use when background is of primary colours, basically everything is predetermined. From fonts to spacings to colours to everything.
Head over to https://mui.com/material-ui/customization/default-theme/ to checkout the default theme palette object and it’s values for light and dark mode. This is the default set of values you get, for example when you add color={’primary’} props to a MUI Button, this theme object tells what button background and its text is going to look like. Expand the palette key of the entire theme object. That’s what we will be tweaking to create a set of colours.
Now checkout theme.palette.primary key, whose value is an object with four keys namely main, light, dark, contrastText.
when you set color={’primary’} to your button, it applies the main colour to its background and contrastText to its foreground like text color. You can also tell MUI to use light or dark variants of your main colour.
This means if we need to create additional themes, lets say a reddish theme named Dracula… we will have to decide most of these default values (if not all) for light as well as dark modes (the above screenshot is of light mode theme palette object)
How do we decide what values to put for our Dracula theme and ensure we don’t mess up accessibility?
One fun way (not the only) that I’ll show you is as follows:
now from the left most panel, click on Primary, select any colour you like. This will generate an entire palette to use for you on the right side.
Like so:
What does this mean? How will it help us colour our components and pages?
imagine a homepage,
It’ll take background colour of background and font colour of onBackground (from the above image)
A card on homepage will take background colour of primaryContainer and font colour of onPrimaryContainer
A button on that card will take background colour of lets say primary and text on button will take font colour of onPrimary
all of this is for light theme, for dark there is another set of colours.
now we just need to create a theme out of these values, and tell material UI when to use what.
don’t worry if things don’t make much sense, follow along:
create a file called blue.ts in src/theme/presets/blue.ts
add the following code in it and follow along the comments to know what’s done: (If you’re seeing typescript errors, don’t worry we shall get rid of them soon)
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5// 1. we defined a new theme object which has two keys, light and dark.
6// light and dark will store palette values in a way MUI understands.
7// these palette value are picked from the obove mentioned website
8// what colour to put where? keep reading...
9export const theme = {
10 dark: {
11 palette: {
12 mode: "dark",
13 // this method augmentColor creates a MUI colour object, with other values automatically like light and dark
14 // as a colour object has main, contrastText, light and dark keys. but we need not provide light and dark keys.
15 primary: palette.augmentColor({
16 color: {
17 // pick the primary colour OF DARK and paste it here
18 main: "#cdbeff",
19 // pick the onPrimary colour OF DARK and paste it here
20 contrastText: "#32009a",
21 },
22 }),
23 secondary: palette.augmentColor({
24 color: {
25 // pick the secondary colour OF DARK and paste it here
26 main: "#cac3dc",
27 // pick the onSecondary colour OF DARK and paste it here
28 contrastText: "#322e41",
29 },
30 }),
31 text: {
32 // pick the onBackground colour OF DARK and paste it here
33 primary: "#e6e1e6",
34 // pick the onSurface colour OF DARK and paste it here
35 secondary: "#e6e1e6",
36 },
37 background: {
38 // pick the background colour OF DARK and paste it here
39 default: "#1c1b1e",
40 // pick the surface colour and OF DARK paste it here
41 paper: "#1c1b1e",
42 },
43 error: palette.augmentColor({
44 color: {
45 // pick the error colour OF DARK and paste it here
46 main: "#ffb4a9",
47 // pick the onError colour OF DARK and paste it here
48 contrastText: "#680003",
49 },
50 }),
51 success: palette.augmentColor({
52 color: {
53 // where did this come from? there is no succeess colour mentioned in thatpalette generator, but you can go ahead
54 // and add custom colours (on bottom left side of the material-theme-builder page and it'll generate palette
55 // for success for you on the right side. from there just pick success OF DARK and onSuccess OF DARK and paste here
56 main: "#79dd72",
57 contrastText: "#003a03",
58 },
59 }),
60 info: palette.augmentColor({
61 color: {
62 // same as above
63 main: "#99cbff",
64 contrastText: "#003257",
65 },
66 }),
67 warning: palette.augmentColor({
68 color: {
69 // same as above
70 main: "#cace09",
71 contrastText: "#313300",
72 },
73 }),
74 // I put the outline colour here
75 divider: "#938f99",
76 // important: these are custom variables
77 // suppose instead of doing <Button colour={'primary'} /> you want to do something like <Button colour={'upvote'} />
78 // for an upvote button? here I am creating custom variabels and supplying colours that I want based on my product design
79 upvote: palette.augmentColor({
80 color: {
81 main: "#cdbeff",
82 contrastText: "#32009a",
83 },
84 }),
85 // same as above
86 downvote: palette.augmentColor({
87 color: {
88 main: "#ffb4a9",
89 contrastText: "#680003",
90 },
91 })
92 containerPrimary: palette.augmentColor({
93 color: {
94 // pick the primary Conatiner colour OF DARK and paste it here
95 main: "#4b24ba",
96 // pick the On primary Conatiner colour OF DARK and paste it here
97 contrastText: "#e8deff",
98 },
99 }),
100 containerSecondary: palette.augmentColor({
101 color: {
102 // pick the secondary Conatiner colour OF DARK and paste it here
103 main: "#494458",
104 // pick the On secondary Conatiner colour OF DARK and paste it here
105 contrastText: "#e7dff8",
106 },
107 }),
108 },
109 },
110// REPEAT FOR LIGHT. instead of picking colours from dark palette, pick colours from the light one and repeat as above
111 light: {
112 palette: {
113 mode: "light",
114 primary: palette.augmentColor({
115 color: {
116 main: "#6342d2",
117 contrastText: "#ffffff",
118 },
119 }),
120 secondary: palette.augmentColor({
121 color: {
122 main: "#605b71",
123 contrastText: "#ffffff",
124 },
125 }),
126 text: {
127 primary: "#1c1b1e",
128 secondary: "#1c1b1e",
129 },
130 background: {
131 default: "#fffbff",
132 paper: "#fffbff",
133 },
134 error: palette.augmentColor({
135 color: {
136 main: "#ba1b1b",
137 contrastText: "#ffffff",
138 },
139 }),
140 success: palette.augmentColor({
141 color: {
142 main: "#006e10",
143 contrastText: "#ffffff",
144 },
145 }),
146 info: palette.augmentColor({
147 color: {
148 main: "#0062a2",
149 contrastText: "#ffffff",
150 },
151 }),
152 warning: palette.augmentColor({
153 color: {
154 main: "#606200",
155 contrastText: "#313300",
156 },
157 }),
158 divider: "#79757f",
159 upvote: palette.augmentColor({
160 color: {
161 main: "#6342d2",
162 contrastText: "#ffffff",
163 },
164 }),
165 downvote: palette.augmentColor({
166 color: {
167 main: "#ba1b1b",
168 contrastText: "#ffffff",
169 },
170 }),
171 containerPrimary: palette.augmentColor({
172 color: {
173 main: "#e8deff",
174 contrastText: "#1c0062",
175 },
176 }),
177 containerSecondary: palette.augmentColor({
178 color: {
179 main: "#e7dff8",
180 contrastText: "#1d192b",
181 },
182 }),
183 },
184 },
185};
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5// 1. we defined a new theme object which has two keys, light and dark.
6// light and dark will store palette values in a way MUI understands.
7// these palette value are picked from the obove mentioned website
8// what colour to put where? keep reading...
9export const theme = {
10 dark: {
11 palette: {
12 mode: "dark",
13 // this method augmentColor creates a MUI colour object, with other values automatically like light and dark
14 // as a colour object has main, contrastText, light and dark keys. but we need not provide light and dark keys.
15 primary: palette.augmentColor({
16 color: {
17 // pick the primary colour OF DARK and paste it here
18 main: "#cdbeff",
19 // pick the onPrimary colour OF DARK and paste it here
20 contrastText: "#32009a",
21 },
22 }),
23 secondary: palette.augmentColor({
24 color: {
25 // pick the secondary colour OF DARK and paste it here
26 main: "#cac3dc",
27 // pick the onSecondary colour OF DARK and paste it here
28 contrastText: "#322e41",
29 },
30 }),
31 text: {
32 // pick the onBackground colour OF DARK and paste it here
33 primary: "#e6e1e6",
34 // pick the onSurface colour OF DARK and paste it here
35 secondary: "#e6e1e6",
36 },
37 background: {
38 // pick the background colour OF DARK and paste it here
39 default: "#1c1b1e",
40 // pick the surface colour and OF DARK paste it here
41 paper: "#1c1b1e",
42 },
43 error: palette.augmentColor({
44 color: {
45 // pick the error colour OF DARK and paste it here
46 main: "#ffb4a9",
47 // pick the onError colour OF DARK and paste it here
48 contrastText: "#680003",
49 },
50 }),
51 success: palette.augmentColor({
52 color: {
53 // where did this come from? there is no succeess colour mentioned in thatpalette generator, but you can go ahead
54 // and add custom colours (on bottom left side of the material-theme-builder page and it'll generate palette
55 // for success for you on the right side. from there just pick success OF DARK and onSuccess OF DARK and paste here
56 main: "#79dd72",
57 contrastText: "#003a03",
58 },
59 }),
60 info: palette.augmentColor({
61 color: {
62 // same as above
63 main: "#99cbff",
64 contrastText: "#003257",
65 },
66 }),
67 warning: palette.augmentColor({
68 color: {
69 // same as above
70 main: "#cace09",
71 contrastText: "#313300",
72 },
73 }),
74 // I put the outline colour here
75 divider: "#938f99",
76 // important: these are custom variables
77 // suppose instead of doing <Button colour={'primary'} /> you want to do something like <Button colour={'upvote'} />
78 // for an upvote button? here I am creating custom variabels and supplying colours that I want based on my product design
79 upvote: palette.augmentColor({
80 color: {
81 main: "#cdbeff",
82 contrastText: "#32009a",
83 },
84 }),
85 // same as above
86 downvote: palette.augmentColor({
87 color: {
88 main: "#ffb4a9",
89 contrastText: "#680003",
90 },
91 })
92 containerPrimary: palette.augmentColor({
93 color: {
94 // pick the primary Conatiner colour OF DARK and paste it here
95 main: "#4b24ba",
96 // pick the On primary Conatiner colour OF DARK and paste it here
97 contrastText: "#e8deff",
98 },
99 }),
100 containerSecondary: palette.augmentColor({
101 color: {
102 // pick the secondary Conatiner colour OF DARK and paste it here
103 main: "#494458",
104 // pick the On secondary Conatiner colour OF DARK and paste it here
105 contrastText: "#e7dff8",
106 },
107 }),
108 },
109 },
110// REPEAT FOR LIGHT. instead of picking colours from dark palette, pick colours from the light one and repeat as above
111 light: {
112 palette: {
113 mode: "light",
114 primary: palette.augmentColor({
115 color: {
116 main: "#6342d2",
117 contrastText: "#ffffff",
118 },
119 }),
120 secondary: palette.augmentColor({
121 color: {
122 main: "#605b71",
123 contrastText: "#ffffff",
124 },
125 }),
126 text: {
127 primary: "#1c1b1e",
128 secondary: "#1c1b1e",
129 },
130 background: {
131 default: "#fffbff",
132 paper: "#fffbff",
133 },
134 error: palette.augmentColor({
135 color: {
136 main: "#ba1b1b",
137 contrastText: "#ffffff",
138 },
139 }),
140 success: palette.augmentColor({
141 color: {
142 main: "#006e10",
143 contrastText: "#ffffff",
144 },
145 }),
146 info: palette.augmentColor({
147 color: {
148 main: "#0062a2",
149 contrastText: "#ffffff",
150 },
151 }),
152 warning: palette.augmentColor({
153 color: {
154 main: "#606200",
155 contrastText: "#313300",
156 },
157 }),
158 divider: "#79757f",
159 upvote: palette.augmentColor({
160 color: {
161 main: "#6342d2",
162 contrastText: "#ffffff",
163 },
164 }),
165 downvote: palette.augmentColor({
166 color: {
167 main: "#ba1b1b",
168 contrastText: "#ffffff",
169 },
170 }),
171 containerPrimary: palette.augmentColor({
172 color: {
173 main: "#e8deff",
174 contrastText: "#1c0062",
175 },
176 }),
177 containerSecondary: palette.augmentColor({
178 color: {
179 main: "#e7dff8",
180 contrastText: "#1d192b",
181 },
182 }),
183 },
184 },
185};
Once this is done, I want you to create 3 more similar files namely red.ts, green.ts, default,ts in the same directory as blue.ts
I’m pasting theme presets for red green and default below, just paste them as it is in your files.
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5export const theme = {
6 dark: {
7 palette: {
8 mode: "dark",
9 primary: palette.augmentColor({
10 color: {
11 main: "#ffb3b0",
12 contrastText: "#68000c",
13 },
14 }),
15 secondary: palette.augmentColor({
16 color: {
17 main: "#4fd8eb",
18 contrastText: "#00363d",
19 },
20 }),
21 text: {
22 primary: "#E6E1E5",
23 secondary: "#E6E1E5",
24 },
25 background: {
26 default: "#1C1B1F",
27 paper: "#1C1B1F",
28 },
29 error: palette.augmentColor({
30 color: {
31 main: "#F2B8B5",
32 contrastText: "#601410",
33 },
34 }),
35 success: palette.augmentColor({
36 color: {
37 main: "#79dd72",
38 contrastText: "#003a03",
39 },
40 }),
41 info: palette.augmentColor({
42 color: {
43 main: "#99cbff",
44 contrastText: "#003257",
45 },
46 }),
47 warning: palette.augmentColor({
48 color: {
49 main: "#cace09",
50 contrastText: "#313300",
51 },
52 }),
53 divider: "#938F99",
54 upvote: palette.augmentColor({
55 color: {
56 main: "#bd0b25",
57 contrastText: "#68000c",
58 },
59 }),
60 downvote: palette.augmentColor({
61 color: {
62 main: "#4fd8eb",
63 contrastText: "#00363d",
64 },
65 }),
66 containerPrimary: palette.augmentColor({
67 color: {
68 main: "#920016",
69 contrastText: "#ffdad6",
70 },
71 }),
72 containerSecondary: palette.augmentColor({
73 color: {
74 main: "#5c3f3d",
75 contrastText: "#ffdad8",
76 },
77 }),
78 },
79 },
80 light: {
81 palette: {
82 mode: "light",
83 primary: palette.augmentColor({
84 color: {
85 main: "#bd0b25",
86 contrastText: "#ffffff",
87 },
88 }),
89 secondary: palette.augmentColor({
90 color: {
91 main: "#006874",
92 contrastText: "#ffffff",
93 },
94 }),
95 text: {
96 primary: "#1C1B1F",
97 secondary: "#1C1B1F",
98 },
99 background: {
100 default: "#FFFBFE",
101 paper: "#fffbff",
102 },
103 error: palette.augmentColor({
104 color: {
105 main: "#B3261E",
106 contrastText: "#FFFFFF",
107 },
108 }),
109 success: palette.augmentColor({
110 color: {
111 main: "#006e10",
112 contrastText: "#ffffff",
113 },
114 }),
115 info: palette.augmentColor({
116 color: {
117 main: "#0062a2",
118 contrastText: "#ffffff",
119 },
120 }),
121 warning: palette.augmentColor({
122 color: {
123 main: "#606200",
124 contrastText: "#313300",
125 },
126 }),
127 divider: "#79747E",
128 upvote: palette.augmentColor({
129 color: {
130 main: "#bd0b25",
131 contrastText: "#ffffff",
132 },
133 }),
134 downvote: palette.augmentColor({
135 color: {
136 main: "#006874",
137 contrastText: "#ffffff",
138 },
139 }),
140 containerPrimary: palette.augmentColor({
141 color: {
142 main: "#ffdad6",
143 contrastText: "#410005",
144 },
145 }),
146 containerSecondary: palette.augmentColor({
147 color: {
148 main: "#ffdad8",
149 contrastText: "#2d1514",
150 },
151 }),
152 },
153 },
154};
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5export const theme = {
6 dark: {
7 palette: {
8 mode: "dark",
9 primary: palette.augmentColor({
10 color: {
11 main: "#ffb3b0",
12 contrastText: "#68000c",
13 },
14 }),
15 secondary: palette.augmentColor({
16 color: {
17 main: "#4fd8eb",
18 contrastText: "#00363d",
19 },
20 }),
21 text: {
22 primary: "#E6E1E5",
23 secondary: "#E6E1E5",
24 },
25 background: {
26 default: "#1C1B1F",
27 paper: "#1C1B1F",
28 },
29 error: palette.augmentColor({
30 color: {
31 main: "#F2B8B5",
32 contrastText: "#601410",
33 },
34 }),
35 success: palette.augmentColor({
36 color: {
37 main: "#79dd72",
38 contrastText: "#003a03",
39 },
40 }),
41 info: palette.augmentColor({
42 color: {
43 main: "#99cbff",
44 contrastText: "#003257",
45 },
46 }),
47 warning: palette.augmentColor({
48 color: {
49 main: "#cace09",
50 contrastText: "#313300",
51 },
52 }),
53 divider: "#938F99",
54 upvote: palette.augmentColor({
55 color: {
56 main: "#bd0b25",
57 contrastText: "#68000c",
58 },
59 }),
60 downvote: palette.augmentColor({
61 color: {
62 main: "#4fd8eb",
63 contrastText: "#00363d",
64 },
65 }),
66 containerPrimary: palette.augmentColor({
67 color: {
68 main: "#920016",
69 contrastText: "#ffdad6",
70 },
71 }),
72 containerSecondary: palette.augmentColor({
73 color: {
74 main: "#5c3f3d",
75 contrastText: "#ffdad8",
76 },
77 }),
78 },
79 },
80 light: {
81 palette: {
82 mode: "light",
83 primary: palette.augmentColor({
84 color: {
85 main: "#bd0b25",
86 contrastText: "#ffffff",
87 },
88 }),
89 secondary: palette.augmentColor({
90 color: {
91 main: "#006874",
92 contrastText: "#ffffff",
93 },
94 }),
95 text: {
96 primary: "#1C1B1F",
97 secondary: "#1C1B1F",
98 },
99 background: {
100 default: "#FFFBFE",
101 paper: "#fffbff",
102 },
103 error: palette.augmentColor({
104 color: {
105 main: "#B3261E",
106 contrastText: "#FFFFFF",
107 },
108 }),
109 success: palette.augmentColor({
110 color: {
111 main: "#006e10",
112 contrastText: "#ffffff",
113 },
114 }),
115 info: palette.augmentColor({
116 color: {
117 main: "#0062a2",
118 contrastText: "#ffffff",
119 },
120 }),
121 warning: palette.augmentColor({
122 color: {
123 main: "#606200",
124 contrastText: "#313300",
125 },
126 }),
127 divider: "#79747E",
128 upvote: palette.augmentColor({
129 color: {
130 main: "#bd0b25",
131 contrastText: "#ffffff",
132 },
133 }),
134 downvote: palette.augmentColor({
135 color: {
136 main: "#006874",
137 contrastText: "#ffffff",
138 },
139 }),
140 containerPrimary: palette.augmentColor({
141 color: {
142 main: "#ffdad6",
143 contrastText: "#410005",
144 },
145 }),
146 containerSecondary: palette.augmentColor({
147 color: {
148 main: "#ffdad8",
149 contrastText: "#2d1514",
150 },
151 }),
152 },
153 },
154};
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5export const theme = {
6 dark: {
7 palette: {
8 mode: "dark",
9 primary: palette.augmentColor({
10 color: {
11 main: "#acd452",
12 contrastText: "#253600",
13 },
14 }),
15 secondary: palette.augmentColor({
16 color: {
17 main: "#c2caaa",
18 contrastText: "#2c331c",
19 },
20 }),
21 text: {
22 primary: "#e4e2db",
23 secondary: "#e4e2db",
24 },
25 background: {
26 default: "#1b1c17",
27 paper: "#1b1c17",
28 },
29 error: palette.augmentColor({
30 color: {
31 main: "#ffb4a9",
32 contrastText: "#680003",
33 },
34 }),
35 success: palette.augmentColor({
36 color: {
37 main: "#79dd72",
38 contrastText: "#003a03",
39 },
40 }),
41 info: palette.augmentColor({
42 color: {
43 main: "#0062a2",
44 contrastText: "#ffffff",
45 },
46 }),
47 warning: palette.augmentColor({
48 color: {
49 main: "#606200",
50 contrastText: "#ffffff",
51 },
52 }),
53 divider: "#909284",
54 upvote: palette.augmentColor({
55 color: {
56 main: "#acd452",
57 contrastText: "#253600",
58 },
59 }),
60 downvote: palette.augmentColor({
61 color: {
62 main: "#ffb4a9",
63 contrastText: "#680003",
64 },
65 }),
66 containerPrimary: palette.augmentColor({
67 color: {
68 main: "#374e00",
69 contrastText: "#c8f16c",
70 },
71 }),
72 containerSecondary: palette.augmentColor({
73 color: {
74 main: "#3d4a36",
75 contrastText: "#d8e8cb",
76 },
77 }),
78 },
79 },
80 light: {
81 palette: {
82 mode: "light",
83 primary: palette.augmentColor({
84 color: {
85 main: "#4a6800",
86 contrastText: "#ffffff",
87 },
88 }),
89 secondary: palette.augmentColor({
90 color: {
91 main: "#5a6147",
92 contrastText: "#ffffff",
93 },
94 }),
95 text: {
96 primary: "#1b1c17",
97 secondary: "#1b1c17",
98 },
99 background: {
100 default: "#fefdf4",
101 paper: "#fefcf4",
102 },
103 error: palette.augmentColor({
104 color: {
105 main: "#ba1b1b",
106 contrastText: "#ffffff",
107 },
108 }),
109 success: palette.augmentColor({
110 color: {
111 main: "#006e10",
112 contrastText: "#ffffff",
113 },
114 }),
115 info: palette.augmentColor({
116 color: {
117 main: "#0062a2",
118 contrastText: "#ffffff",
119 },
120 }),
121 warning: palette.augmentColor({
122 color: {
123 main: "#606200",
124 contrastText: "#ffffff",
125 },
126 }),
127 divider: "#75786a",
128 upvote: palette.augmentColor({
129 color: {
130 main: "#4a6800",
131 contrastText: "#ffffff",
132 },
133 }),
134 downvote: palette.augmentColor({
135 color: {
136 main: "#ba1b1b",
137 contrastText: "#ffffff",
138 },
139 }),
140 containerPrimary: palette.augmentColor({
141 color: {
142 main: "#c8f16c",
143 contrastText: "#131f00",
144 },
145 }),
146 containerSecondary: palette.augmentColor({
147 color: {
148 main: "#d8e8cb",
149 contrastText: "#131f0e",
150 },
151 }),
152 },
153 },
154};
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5export const theme = {
6 dark: {
7 palette: {
8 mode: "dark",
9 primary: palette.augmentColor({
10 color: {
11 main: "#acd452",
12 contrastText: "#253600",
13 },
14 }),
15 secondary: palette.augmentColor({
16 color: {
17 main: "#c2caaa",
18 contrastText: "#2c331c",
19 },
20 }),
21 text: {
22 primary: "#e4e2db",
23 secondary: "#e4e2db",
24 },
25 background: {
26 default: "#1b1c17",
27 paper: "#1b1c17",
28 },
29 error: palette.augmentColor({
30 color: {
31 main: "#ffb4a9",
32 contrastText: "#680003",
33 },
34 }),
35 success: palette.augmentColor({
36 color: {
37 main: "#79dd72",
38 contrastText: "#003a03",
39 },
40 }),
41 info: palette.augmentColor({
42 color: {
43 main: "#0062a2",
44 contrastText: "#ffffff",
45 },
46 }),
47 warning: palette.augmentColor({
48 color: {
49 main: "#606200",
50 contrastText: "#ffffff",
51 },
52 }),
53 divider: "#909284",
54 upvote: palette.augmentColor({
55 color: {
56 main: "#acd452",
57 contrastText: "#253600",
58 },
59 }),
60 downvote: palette.augmentColor({
61 color: {
62 main: "#ffb4a9",
63 contrastText: "#680003",
64 },
65 }),
66 containerPrimary: palette.augmentColor({
67 color: {
68 main: "#374e00",
69 contrastText: "#c8f16c",
70 },
71 }),
72 containerSecondary: palette.augmentColor({
73 color: {
74 main: "#3d4a36",
75 contrastText: "#d8e8cb",
76 },
77 }),
78 },
79 },
80 light: {
81 palette: {
82 mode: "light",
83 primary: palette.augmentColor({
84 color: {
85 main: "#4a6800",
86 contrastText: "#ffffff",
87 },
88 }),
89 secondary: palette.augmentColor({
90 color: {
91 main: "#5a6147",
92 contrastText: "#ffffff",
93 },
94 }),
95 text: {
96 primary: "#1b1c17",
97 secondary: "#1b1c17",
98 },
99 background: {
100 default: "#fefdf4",
101 paper: "#fefcf4",
102 },
103 error: palette.augmentColor({
104 color: {
105 main: "#ba1b1b",
106 contrastText: "#ffffff",
107 },
108 }),
109 success: palette.augmentColor({
110 color: {
111 main: "#006e10",
112 contrastText: "#ffffff",
113 },
114 }),
115 info: palette.augmentColor({
116 color: {
117 main: "#0062a2",
118 contrastText: "#ffffff",
119 },
120 }),
121 warning: palette.augmentColor({
122 color: {
123 main: "#606200",
124 contrastText: "#ffffff",
125 },
126 }),
127 divider: "#75786a",
128 upvote: palette.augmentColor({
129 color: {
130 main: "#4a6800",
131 contrastText: "#ffffff",
132 },
133 }),
134 downvote: palette.augmentColor({
135 color: {
136 main: "#ba1b1b",
137 contrastText: "#ffffff",
138 },
139 }),
140 containerPrimary: palette.augmentColor({
141 color: {
142 main: "#c8f16c",
143 contrastText: "#131f00",
144 },
145 }),
146 containerSecondary: palette.augmentColor({
147 color: {
148 main: "#d8e8cb",
149 contrastText: "#131f0e",
150 },
151 }),
152 },
153 },
154};
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5const defaultLight = createTheme({
6 palette: {
7 mode: "light",
8 },
9});
10
11const defaultDark = createTheme({
12 palette: {
13 mode: "dark",
14 },
15});
16
17export const theme = {
18 dark: {
19 palette: {
20 ...defaultDark.palette,
21 upvote: palette.augmentColor({
22 color: {
23 main: "#66bb6a",
24 contrastText: "rgba(0,0,0,0.87)",
25 },
26 }),
27 downvote: palette.augmentColor({
28 color: {
29 main: "#f44336",
30 contrastText: "#fff",
31 },
32 }),
33 containerPrimary: palette.augmentColor({
34 color: {
35 main: "#121212",
36 contrastText: "white",
37 },
38 }),
39 containerSecondary: palette.augmentColor({
40 color: {
41 main: "#121212",
42 contrastText: "white",
43 },
44 }),
45 },
46 },
47 light: {
48 palette: {
49 ...defaultLight.palette,
50 upvote: palette.augmentColor({
51 color: {
52 main: "#2e7d32",
53 contrastText: "#32009a",
54 },
55 }),
56 downvote: palette.augmentColor({
57 color: {
58 main: "#d32f2f",
59 contrastText: "#fff",
60 },
61 }),
62 containerPrimary: palette.augmentColor({
63 color: {
64 main: "#fff",
65 contrastText: "#black",
66 },
67 }),
68 containerSecondary: palette.augmentColor({
69 color: {
70 main: "#fff",
71 contrastText: "#black",
72 },
73 }),
74 },
75 },
76};
1import { createTheme } from "@mui/material/styles";
2
3const { palette } = createTheme();
4
5const defaultLight = createTheme({
6 palette: {
7 mode: "light",
8 },
9});
10
11const defaultDark = createTheme({
12 palette: {
13 mode: "dark",
14 },
15});
16
17export const theme = {
18 dark: {
19 palette: {
20 ...defaultDark.palette,
21 upvote: palette.augmentColor({
22 color: {
23 main: "#66bb6a",
24 contrastText: "rgba(0,0,0,0.87)",
25 },
26 }),
27 downvote: palette.augmentColor({
28 color: {
29 main: "#f44336",
30 contrastText: "#fff",
31 },
32 }),
33 containerPrimary: palette.augmentColor({
34 color: {
35 main: "#121212",
36 contrastText: "white",
37 },
38 }),
39 containerSecondary: palette.augmentColor({
40 color: {
41 main: "#121212",
42 contrastText: "white",
43 },
44 }),
45 },
46 },
47 light: {
48 palette: {
49 ...defaultLight.palette,
50 upvote: palette.augmentColor({
51 color: {
52 main: "#2e7d32",
53 contrastText: "#32009a",
54 },
55 }),
56 downvote: palette.augmentColor({
57 color: {
58 main: "#d32f2f",
59 contrastText: "#fff",
60 },
61 }),
62 containerPrimary: palette.augmentColor({
63 color: {
64 main: "#fff",
65 contrastText: "#black",
66 },
67 }),
68 containerSecondary: palette.augmentColor({
69 color: {
70 main: "#fff",
71 contrastText: "#black",
72 },
73 }),
74 },
75 },
76};
Okay this is done, now how do we tell typescript that if I do <Button colour={’upvote’} /> then don’t throw an error? because I’ve supplied the values here in this object? also we haven’t added proper types to our current theme files. lets create some types.
create a file called index.ts at src/theme/index.ts
add the following code and read along:
1import { theme as green } from "./presets/green";
2import { theme as blue } from "./presets/blue";
3import { theme as _default } from "./presets/default";
4import { theme as red } from "./presets/red";
5import { Palette, PaletteColor } from "@mui/material/styles";
6
7// this is a typescript utility, if I say DeepPartial<Object> it means any key of that object, is not reauired.
8// this works even when we have nested objects and we want all the keys to be optional. why is this being used?
9// I'd recommend you try to omit this at the end of the tutorial to findout the errors you get to understand it's importance