I am trying to create custom variants for the Button
component in Material UI.
My first step is to create a component-based off of the Button
component with the styles that I want:
// 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.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"
. 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. I cannot figure out what that is. I would have thought that <Button variant="outlined">
would work just like <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 variants for your components (See the list of supported components in this RFC) using createTheme()
which removes the need to create wrapper components. 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.
declare module '@mui/material/Button' {
interface ButtonPropsVariantOverrides {
dashed: true;
}
}
Two options are possible, it dont work cause you destruct "variant" and don't forward it to your MuiButton.
You can do it this way in your 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
// 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}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With