-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[theme] Allow custom color variants #13875
Comments
success
color palette option
success
color palette option
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
what's the status here? <Button color="customPaletteColor">Awesome!</Button> |
@katerlouis It works but you will get a prop-type warning. The next step is to, somehow, loosen the prop-types from a static check to a dynamic check. |
this doesn't work for me: // colors.js
export const blue = {
main: "#00CDE8",
}
export const red = {
main: "#FF495A",
light: "#F76E7B",
}
export const purple = {
main: "#5D2BFF",
}
... // theme.js
...
palette: {
primary: blue,
secondary: purple,
buy: blue,
sell: red,
},
... // SomeComponent.jsx
...
<Button color="sell">This is not red :'(</Button> What am I doing wrong? |
@katerlouis Ok, my bad, the current style structure doesn't allow it. We would need to perform the following diff: diff --git a/packages/material-ui/src/Button/Button.js b/packages/material-ui/src/Button/Button.js
index 958cb4d74..ad737d575 100644
--- a/packages/material-ui/src/Button/Button.js
+++ b/packages/material-ui/src/Button/Button.js
@@ -199,34 +199,20 @@ const Button = React.forwardRef(function Button(props, ref) {
...other
} = props;
- const text = variant === 'text';
- const outlined = variant === 'outlined';
- const contained = variant === 'contained';
- const primary = color === 'primary';
- const secondary = color === 'secondary';
- const className = clsx(
- classes.root,
- {
- [classes.text]: text,
- [classes.textPrimary]: text && primary,
- [classes.textSecondary]: text && secondary,
- [classes.outlined]: outlined,
- [classes.outlinedPrimary]: outlined && primary,
- [classes.outlinedSecondary]: outlined && secondary,
- [classes.contained]: contained,
- [classes.containedPrimary]: contained && primary,
- [classes.containedSecondary]: contained && secondary,
- [classes[`size${capitalize(size)}`]]: size !== 'medium',
- [classes.disabled]: disabled,
- [classes.fullWidth]: fullWidth,
- [classes.colorInherit]: color === 'inherit',
- },
- classNameProp,
- );
-
return (
<ButtonBase
- className={className}
+ className={clsx(
+ classes.root,
+ classes[variant],
+ {
+ [classes[`size${capitalize(size)}`]]: size !== 'medium',
+ [classes.disabled]: disabled,
+ [classes.fullWidth]: fullWidth,
+ [classes[`${variant}${capitalize(color)}`]]: color !== 'inherit',
+ [classes.colorInherit]: color === 'inherit',
+ },
+ classNameProp,
+ )}
component={component}
disabled={disabled}
focusRipple={!disableFocusRipple} From a bundle size perspective, it's already something worth doing :). Is this something you would like to contribute? Then, you could do: import React from 'react';
import { createMuiTheme } from '@material-ui/core/styles';
import { ThemeProvider } from '@material-ui/styles';
import Button from '@material-ui/core/Button';
const theme = createMuiTheme({
overrides: {
// Style sheet name ⚛️
MuiButton: {
// Name of the rule
textSell: {
color: 'red',
},
},
},
});
function OverridesCss() {
return (
<ThemeProvider theme={theme}>
<Button color="sell">Overrides CSS</Button>
</ThemeProvider>
);
}
export default OverridesCss; We would need to move #6115 forward or #16180 first to support |
If anyone is trying to use a new color palette with a button in v4, here is one way to do it:
import * as React from "react";
import clsx from "clsx";
import { ButtonProps, Button as MuiButton, withStyles, fade, capitalize } from "@material-ui/core";
// this is the material-ui Theme being used
import { Theme } from "../path-to-theme/theme";
const EXTRA_COLORS = ["danger"];
export const styles = (theme: Theme) => ({
/* Pseudo-class applied to the root element if `disabled={true}`. */
disabled: {},
/* Styles applied to the root element if `variant="text"` and `color="danger"`. */
textDanger: {
color: theme.palette.danger.main,
"&:hover": {
backgroundColor: fade(theme.palette.danger.main, theme.palette.action.hoverOpacity),
// Reset on touch devices, it doesn't add specificity
"@media (hover: none)": {
backgroundColor: "transparent",
},
},
},
/* Styles applied to the root element if `variant="outlined"` and `color="danger"`. */
outlinedDanger: {
color: theme.palette.danger.main,
border: `1px solid ${fade(theme.palette.danger.main, 0.5)}`,
"&:hover": {
border: `1px solid ${theme.palette.danger.main}`,
backgroundColor: fade(theme.palette.danger.main, theme.palette.action.hoverOpacity),
// Reset on touch devices, it doesn't add specificity
"@media (hover: none)": {
backgroundColor: "transparent",
},
},
"&$disabled": {
border: `1px solid ${theme.palette.action.disabled}`,
},
},
/* Styles applied to the root element if `variant="contained"` and `color="danger"`. */
containedDanger: {
color: theme.palette.danger.contrastText,
backgroundColor: theme.palette.danger.main,
"&:hover": {
backgroundColor: theme.palette.danger.dark,
// Reset on touch devices, it doesn't add specificity
"@media (hover: none)": {
backgroundColor: theme.palette.danger.main,
},
},
},
});
const _Button = React.forwardRef(function Button(
props: Omit<ButtonProps, "color"> & { color: ButtonProps["color"] | "danger" },
ref
) {
const { classes, disabled, className, color = "default", variant = "text", ...otherProps } = props;
return (
// @ts-ignore
<MuiButton
className={
EXTRA_COLORS.includes(color)
? clsx(
{
// @ts-ignore
[classes.disabled]: disabled,
// @ts-ignore
[classes[`${variant}${capitalize(color)}`]]: color !== "default" && color !== "inherit",
},
className
)
: className
}
disabled={disabled}
ref={ref}
// @ts-ignore
color={EXTRA_COLORS.includes(color) ? undefined : color}
variant={variant}
{...otherProps}
/>
);
});
// @ts-ignore
export const Button = withStyles(styles, { name: "ExtendedMuiButton" })(_Button); The above example is for adding support to a
|
Hey guys, |
@dstoyanoff Are you using v5? Do you have a reproduction? |
Hello @oliviertassinari, The issue is that the color property of the Typography is actually css color as Typography doesn't have the explicit color property. If I pass a valid CSS color, it would work, but this means I have to use Bacause of the above, Typography does not provide an overridable type for Typescript - e.g. Is there a plan to include support for color on Typography? |
@dstoyanoff What you are describing doesn't make sense to what I have conceptually for the component. Typography extends the Box which accepts any |
Thanks for this. I didn't know that colors work like this when nested in the theme. It's a nice one. Is there a way to make it type-safe in TypeScript? Perhaps you could leverage the new Template Literal Types... |
@dstoyanoff Please open a new issue for type-safe, it's actually an interesting topic (also to get autocomplete). |
I am having the same issue as #13875 (comment), expect for with the chip component. The button's I am able to customise thanks to @oliviertassinari's above fix. I opened an issue here: #26695 |
Should this automatically add the variants for e.g. <Button color="neutral">{JSON.stringify(theme.palette.neutral)}</Button> So either the type is incorrect in the documentation, or there's a bug in the implementation. |
@cjol It doesn't. You need to use |
Makes sense, so a more accurate type would be: type CustomColor = { main: string }
declare module '@material-ui/core/styles' {
interface Palette {
neutral: CustomColor
}
interface PaletteOptions {
neutral: CustomColor
}
} So that |
@oliviertassinari Im probably not asking this in the right spot, declare module '@mui/material/Typography' {
interface TypographyPropsVariantOverrides {
bold: true;
body3: true;
}
} I'd like to add a custom prop to the Box element that would be called "variant" and if variant 's value is "Bordered" then the Box element would get a custom border. |
@pouyarezvani, you can't just add new props. Those overrides are there to allow adding more possible values to an already existing property. You have to use styled for this or create your own component to wrap this one. |
Can we get this for v4 please, its impossible to upgrade to v5 y'all changed way too much and styled-components is just not the way we will be developing, v4 needs to live forever. |
v5 uses emotion by default, not styled-components, and we don't plan to support v4 anymore, except for security patches if there is need for them. Using emotion instead of JSS has enabled us tp create some of these new APIs which were not possible (too slow) when using JSS (v4) |
So, in the end: |
<Typography sx={{ color: (theme) => theme.palette.text.disabled }}>
This thing is disabled right now
</Typography> Read more about about MUI system properties |
Expected Behavior 🤔
The ability to have
success
in the color palette for Button, or any component w/ acolor
prop.Current Behavior 😯
Only
error
palette option is available.Context 🔦
Similar to the need for error styling, a
success
color palette option for any component that has acolor
prop would be equally valuable. The current functionality to get a green button option, for instance, requires lots of custom styling on the Button component which isn't ideal. If error is warranted in the palette, why not success as well?Another idea is for some kind of dynamic mapping, so if you created a manual key of
success
and passed it in as a color prop to a Button, the button would just try to find the theme override with that key in the palette.Thanks!
The text was updated successfully, but these errors were encountered: