简体   繁体   English

使用 Material-UI 创建自定义变体

[英]Creating custom variants with Material-UI

I am trying to create custom variants for the Button component in Material-UI.我正在尝试为 Material-UI 中的Button组件创建自定义变体。

My first step is to create a component based off of the Button component with the styles that I want:我的第一步是使用我想要的 styles 创建一个基于Button组件的组件:

// CTA.js

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

const useStyles = makeStyles({
  root: { // CUSTOM__STYLES },
  label: { // CUSTOM__STYLES },
});

const CTA = ({ children }) => {
  const classes = useStyles();

  return (
    <Button
      classes={{
        root: classes.root, 
        label: classes.label,
      }}
    >
      {children}
    </Button>
  );
};

I then import that component into a new Button component that I am creating as follows:然后我将该组件导入到我正在创建的新Button组件中,如下所示:

// Button.js
import MuiButton from "@material-ui/core/Button";
import CTA from "./CTA";

const Button = ({ variant, ...muiButtonProps }) => {
  if (variant === "cta") {
    return <CTA {...muiButtonProps} />;
  }
  return <MuiButton {...muiButtonProps} />;
};

Now, what I want is to be able to import my new Button component and have it work just like a regular Material-UI button component, but with the addition of variant="cta" .现在,我想要的是能够导入我的新Button组件并让它像普通的 Material-UI 按钮组件一样工作,但添加了variant="cta" However, it does not quite work.但是,它并不完全有效。

For example, take a look at the following:例如,看看以下内容:

// Header.js
import { Button as MuiButton } from "@material-ui/core";
import { Button } from "@/theme/button.js";

...

<MuiButton variant="outlined">Mui Button</MuiButton>  // works
<Button variant="outlined">Button</Button> // does not work
<Button variant="cta">CTA Button</Button>  // works

I see that my new custom Button component works when I use variant="cta" , but it does not work when I use any of the built-in Material-UI variant options.我看到我的新自定义 Button 组件在我使用variant="cta"时有效,但在我使用任何内置 Material-UI 变体选项时它不起作用。 I cannot figure out what that is.我无法弄清楚那是什么。 I would have thought that <Button variant="outlined"> would work just like <MuiButton variant="outlined"> .我原以为<Button variant="outlined">会像<MuiButton variant="outlined">一样工作。 But that is not the case.但事实并非如此。

Any idea why not and how to fix it?知道为什么不以及如何解决吗?

In Material-UI v5, you can easily create a new variant for your components using createTheme() which removes the need to create wrapper components.在 Material-UI v5 中,您可以使用createTheme()轻松为您的组件创建一个新变体,从而无需创建包装组件。 Below is the minimum example:下面是最小的例子:

const theme = createTheme({
  components: {
    MuiButton: {
      variants: [
        {
          props: { variant: 'dashed' },
          style: {
            textTransform: 'none',
            border: `2px dashed grey${blue[500]}`,
          },
        },
      ],
    },
  },
});
export default function Demo() {
  return (
    <ThemeProvider theme={theme}>
      <Button variant="outlined">
        Outline
      </Button>
      <Button variant="dashed">
        Dashed
      </Button>
    </ThemeProvider>
  );
}

For typescript users, you also need to update the variant definition using module augmentation.对于 typescript 用户,您还需要使用模块扩充来更新变体定义。

declare module '@material-ui/core/Button' {
  interface ButtonPropsVariantOverrides {
    dashed: true;
  }
}

Live Demo现场演示

编辑 GlobalThemeVariants 材质演示

Two options are possible, it dont work cause you destruct "variant" and don't forward it to your MuiButton.有两种选择,它不起作用,因为您破坏“变体”并且不将其转发到您的 MuiButton。

You can do it this way in your Button.js您可以在 Button.js 中这样做

const Button = ({ variant, ...muiButtonProps }) => {
  if (variant === "cta") {
    return <CTA {...muiButtonProps} />;
  }
  return <MuiButton variant={variant} {...muiButtonProps} />;
};

or或者

const Button = (muiButtonProps) => {
  if (muiButtonProps.variant === "cta") {
    return <CTA {...muiButtonProps} />;
  }
  return <MuiButton {...muiButtonProps} />;
};

Take a look at the docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment查看文档: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

// Stage 4(finished) proposal
({a, b, ...rest} = {a: 10, b: 20, c: 30, d: 40});
console.log(a); // 10
console.log(b); // 20
console.log(rest); // {c: 30, d: 40}

In case, you are trying to style a given mui component globaly with the version 5, it should be something like:如果您尝试使用版本 5 对给定的 mui 组件进行全局样式设置,它应该类似于:

 const theme = createTheme({
 components:{
    MuiTableCell:{
      styleOverrides:{
        root:{
          color: "red"
        }
      }
    }
  },
});

to add on to NearHuscarl's answer if you want to customize a component that doesn't support custom variants yet, you can still change the style based on prop.如果要自定义尚不支持自定义变体的组件,要添加到 NearHuscarl 的答案中,您仍然可以根据 prop 更改样式。 Same as in Yassine CHABLI's answer, but one level more.与 Yassine CHABLI 的答案相同,但多了一层。 I had to do this recently when I wanted to be able to past variant='largeText' to my MuiTooltips.最近,当我希望能够将 variant='largeText' 传递到我的 MuiTooltips 时,我不得不这样做。

You're able to enter functions as the styleOveride and its passed an object with ownerState that has all the props you passed in at the top level.您可以输入作为 styleOveride 的函数,并且它传递了一个带有 ownerState 的 object ,其中包含您在顶层传递的所有道具。

From these docs: https://mui.com/material-ui/customization/theme-components/来自这些文档: https://mui.com/material-ui/customization/theme-components/

Minimal version looks like this:最小版本如下所示:

const theme = createTheme({
  components: {
    MuiTooltip: {
      styleOverrides: {
        tooltip: ({ ownerState }) => {
          if (ownerState?.variant === 'largeText') {
            return { fontSize: 16 };
          }
          return {};
        },
      },
    },
  },
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM