Material-UI主题优先于利用主题调色板颜色

时间:2019-08-23 17:49:01

标签: reactjs material-ui

我目前正在使用全局主题重写自定义一些组件,以期尽可能地保持Material-UI主题引擎的完整性。我知道我可以完成使用合成的尝试,但是我想看看是否有可能通过重写来实现。

目标

更改BottomNavigation组件的背景色以使用当前主题的原色,并确保标签获得在该背景色之上可辨认的颜色。

我当前的方法

const theme = createMuiTheme({
    palette: {
      primary: {
        main: 'rgba(217,102,102,1)'
      }
    },
    overrides: {
        MuiBottomNavigation: {
            root: {
                backgroundColor: 'rgba(217,102,102,1)'
            }
        },
        MuiBottomNavigationAction: {
            wrapper: {
                color: '#fff'
            }
        }
    }
});

此代码完成了该任务,并将底部导航变成红色,标签/图标变成白色。但是,我希望能够灵活地更改调色板中的原色并相应地更新组件。

我要做什么

const theme = createMuiTheme({
    palette: {
      primary: {
        main: 'rgba(217,102,102,1)'
      }
    },
    overrides: {
        MuiBottomNavigation: {
            root: {
                backgroundColor: 'primary.main'
            }
        },
        MuiBottomNavigationAction: {
            wrapper: {
                color: 'primary.contrastText'
            }
        }
    }
});

通过这种方式,我可以轻松地更新原色,而不必担心在我的替代中更改对原色的所有引用。我意识到我可以将rgba的值提取到const中,这可以实现我的目标的一部分,但是我看不到如何获得像contrastText这样有用的东西我选择了更浅的原色。

那么-有人知道在主题覆盖定义中引用主题调色板颜色的方法吗?任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:6)

这里还有另一种方法。 createMuiTheme accepts any number of additional theme objects to be merged together

请记住,您可以复制your accepted answer而不必使用两个不同的ThemeProvider。而且,如果将主题定义移至其自己的模块,则不会在每个渲染器上重新创建它。

import { createMuiTheme } from "@material-ui/core/styles";

const globalTheme = createMuiTheme({
  palette: {
    primary: {
      main: "rgba(217,255,102,1)"
    }
  }
});

const theme = createMuiTheme(
  {
    overrides: {
      MuiButton: {
        root: {
          backgroundColor: globalTheme.palette.primary.main
        },
        label: {
          color: globalTheme.palette.primary.contrastText
        }
      }
    }
  },
  globalTheme
);

export default theme;

我更新了CodeSandBox以反映这一点。

答案 1 :(得分:2)

我将提供两种解决方案-一种更具可读性和可维护性,一种具有更好的性能。

  1. 可读且可维护的方法:
    创建嵌套主题。
    一个主题将用于定义调色板,而一个主题将用于覆盖。
    因为有两个主题,所以您可以从替代主题访问调色板主题:

    const globalTheme = createMuiTheme({
      palette: {
        primary: {
          main: 'rgba(217,255,102,1)'
        }
      },
    });
    
    const overridesTheme = createMuiTheme({
      overrides: {
        MuiButton: {
            root: {
                backgroundColor: globalTheme.palette.primary.main,
            },
            label: {
              color:globalTheme.palette.primary.contrastText,
            }
        },
    }
    })
    

    您可以参考此CodeSandbox

    这种方法性能不佳,因为每次渲染都会计算并注入一个新的CSS对象


  1. 更好的性能方法:
    首先,使用调色板创建一个Mui主题骨架。 创建完之后,您添加依赖于调色板的样式(请注意,我必须如何大量使用span运算符以避免删除样式):

    const theme = createMuiTheme({
      palette: {
        primary: {
          main: 'rgba(217,255,102,1)'
        }
      },
    })
    
    theme.overrides = {
      ...theme.overrides,
      MuiButton: {
          ...theme.MuiButton,
          root: {
             ...theme.root,
              backgroundColor: theme.palette.primary.main,
          },
          label: {
            ...theme.label,
            color:theme.palette.primary.contrastText,
          }
      },
    }
    

    您可以参考此CodeSandbox

答案 2 :(得分:0)

适合那些正在寻找主题和主题间切换答案的人。

https://codesandbox.io/s/material-theme-switching-with-pallete-colors-vfdhn

创建两个主题对象并在它们之间切换。在它们之间使用相同的主题属性,以便您所有的替代都可以使用相同的调色板来确保不会重复,并且我们将完全使用替代。

import { createMuiTheme } from "@material-ui/core/styles";

let globalTheme = createMuiTheme({
  palette: {
    primary: {
      main: "#fa4616"
    }
  }
});

export const LightTheme = createMuiTheme(
  {
    overrides: {
      MuiButton: {
        root: {
          backgroundColor: globalTheme.palette.primary.main
        },
        label: {
          color: globalTheme.palette.primary.contrastText
        }
      }
    }
  },
  globalTheme
);

globalTheme = createMuiTheme({
  palette: {
    primary: {
      main: "#0067df"
    }
  }
});

export const DarkTheme = createMuiTheme(
  {
    overrides: {
      MuiButton: {
        root: {
          backgroundColor: globalTheme.palette.primary.main
        },
        label: {
          color: globalTheme.palette.primary.contrastText
        }
      }
    }
  },
  globalTheme
);