Material-UI 主题覆盖利用主题调色板颜色

n-d*_*evr 17 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'
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

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

我想做什么

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

通过这种方式,我可以轻松更新原色,而不必担心在我的覆盖范围内更改对它的每个引用。我意识到我可以将rgba值提取到 a 中const,这将实现我的部分目标,但我不知道如何获得一些有用的东西,因为contrastText如果我选择了更浅的原色。

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

Nic*_*one 19

这里有另一种方法。createMuiTheme 接受任意数量的附加主题对象合并在一起

考虑到这一点,您可以复制您接受的答案,而无需使用两个不同的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;
Run Code Online (Sandbox Code Playgroud)

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

  • 这是我的首选解决方案 (3认同)

Ido*_*Ido 15

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

  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,
            }
        },
    }
    })
    
    Run Code Online (Sandbox Code Playgroud)

    你可以参考这个CodeSandbox

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


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

    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,
          }
      },
    }
    
    Run Code Online (Sandbox Code Playgroud)

    可以参考这个CodeSandbox


say*_*ode 9

MUI v5 中提供了一种更加简单的新方法。假设您想要覆盖 Mui 按钮的背景颜色。在自定义主题对象中,您可以指定:

const customTheme = createTheme({
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          backgroundColor: 'red',
        },
      },
    },
  },
});
Run Code Online (Sandbox Code Playgroud)

这是对值进行硬编码的常见情况。现在,如果您想使用刚刚制作的自定义主题中的某些属性(例如原色),您可以将一个箭头函数传递到根(或您需要覆盖的任何组件),并以对象作为参数,并返回一个对象包含您需要的样式。您可以访问返回对象内的主题。

const customTheme = createTheme({
  palette: {
    primary: {
      main: '#002255',
    },
  },
  components: {
    MuiButton: {
      styleOverrides: {
        root: ({ theme }) => ({
          backgroundColor: theme.palette.primary.main,
        }),
      },
    },
});
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,在对象内部您可以解构theme. 同样,您可以 destruct ownerState,其中包含组件的所有 props 和状态,您可以使用点运算符访问它们。为了说明这一点,我在 Mui 按钮组件上声明了一个名为 dark 的 prop

<Button dark={true}>Random Button</Button>
Run Code Online (Sandbox Code Playgroud)

现在我可以使用对象解构在按钮中访问此道具

const customTheme = createTheme({
  palette: {
    primary: {
      main: '#002255',
    },
  },
  components: {
    MuiButton: {
      styleOverrides: {
        root: ({ ownerState, theme }) => ({
          backgroundColor: ownerState.dark
            ? theme.palette.primary.dark
            : theme.palette.primary.light,
        }),
      },
    },
});
Run Code Online (Sandbox Code Playgroud)