0
votes

Material UI's default theme ships a palette of colors, including a special set of dark colors (docs, code).

What makes these dark mode colors special is components who consume them don't need to depend on knowing the theme's palette.mode (aka light/dark mode) - they update automatically. codesandbox demo

My goal is to extend this set of colors, such that components I write can use new colors beyond this built-in set, e.g. theme.palette.myColor and benefit from the same automatic behavior.

In other words, I don't want to have dark mode logic be duplicated in each theme-consuming component:

const WhatIDontWantComponent = () => (
  <Box
    sx={{
      color: (theme) =>
        theme.palette.mode === "light"
          ? theme.palette.myColor.light
          : theme.palette.myColor.dark,
    }}
  />
);

I instead want to use

const WhatIWantComponent = () => (
  <Box
    sx={{
      color: (theme) => theme.palette.myColor
    }}
  />
);

So myColor would be included in the light/dark set that already exists, and benefit from this automatic behavior.

Example

Possible? Is there some way to accomplish this within my app without patching MUI in some way to accept custom colors?


deps

  • @material-ui/core version 5.0.0-beta.4
  • react, react-dom 17.0.2
  • next.js 11.0
2

2 Answers

0
votes

You can customize the material-ui theme using theme provider component in order to add your custom colors for e.g,

  import { createTheme, colors } from '@material-ui/core/styles';

  const theme = createTheme({
  palette: {
    background: {
      default: "#F6F7FF",
      paper: colors.common.white
    },
    primary: {
      main: "#43A047"
    },
    secondary: {
      main: "#43A047"
    },
    text: {
      primary: "#000000",
      secondary: "#6b778c"
    },
    // Add your custom colors if any
  },
});

You can write this configuration code inside a separate file and then import it into your root component file.

import theme from "src/theme";
import { ThemeProvider } from "@material-ui/core";


<ThemeProvider theme={theme}>
   <YourRootComponent />
</ThemeProvider>

Then consume it the same way you do it for the default material UI colors

Also, you can customize typography, shadows, override default class, and much more check out this

0
votes

Ended up going with this:

const baseTheme = createTheme({...common options...})
export const lightTheme = createTheme({ ...light specific...}, baseTheme)
export const darkTheme = createTheme({ mode: "dark", ...dark specific...}, baseTheme)

based on this discussion. We basically perform theme composition in multiple steps + utilizing how the second arg to createTheme() gets deepmerge'd.

Once you have the two themes, you could consider setting up a toggle by bringing your own mode:

<ThemeProvider theme={mode ? lightTheme : darkTheme}>
  {...app...}
</ThemeProvider>

This works, but IMO a downside of this approach though is that I have two themes and have to manage dark/light state externally. Not a huge problem but feels a bit redundant -- in my mind dark/light mode seems like a concern that could (should) be handled internally to a single theme.

Perhaps there are good reasons against, but IMO it feels more ergonomic if MUI would allow users to specify our own dark palette, like I asked in my original question, vs the current hard coded one.

So if you're looking for custom MUI dark colors, this approach seems to be the best one given the situation right now.