Material-UI:如何在组件内访问所有调色板颜色?

13

为了自定义我的 Material UI 调色板,我做了以下操作来设置主题:

import blue from '@material-ui/core/colors/blue';

const theme = createMuiTheme({
  palette: {
    primary: blue,
  },
});

blue 包含许多不同的色调,如下所示:

enter image description here

现在我该如何在我的组件中访问 primary 调色板的所有色调?访问 palette.grey 的所有色调很容易,如下所示:

enter image description here

但是我似乎无法访问 primary 的除了 main, dark, light, 和 contrastColor 之外的其他色调,如下所示:

enter image description here

我应该如何从我的组件中访问所有的色调(例如,theme.palette.primary.A100)?

2个回答

9
现在我该如何在我的组件中访问主色调的所有阴影?我认为这里有一个误解。您已经可以访问主题颜色的变体(darklightcontrastText),但如果您指的是来自颜色对象的所有阴影(blue[100]blue[200],...)。那么不,createTheme() 不会自动为您生成它。
来自 Material-UI docs 的信息:
只需要提供主要色调即可(除非您希望进一步自定义 lightdarkcontrastText),因为其他颜色将由 createTheme() 计算,如主题自定义部分所述。
当您仅向 main 属性提供 1 种颜色时:
const theme = createTheme({
  palette: {
    primary: {
      main: "#607d8b"
    }
  }
});

Material-UI将计算该颜色的lightdark变体以及文本颜色的contrastText。 您可以记录theme.palette.main以确认此操作:
const useStyles = makeStyles((theme) => {
  console.log(theme.palette.main);
  return {};
});

{
  main: "#607d8b",
  light: "rgb(127, 151, 162)",
  dark: "rgb(67, 87, 97)",
  contrastText: "#fff",
}

如果您决定传递一个颜色对象
import { createTheme } from '@material-ui/core/styles';
import blue from '@material-ui/core/colors/blue';

const theme = createTheme({
  palette: {
    primary: blue,
  },
});

然后Material-UI将查找该对象的主要色调。默认值为blue[500],并根据main颜色正常计算darklightcontrastText。最终结果看起来像这样:
const useStyles = makeStyles((theme) => {
  console.log(theme.palette.main);
  return {};
});

{
  50: "#eceff1",
  100: "#cfd8dc",
  200: "#b0bec5",
  300: "#90a4ae",
  400: "#78909c",
  500: "#607d8b", // createPalette() uses this color as main
  600: "#546e7a",
  700: "#455a64",
  800: "#37474f",
  900: "#263238",
  A100: "#cfd8dc",
  A200: "#b0bec5",
  A400: "#78909c",
  A700: "#455a64",
  main: "#607d8b", // added from createPalette()
  light: "#90a4ae", // added from createPalette()
  dark: "#455a64", // added from createPalette()
  contrastText: "#fff", // added from createPalette()
}

使用Typescript

正如this问题所指出的那样,如果你正在使用Typescript,你可能会意识到它没有在主题PaletteColor中提供给你阴影信息。

const useStyles = makeStyles((theme) => {
  const shade = theme.palette.main[500]; // shade is any instead of string
  return {};
});

维护者建议的解决方案是使用“模块增强”来扩展PaletteColor的定义:
import { ColorPartial } from "@material-ui/core/styles/createPalette";

declare module "@material-ui/core/styles/createPalette" {
  interface PaletteColor extends ColorPartial {}
}

如果您正在使用 this 代码检查建议来避免导入私有模块(任何深度超过2级的导入)。您可以轻松地像这样创建自己的 ColorPartial:
import { Color } from "@material-ui/core";

type ColorPartial = Partial<Color>;

declare module "@material-ui/core/styles/createPalette" {
  interface PaletteColor extends ColorPartial {}
}

现在,TypeScript已经了解了您的 PaletteColor 中所有可能的色调:
const useStyles = makeStyles((theme) => {
  const shade = theme.palette.main[500]; // shade is string
  return {};
});

演示

Edit 67013112/material-ui-how-to-access-all-palette-shades-inside-component


非常好,运行得非常顺利!原来是 TypeScript 让我困惑了。我只能在 theme.palette.primary[500] 顶部添加 //@ts-ignore 才能让它工作,否则就会出现以下错误:Element implicitly has an 'any' type because expression of type '500' can't be used to index type 'PaletteColor'. TS7053。您的 codesandbox 似乎没有这个问题。你是怎么让 TypeScript 允许在 PaletteColor 上使用 500 索引器的? - Johnny Oshika
这是我的沙盒。我可以让它工作,但代码编辑器显示类型错误。在 VS Code 中,除非我添加 //@ts-ignore,否则它甚至无法运行。https://codesandbox.io/s/material-ui-access-all-palette-shades-inside-components-gimgx?file=/src/demo.tsx - Johnny Oshika
1
@JohnnyOshika 我刚刚将我的工作沙盒中的tsconfig复制到你的沙盒中,但仍然出现错误。不确定为什么我的可以工作,因为它本来是不应该工作的。一个解决方案是使用模块扩展来扩展PaletteColor。请参考这个示例。如果您需要PaletteColor扩展的示例,请联系我。 - NearHuscarl
@NearHuscari 我尝试了模块增强。虽然它可以使用自定义调色板名称(例如,我正在使用primaryShades),但是当我想将标准名称(如primary)作为Color进行增强时,它就无法工作,因为它已经被定义为PaletteColor。我得到的错误是:后续属性声明必须具有相同的类型。属性'primary'的类型必须为'PaletteColor',但此处的类型为'Color'。ts(2717) - Johnny Oshika
我的工作解决方案是我创建的自定义调色板(primaryShades),它运行得足够好。但使用默认的 primary 会更好。 - Johnny Oshika
显示剩余2条评论

0
根据Material UI颜色系统文档,它会自动计算出几个值,例如darklightmain。然而,对于更多的变体,建议使用颜色对象,例如@material-ui/core/colors/blue。这可能就是你在第一个示例代码中使用的blue
颜色对象的结构如下所示。GitHub链接
const blue = {
  50: '#e3f2fd',
  100: '#bbdefb',
  200: '#90caf9',
  300: '#64b5f6',
  400: '#42a5f5',
  500: '#2196f3',
  600: '#1e88e5',
  700: '#1976d2',
  800: '#1565c0',
  900: '#0d47a1',
  A100: '#82b1ff',
  A200: '#448aff',
  A400: '#2979ff',
  A700: '#2962ff',
};

export default blue;

因此,如果您想使用更多未作为颜色对象提供的颜色变体,您应该自己创建颜色变体。


谢谢,但是我如何在我的React组件中访问这些不同的蓝色阴影呢?主题被注入到makeStyles中,但我似乎无法在那里访问主要颜色的阴影。您是否建议我在全局blue模块中硬编码这些值并导入该模块?那将绕过Material UI主题。 - Johnny Oshika
我不确定,但我认为你应该创建一个名为createPalette的函数或覆盖它。源代码 - Hyeonseo Kim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接