Repository: material-ui
Issue: [mui-6] CssVarsProvider createTheme palette.mode ignores existing colorSchemes
Labels: status: expected behavior,customization: theme

### Summary

I would like createTheme to use existing colorScheme definitions when initialized with a mode and simply apply them to the theme, as opposed to generating a default and applying it to the theme.  I'd like this to only generate a default is a suitable colorScheme had not already been provided.



### Examples

My Theme looks something like this:

```json
{
  "name": "Theme Example",
  "colorSchemes": {
    "light": {
      "palette": {
        "primary": {
          "light": "var(--ns-palette-light-primary-light)",
          "main": "var(--ns-palette-light-primary-main)",
          "dark": "var(--ns-palette-light-primary-dark)",
          "lightChannel": "var(--ns-palette-light-primary-light-channel)",
          "mainChannel": "var(--ns-palette-light-primary-main-channel)",
          "darkChannel": "var(--ns-palette-light-primary-dark-channel)",
          "contrastText": "var(--ns-palette-light-primary-contrast-text)"
        },
...
      }
    },
    "dark": {
      "palette": {
        "primary": {
          "light": "var(--ns-palette-dark-primary-light)",
          "main": "var(--ns-palette-dark-primary-main)",
          "dark": "var(--ns-palette-dark-primary-dark)",
          "lightChannel": "var(--ns-palette-dark-primary-light-channel)",
          "mainChannel": "var(--ns-palette-dark-primary-main-channel)",
          "darkChannel": "var(--ns-palette-dark-primary-dark-channel)",
          "contrastText": "var(--ns-palette-dark-primary-contrast-text)"
        },
...
    }
  },
...
  "cssVariables": {
    "colorSchemeSelector": "class"
  },
  "palette": {}
}
```

This is heavily trimmed, but it should give the context.  And yes, the theme itself pulls in css variables for the underlying primitives from our design system, and whilst it gets somewhat indirect, it actually works very nicely.

Then I change color scheme to dark, the main theme (the one attached to the ThemeProvider), becomes:

```json
{
  "defaultColorScheme": "light",
  "name": "Dynamic Theme",
  "colorSchemeSelector": "class",
  "rootSelector": ":root",
  "vars": {
    "palette": {
      "primary": {
        "light": "var(--mui-palette-primary-light)",
        "main": "var(--mui-palette-primary-main)",
        "dark": "var(--mui-palette-primary-dark)",
        "lightChannel": "var(--mui-palette-primary-lightChannel)",
        "mainChannel": "var(--mui-palette-primary-mainChannel)",
        "darkChannel": "var(--mui-palette-primary-darkChannel)",
        "contrastText": "var(--mui-palette-primary-contrastText)",
        "contrastTextChannel": "var(--mui-palette-primary-contrastTextChannel)"
      },
...
    },
...
  },
  "palette": {
    "mode": "dark",
    "primary": {
      "light": "var(--ns-palette-dark-primary-light)",
      "main": "var(--ns-palette-dark-primary-main)",
      "dark": "var(--ns-palette-dark-primary-dark)",
      "lightChannel": "var(--ns-palette-dark-primary-light-channel)",
      "mainChannel": "var(--ns-palette-dark-primary-main-channel)",
      "darkChannel": "var(--ns-palette-dark-primary-dark-channel)",
      "contrastText": "var(--ns-palette-dark-primary-contrast-text)",
      "contrastTextChannel": "var(--ns-palette-dark-primary-contrast-text)"
    },
...
  "colorSchemes": {
    "light": {
      "palette": {
        "mode": "light",
        "primary": {
          "light": "var(--ns-palette-light-primary-light)",
          "main": "var(--ns-palette-light-primary-main)",
          "dark": "var(--ns-palette-light-primary-dark)",
          "lightChannel": "var(--ns-palette-light-primary-light-channel)",
          "mainChannel": "var(--ns-palette-light-primary-main-channel)",
          "darkChannel": "var(--ns-palette-light-primary-dark-channel)",
          "contrastText": "var(--ns-palette-light-primary-contrast-text)",
          "contrastTextChannel": "var(--ns-palette-light-primary-contrast-text)"
        },
...
    },
    "dark": {
      "palette": {
        "mode": "dark",
        "primary": {
          "light": "var(--ns-palette-dark-primary-light)",
          "main": "var(--ns-palette-dark-primary-main)",
          "dark": "var(--ns-palette-dark-primary-dark)",
          "lightChannel": "var(--ns-palette-dark-primary-light-channel)",
          "mainChannel": "var(--ns-palette-dark-primary-main-channel)",
          "darkChannel": "var(--ns-palette-dark-primary-dark-channel)",
          "contrastText": "var(--ns-palette-dark-primary-contrast-text)",
          "contrastTextChannel": "var(--ns-palette-dark-primary-contrast-text)"
        },
...
  },
  "cssVarPrefix": "mui"
}
```

With palette switching to dark as desired and referencing the underlying colorScheme.

If I just pass in mode = 'dark' to create them, I get this instead:

```json
{
  "defaultColorScheme": "dark",
  "name": "Theme Example",
  "colorSchemeSelector": "class",
  "rootSelector": ":root",
  "vars": {
    "palette": {
      "primary": {
        "light": "var(--mui-palette-primary-light, #e3f2fd)",
        "main": "var(--mui-palette-primary-main, #90caf9)",
        "dark": "var(--mui-palette-primary-dark, #42a5f5)",
        "lightChannel": "var(--mui-palette-primary-lightChannel, 227 242 253)",
        "mainChannel": "var(--mui-palette-primary-mainChannel, 144 202 249)",
        "darkChannel": "var(--mui-palette-primary-darkChannel, 66 165 245)",
        "contrastText": "var(--mui-palette-primary-contrastText, rgba(0, 0, 0, 0.87))",
        "contrastTextChannel": "var(--mui-palette-primary-contrastTextChannel, 0 0 0)"
      },
...
    },
  },
  "palette": {
    "mode": "dark",
    "primary": {
      "main": "#90caf9",
      "light": "#e3f2fd",
      "dark": "#42a5f5",
      "contrastText": "rgba(0, 0, 0, 0.87)",
      "mainChannel": "144 202 249",
      "lightChannel": "227 242 253",
      "darkChannel": "66 165 245",
      "contrastTextChannel": "0 0 0"
    },
...
  "colorSchemes": {
    "dark": {
      "palette": {
        "mode": "dark",
        "primary": {
          "main": "#90caf9",
          "light": "#e3f2fd",
          "dark": "#42a5f5",
          "contrastText": "rgba(0, 0, 0, 0.87)",
          "mainChannel": "144 202 249",
          "lightChannel": "227 242 253",
          "darkChannel": "66 165 245",
          "contrastTextChannel": "0 0 0"
        },
...
    },
    "light": {
      "palette": {
        "mode": "light",
        "primary": {
          "light": "var(--ns-palette-light-primary-light)",
          "main": "var(--ns-palette-light-primary-main)",
          "dark": "var(--ns-palette-light-primary-dark)",
          "lightChannel": "var(--ns-palette-light-primary-light-channel)",
          "mainChannel": "var(--ns-palette-light-primary-main-channel)",
          "darkChannel": "var(--ns-palette-light-primary-dark-channel)",
          "contrastText": "var(--ns-palette-light-primary-contrast-text)",
          "contrastTextChannel": "var(--ns-palette-light-primary-contrast-text)"
        },
...
  },
  "cssVarPrefix": "mui",
}
```

Whatever theme I pass in as the mode gets overwritten.

Now, I do understand that this is [probably intentional, but it would be awfully useful if this overwriting of the colorScheme only happened when there wasn't already a colorScheme defined.  That would make this much more flexible, and to my mind at least, more consistent


### Motivation

I'm trying to display a theme inspector - similar to the mui 6 one, where I create a theme using cssVariables, and I can toggle between light and dark modes of the theme without changing the theme that's applied to the application.

I want some way to create a theme object that can be inspected in both light and dark modes that isn't tied to the DOM, as far as I can tell from digging into useCurrentColorScheme.js, there's no way to get a theme in a specific mode without it trying to edit the DOM.  I want to be able to inspect the css variables, not apply them.

The closest is to use `createTheme` with palette.mode set to either light or dark, however that also initializes a default color scheme for that mode ignoring anything that you might already have set and then applying that scheme to the palette.  This works as desired if you are using an autogenerated theme, but if you are trying to migrate from an existing theme and have a rather large set of values that you want to preserve, it ignores and overwrites them.

If I just display the main application theme, I can see it switch between light and dark mode and update the palette and it's working beautifully, I can inspect that value and get exactly the behavior that I'm after, but it's changing the application theme.

I want the same change to a theme but without tying it to a ThemeProvider or having it try and update the DOM.

**Search keywords**: CssVarProvider