Merge material-ui overrides - material-ui

I'm trying to merge overrides of two themes but have not got it working.
So I have common settings:
const commonSettings = {
spacing: 10,
overrides: {
MuiButton: {
root: {
textTransform: "uppercase",
borderRadius: 6
}
}
}
};
And theme settings:
const themeSettings = {
overrides: {
MuiAppBar: {
colorPrimary: {
backgroundColor: "#333",
color: "#FFF"
}
}
}
};
Merging the theme:
const lightTheme = createMuiTheme({ ...commonSettings, ...themeSettings });
So spacing will get added to the merged theme from commonSettings, it works as expected but I can't get the overrides values to merge. The override from themeSettings will be used without the values from commonSettings. Is it possible to merge the overrides together?

Okey, so I got it working by inserting the overrides from the theme in the commonSettings as a standard object.
overrides: {
MuiButton: {
root: {
textTransform: "none",
borderRadius: 50
}
},
...(lightThemeOverrides)
},

Related

Material-UI Table/XGrid - How to set a different color for each cell

The styling for cell tables in material-ui is fine when you have a limited known amount of options but I'm struggling when is not known in advance.
To simplify, the idea is setting the background color for each cell based on the table cell values (let's imagine the value of the cell is actually the color).
Using cellRenderers is limited (not really a clean option).
The current solution looks like (doc):
cellClassName: (params: GridCellClassParams) =>
clsx('super-app', {
negative: (params.value as number) < 0,
positive: (params.value as number) > 0,
}),
How could create dynamically add styling or css in material-ui v5/emotion (doc). Something like :
cellSx: (params: GridCellClassParams) =>{
{
backgroundColor: params.value
}
}),
As per your question, I understood that you will receive color names and need to apply those colors on the cells in which the color names are present.
To dynamically create the object present in "clsx" method.
// let us consider that there is a key named color in the params which is received in the colums.
const generateColorsObject = (color) => {
const colorKey = color;
const colorObject = {}
colorObj[colorKey] = color
return colorObj; // it's value will have something like { 'red': 'red' }
}
const columns = [
{
field: 'name',
cellClassName: 'super-app-theme--cell',
},
{
field: 'score',
type: 'number',
width: 140,
cellClassName: (params) =>
clsx('super-app', generateColorsObject(params.color)),
},
];
const useStyles = makeStyles({
root: {
'& .super-app.red': {
backgroundColor: 'red', // you need to configure the background colors to the colorKey
color: '#1a3e72',
fontWeight: '600',
},
'& .super-app.blue': {
backgroundColor: 'blue',
color: '#1a3e72',
fontWeight: '600',
},
'& .super-app.orange': {
backgroundColor: 'orange',
color: '#1a3e72',
fontWeight: '600',
},
},
});
I think it boils down to the problem to create a mui class which applies the styling from the received props.
You can leverage material ui useStyles hook advanced feature to create mui classes which accepts the props, so you can pass over some style details as you want.
const useStyles = makeStyles({
// style rule
foo: props => ({
backgroundColor: props.backgroundColor,
}),
bar: {
// CSS property
color: props => props.color,
},
});
function MyComponent() {
// Simulated props for the purpose of the example
const props = { backgroundColor: 'black', color: 'white' };
// Pass the props as the first argument of useStyles()
const classes = useStyles(props);
return <div className={`${classes.foo} ${classes.bar}`} />
}
You can find the doc from here.
To solve this issue I used the cellClassName and changing the class using a function. Here is my working code:
// Based on the value of the cell the class will be applied.
const applyCellColour = (value: boolean) => (value ? 'notApprovedCell' : 'approvedCell');
// In the columns array in the cellClassName:
const columns: GridColDef[] = [
{
field: 'Approval',
headerName: 'Approval',
headerAlign: 'center',
align: 'center',
cellClassName: params => applyCellColour(params),
},
]
// CSS
.approvedCell {
background-color: 'green';
}
.notApprovedCell {
background-color: 'red';
}

Correct way to style a section of a material-ui document

I have a header and want to style all of it's buttons differently than my global theme. I have tried using a child theme like:
<ThemeProvider
theme={(outerTheme) =>
_.merge(outerTheme, {
overrides: {
MuiButton: {
label: {
color: "#fff",
},
},
},
})
}
>
However, while I had expected this to override only MuiButton's in the child theme, it overrode them in them globally.
I know I can use makeStyles but, then, as far as I know, I have to reference it in all the child components which want to use the style. I'd like to wrap a higher level component and have all child components pick up the style. How is this done?
You can do this:
import Button from '#material-ui/core/Button';
import { purple } from '#material-ui/core/colors';
import { makeStyles } from '#material-ui/core/styles';
const useStyles = makeStyles((theme) => ({
header: {
"& button": {
marginRight: theme.spacing(1),
color: theme.palette.getContrastText(purple[500]),
backgroundColor: purple[500],
"&:hover": {
backgroundColor: purple[700],
},
},
},
});
function CustomHeader(props) {
const classes = useStyles();
return (
<div className={classes.header}>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button disabled>Button 3</Button>
</div>
)
};

Cannot override Material UI Typography fontWeight

I just started using Material UI and learning to customize the default theme. I tried changing default palette color and it worked but overriding the typography property was not working.
I am trying to fontWeight property of h3 variant. The default fontWeight for h3 variant is 400. I am changing it to 100 or 300 but it's not reflecting.
Here is my code
Component.js
return (
<Typography variant="h3" color="secondary">
Arc Development
</Typography>
)
theme.js
import {createMuiTheme} from "#material-ui/core";
const arcBlue = "#0B72B9";
const arcOrange = "#FFBA60";
export default createMuiTheme({
palette: {
common: {
blue: `${arcBlue}`,
orange: `${arcOrange}`,
},
primary: {
main: `${arcBlue}`
},
secondary: {
main: `${arcOrange}`
}
},
typography: {
h3: {
fontS: 0,
}
}
});
Ciao, to override Typography you have to define in your theme an object called overrides and then inside this object you have to define another object called MuiTypography and override the h3 variant like this:
export default createMuiTheme({
palette: {
common: {
blue: `${arcBlue}`,
orange: `${arcOrange}`,
},
primary: {
main: `${arcBlue}`
},
secondary: {
main: `${arcOrange}`
}
},
overrides: {
MuiTypography: {
h3: {
fontWeight: 100
}
}
}
});
And if you inspect the element, you will see:
Here a codesandbox example.

Re-use themed style blocks within a Material-UI components styles

Thinking of the concept of a SASS mixin, what would be the best approach to enable the re-use of style blocks that incorporate the current theme.
For example I have two components that import their respective styles:
Component 1
index
styles
Component 2
index
styles
Each component has a text block
Component 1
import { styles } from './styles'
....
<div className={classes.richText}>...</div>
Component 2
import { styles } from './styles'
....
<div className={classes.richText}>...</div>
The styles for richText are the same but I would rather not duplicate them in the imported styles file.
I would rather have a single file that exposes reusable CSS properties based on the theme.
The only way I can currently do this is by returning an object that I have passed the theme to e.g.
const RichText = (theme) => {
return {
fontWeight: 100,
color: theme.typography.body1.color
}
}
Then import this into the styles
Component 1
styles.js
import { RichText } from '../mixins/'
const styles = theme => ({
richText: {
...RichText(theme),
fontSize: '1rem'
}
Component 2
styles.js
import { RichText } from '../mixins/'
const styles = theme => ({
richText: {
...RichText(theme),
fontSize: '1.2rem'
}
Feels like there has to be a better way: utilising withTheme() maybe?
Let's say you want to custom a checkbox as below:
import { makeStyles } from '#material-ui/core/styles';
import CheckBox from '#material-ui/core/CheckBox';
const useStyles = makeStyles((theme) => ({
root: {
color: theme.status.danger,
'&$checked': {
color: theme.status.danger,
},
},
checked: {},
}));
function CustomCheckbox() {
const classes = useStyles();
return (
<Checkbox
defaultChecked
classes={{
root: classes.root,
checked: classes.checked,
}}
/>
);
}
And you want to reuse its style as many components as you can.
You have two options: ThemeProvider or export your custom style.
Changing the component's theme
Themes let you apply a consistent tone to your app. It allows you to customize all design aspects of your project in order to meet the specific needs of your business or brand.
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
import orange from '#material-ui/core/colors/orange';
const myTheme = createMuiTheme({
status: {
danger: orange[500],
},
});
export default function CustomStyles() {
return (
<ThemeProvider theme={myTheme}>
<CustomCheckbox />
</ThemeProvider>
);
}
Exporting your custom styles
Separate your components in a proper folder, i.e: ./assets/styles:
import { makeStyles } from '#material-ui/core/styles';
export const useCheckBoxStyles = makeStyles((theme) => ({
root: {
color: theme.status.danger,
'&$checked': {
color: theme.status.danger,
},
},
checked: {},
}));
And your components tree ./components:
import { useCheckBoxStyles } from './assets/styles';
function CustomCheckbox() {
const classes = useCheckBoxStyles();
return (
<Checkbox
defaultChecked
classes={{
root: classes.root,
checked: classes.checked,
}}
/>
);
}
References
https://material-ui.com/customization/theming

Change onHover colour of TextField Material-UI v1

I m unable to change the onHover color of the TextField by overriding the classname. How can I do that?
I'm using material UI v1: https://github.com/callemall/material-ui/tree/v1-beta
Overriding with classes didn't help.
It worked by overriding MUIclass in createMuiTheme as below.
const theme = createMuiTheme({
overrides: {
MuiInput: {
underline: {
'&:hover:not($disabled):before': {
backgroundColor: 'rgba(0, 188, 212, 0.7)',
},
},
},
},
});
TextField is implemented using the Input component, which exposes a class named underline as part of its CSS API. Here is the the current definition of this class from the Input source:
underline: {
paddingBottom: 2,
'&:before': {
backgroundColor: theme.palette.input.bottomLine,
left: 0,
bottom: 0,
// Doing the other way around crash on IE11 "''" https://github.com/cssinjs/jss/issues/242
content: '""',
height: 1,
position: 'absolute',
right: 0,
transition: theme.transitions.create('backgroundColor', {
duration: theme.transitions.duration.shorter,
easing: theme.transitions.easing.ease,
}),
},
'&:hover:not($disabled):before': {
backgroundColor: theme.palette.text.primary,
height: 2,
},
'&$disabled:before': {
background: 'transparent',
backgroundImage: `linear-gradient(to right, ${theme.palette.input
.bottomLine} 33%, transparent 0%)`,
backgroundPosition: 'left top',
backgroundRepeat: 'repeat-x',
backgroundSize: '5px 1px',
},
},
To override the Input's classes, you need to pass them through the TextField using its InputProps property. Here is an example where I'm changing the color of the underline to green:
// define a class that will be used to modify the underline class
const styleSheet = createStyleSheet(theme => ({
greenUnderline: {
'&:before': {
backgroundColor: '#0f0',
},
},
}));
Override the Input's underline class via the TextField's InputProps:
<TextField
id="uncontrolled"
label="Uncontrolled"
defaultValue="foo"
className={classes.textField}
margin="normal"
InputProps={{ classes: { underline: classes.greenUnderline } }}
/>
This may not be exactly what you're looking to do, but it should get you started.
this worked for me:
export const theme = createMuiTheme({
overrides:{
MuiFilledInput:{
root:{
"&:hover": {
backgroundColor: '#5dc2a6',
}
}
}
});