Closed kushal-tech closed 5 years ago
@kushaljain03 Yes, you can:
const theme = createMuiTheme({
palette: {
success: {
main : "#bac778",
},
},
})
Yes I can but I cannot use it like
<Button color="success">Login</Button>
It gives warning about to use only primary default secondary
No, you can't use the success color property directly. You need to create a wrapping component to use the theme values. Going forward, I wish we can make it work. We have recently added the support for style functions. If the performance are good enough. We can imagine changing the implementation.
Adding additional properties is not explicitly documented. At least I couldn't find it. I think we can add another section that also includes how one would make this work with TypeScript.
Actually: https://material-ui.com/customization/themes/#custom-variables for JS and https://material-ui.com/guides/typescript/#customization-of-theme with additional info for TS.
Color styling has been one of the major difficulties when using this library. For instance, a simple use case where you have three buttons side-by-side, all different colors. Trying to style this with themes is really limiting and unintuitive. From what I can tell this is only possible to implement with the first two buttons using one theme, then the third button using a different (nested) theme:
But this is a weird way to break things up logically, because in this app all of these colors should be under one theme.
Another option is to avoid themes for this entirely, but then this seems to give up the nice benefits of having the contrastText helpers and such.
@davidcalhoun Yes, you are right, this issue is about extending the Button implementation so people can just do:
const theme = createMuiTheme({
palette: {
success: {
main : "#bac778",
},
},
})
then have a working:
<Button color="success" />
implementation.
The best solution right now is to add the color in the theme, then to create a wrapping component:
import React from "react";
import { withStyles, ThemeProvider } from "@material-ui/styles";
import MuiButton from "@material-ui/core/Button";
import { createMuiTheme } from "@material-ui/core/styles";
const Button = withStyles(theme => ({
root: props =>
props.color === "success" && props.variant === "contained"
? {
color: theme.palette.success.contrastText,
backgroundColor: theme.palette.success.main,
"&:hover": {
backgroundColor: theme.palette.success.dark,
// Reset on touch devices, it doesn't add specificity
"@media (hover: none)": {
backgroundColor: theme.palette.success.main
}
}
}
: {}
}))(MuiButton);
const theme = createMuiTheme();
theme.palette.success = theme.palette.augmentColor({
main: "#689f38"
});
function Theming() {
return (
<ThemeProvider theme={theme}>
<Button variant="contained" color="primary">
primary
</Button>
<Button variant="contained" color="success">
success
</Button>
</ThemeProvider>
);
}
export default Theming;
https://codesandbox.io/s/7zmw6ox8m1
By the way, we are planing on extending the color to primary | secondary | success | warning | error/danger? | info
. Would that help in your case?
If you don't care about the warnings, you can do 🤷♂️:
import React from "react";
import { ThemeProvider } from "@material-ui/styles";
import Button from "@material-ui/core/Button";
import { createMuiTheme } from "@material-ui/core/styles";
const theme = createMuiTheme();
theme.palette.success = theme.palette.augmentColor({
main: "#689f38"
});
const isSuccess = style => props =>
props.color === "success" && props.variant === "contained" ? style : {};
theme.overrides = {
MuiButton: {
root: {
color: isSuccess(theme.palette.success.contrastText),
backgroundColor: isSuccess(theme.palette.success.main),
"&:hover": {
backgroundColor: isSuccess(theme.palette.success.dark)
}
}
}
};
function Theming() {
return (
<ThemeProvider theme={theme}>
<Button variant="contained" color="primary">
primary
</Button>
<Button variant="contained" color="success">
success
</Button>
</ThemeProvider>
);
}
export default Theming;
Thanks for the great examples! That helps. For sure, having other color names outside of just "primary" and "secondary" helps a lot, but I'm not sure if it solves my use case.
In my case I'm trying to use color themes for a dropdown button I'm creating with three states:
Draft
(a greyish background)In Progress
(bluish background)Completed
(greenish color)It would be great to be able to define these in a theme somehow, but these states don't necessarily map onto semantic names (primary
and secondary
work fine for two of the three colors though!). I like defining them in the theme and then being able to rely on the theme to automatically figure out derived colors (text state based on contrast, hover state colors, etc).
I'm guessing the philosophy is different (or maybe it's a performance concern?), but I would kind of prefer being able to define custom color names inside the theme that wouldn't necessarily be semantic or whatnot, just practical. For the cases above, I'd like to define some colors inside the theme called grey
, blue
, and green
.
I especially like the second example, but I want to avoid anything that generates warnings! For this particular use case, I think I'll just avoid using themes for now and look for other styling options.
@davidcalhoun This is something I'm experimenting locally. The material design guidelines already define a color and the "contrast" color (or "on" color in material speak).
The idea is that you can add any color in the theme and either let us figure out what a good "on"-color would be or let you define that too. The component should then take care of the rest i.e. given a color name figure out what color to choose for background, text or iconography.
States like hover, disabled, focused etc are currently handled via opacity in the material guidelines. Would be interesting to explore possible APIs to make this customizable too e.g. let the user define a theme wide function with the following signature: (Color, State) => Color
.
I have wanted something like this for as long as I've been using Material UI. I've always been extremely frustrated by the fact that the palette is limited to 3 colors, and we have to resort to these awful, dirty, awkward hacks to make it work with more. When can we expect this to be fixed?
When can we expect this to be fixed?
@kaitlynbrown And you started so well...
@mbrookes And you started so vaguely...
Closing this in favor of #13875. You can already add custom colors to the palette. Just not use them in color
props of our components.
For a typescript implementation you can do something like this. Using props in the styles are avoided to improve JSS performance. (This avoids generating unique classes for every button and works great in large lists, etc...)
import React from "react";
import { createStyles, Theme, makeStyles } from "@material-ui/core/styles";
import Button, { ButtonProps } from "@material-ui/core/Button";
import capitalize from "lodash/capitalize";
export type ColorTypes =
| "primary"
| "secondary"
| "error"
| "success"
| "warning"
| "default"
| "inherit"
| "info";
export type ColoredButtonProps = { color: ColorTypes } & Omit<
ButtonProps,
"color"
>;
const useStyles = makeStyles<Theme>(theme =>
createStyles({
outlinedSuccess: {
borderColor: theme.palette.success.main,
color: theme.palette.success.main
},
outlinedError: {
borderColor: theme.palette.error.main,
color: theme.palette.error.main
},
outlinedWarning: {
borderColor: theme.palette.warning.main,
color: theme.palette.warning.main
},
outlinedInfo: {
borderColor: theme.palette.info.main,
color: theme.palette.info.main
},
containedSuccess: {
backgroundColor: theme.palette.success.main,
color: theme.palette.success.contrastText,
"&:hover": {
backgroundColor: theme.palette.success.dark
}
},
containedError: {
backgroundColor: theme.palette.error.main,
color: theme.palette.error.contrastText,
"&:hover": {
backgroundColor: theme.palette.error.dark
}
},
containedWarning: {
backgroundColor: theme.palette.warning.main,
color: theme.palette.warning.contrastText,
"&:hover": {
backgroundColor: theme.palette.warning.dark
}
},
containedInfo: {
backgroundColor: theme.palette.info.main,
color: theme.palette.info.contrastText,
"&:hover": {
backgroundColor: theme.palette.info.dark
}
}
})
);
const ColoredButton: React.FC<ColoredButtonProps> = ({
children,
color,
...props
}) => {
const classes = useStyles();
const className = classes?.[`${props.variant}${capitalize(color)}`];
const colorProp =
["default", "inherit", "primary", "secondary"].indexOf(color) > -1
? (color as "default" | "inherit" | "primary" | "secondary")
: undefined;
return (
<Button {...props} color={colorProp} className={className}>
{children}
</Button>
);
};
ColoredButton.displayName = "ColoredButton";
export default ColoredButton;
For a typescript implementation and mui 5, you can act like this. Example of new color in the palette file:
import { colors } from "@mui/material",
const common = {
infromation: {
warnning: '#CFDD4A',
}
}
type.ts will be like this:
import Palette from "@mui/material/styles/createPalette";
declare module '@mui/material/styles' {
interface Palette {
infromation?: {
warnning?: string
}
}
}
Like MuiTheme already provided a way to override colors of 3 property
Primary
Secondary
error
This is the below way to change the colors of existing properties.
What If we need to define new property for color like
Is that possible ?