React / Material-UI: Use variable reference in custom theme - reactjs

Is there a way in Material-UI (React) to use a reference in a custom theme to a variable defined in the same theme? For example, the component MuiBottomNavigation should use the primary color (main) as background.
import { createTheme, useTheme } from '#mui/material/styles';
const theme = createTheme({
palette: {
primary: {
main: '#f6b1b2'
}
},
components: {
MuiBottomNavigation: {
styleOverrides: {
root: {
// This is not working
backgroundColor: {palette.primary.main}
},
}
}
}
});

You can achieve this by creating several themes and then merging them into one:
// Define all your default styles
const themeBase = createTheme({
palette: {
primary: {
main: "#f6b1b2"
}
}
});
// Define all your component styles
const themeComponents = createTheme({
components: {
MuiBottomNavigation: {
styleOverrides: {
root: {
backgroundColor: themeBase.palette.primary.main
},
}
}
}
});
const theme = createTheme({
...themeBase,
components: themeComponents.components,
});
Of course, you wouldn't need to create an extra theme for the components. You could also just insert them into the final theme.

No, you can't. there is no such API to access the theme when you define it. So something like this wouldn't work
styleOverrides: {
root: {
backgroundColor: theme => theme.palette.primary.main
},
}
To workaround this you can put the commonly shared value into a variable and reference it:
const primaryMain = '#f6b1b2';
const theme = createTheme({
palette: {
primary: {
main: primaryMain,
}
},
components: {
MuiBottomNavigation: {
styleOverrides: {
root: {
backgroundColor: primaryMain,
}
}
}
}
});
If you only need to access a default theme variable, you can create one and reference it like this:
const defaultTheme = createTheme();
const theme = createTheme({
components: {
MuiBottomNavigation: {
styleOverrides: {
root: {
backgroundColor: defaultTheme.palette.primary.main,
}
}
}
}
});

Related

Using the theme context "Material UI 5" React

I Try To Change the default Theme In Material UI By Using createTheme:
I Follow Material UI Dec. (Using Typescript):
import { makeStyles } from '#mui/styles';
import { createTheme, ThemeProvider } from '#mui/material/styles';
const theme = createTheme({
palette: {
primary: {
light: '#d2d8de',
main: '#00a1a6',
dark: '#5c6b77',
contrastText: '#313944',
},
},
typography: {
fontSize: 12
},
});
const useStyles = makeStyles((theme) => ({
root: {
color: theme.palette.primary.main,
}
}));
const App = (props) => {
const classes = useStyles();
return <ThemeProvider theme={theme}><div {...props} className={classes.root}></ThemeProvider>;
}
Typography It's Work As Default But If I use theme is an empty object;
It's Show Error:
TypeError: Cannot read properties of undefined (reading 'primary')
Note: your theme provider will pass theme to your wrapped child components only. So if you are calling theme outside theme provider it will not be accessible.
So you need to wrap styling inside child component
Also pass options for your new theme, its empty.
You need to pass somehting like this, example :
const theme = createTheme({
palette: {
primary: {
main: purple[500],
},
secondary: {
main: green[500],
},
},
});
return (
<ThemeProvider theme={theme}>
<ChildComponent />
</ThemeProvider>
);
ChildComponent
const useStyles = makeStyles(theme => ({
...theme
}));
const ChildComponent = () => {
const classes = useStyles();
return //some dom elements using classes
}
Please check - https://mui.com/customization/theming/#createtheme-options-args-theme

Material UI Button Returning an error when using creatMuiTheme

Why is this returning an error?
const btn = createMuiTheme({Button: {borderRadius: 100%},});
You have to change the Button to MuiButton.
Refer this link. https://mui.com/customization/theme-components/#css
const theme = createTheme({
components: {
// Name of the component
MuiButton: {
styleOverrides: {
// Name of the slot
root: {
// Some CSS
borderRadius: '100%'
},
},
},
},
});

How to use 'overrides' theme when using seed prefix with createGenerateClassName in Material ui

We are extending material ui theme, but when doing :
const theme = createMuiTheme({
overrides: { MuiOutlinedInput: { root: { backgroundColor: 'red' } } },
})
the changes dont apply. We are also using createGenerateClassName:
const generateClassName = createGenerateClassName({
productionPrefix: 'c',
seed: 'corp',
})
So, when taking a look at the html code, I noticed the class MuiOutlinedInput is now corp-MuiOutlinedInput-root, so we decided to use the following override instead:
const theme = createMuiTheme({
overrides: { "corp-MuiOutlinedInput": { root: { backgroundColor: 'red' } } },
})
But it does not work either. Any clue?

Material UI doesn't use overridden styles when using useTheme hook

I'm trying to use custom theming in Material UI like so:
const theme = createMuiTheme({
palette: {
primary: {
main: PRIMARY_COLOR, // "#121212"
},
secondary: {
main: SECONDARY_COLOR, // "#F7D600"
},
},
});
const Wrapper = ({ children }) => {
return (
<ThemeProvider theme={theme}>{children}</ThemeProvider>
);
};
This works for things like buttons:
<Button
variant="contained"
color="secondary"
/>
In this case, the hex color #F7D600 gets applied.
But when I try to use the same color on my components using makeStyles, it doesn't seem to recognize it. It just uses the default by Material UI:
const useStyles = makeStyles((theme) => ({
someElement: {
backgroundColor: theme.palette.primary.main // <- not working. it uses the default purple color
}
});
I also tried useTheme but it's the same result:
const SomeComponent = () => {
const theme = useTheme();
return (
<Box style={{ backgroundColor: theme.palette.primary.main }}></Box>
);
}
Any ideas what I could be missing?
I can't see your import statement, but I use MuiThemeProvider. That could be your issue. Everything else looks right to me
import { MuiThemeProvider } from '#material-ui/core';
Use the below style to override any component in material-UI
import { createMuiTheme, colors } from '#material-ui/core'
const theme = createMuiTheme({
palette: {
background: {
dark: '#F4F6F8',
default: colors.common.white,
paper: colors.common.white,
},
primary: {
main: colors.indigo[500],
},
secondary: {
main: colors.indigo[500],
},
text: {
primary: colors.blueGrey[900],
secondary: colors.blueGrey[600],
},
common: {
tableHeader: '#DEF3FA',
},
action: {
oddRowColor: '#def3fa2e',
},
},
zIndex: {
modal: 10010, // override modal zIndex
appBar: 1000, // override Appbar
},
overrides: { 'MTableHeader-header': { root: { width: '143px !important' } } },
})
// use in your component
const StyledTableRow = withStyles((theme) => ({
root: {
'&:nth-of-type(odd)': {
backgroundColor: theme.palette.action.oddRowColor,//defined in theme
},
padding: 'dense',
},
}))(TableRow)
[https://material-ui.com/customization/default-theme/][1]

Alternative to innerTheme when we want to have different primaryTypographyProps

I have a component which has a List customized with ListeItems and Icons and Buttons. I want to use this component in 2 different places. In one place, I set the MuiListItemTextTypography props this way..
const theme = createMuiTheme({
.
.
.
typography: {
useNextVariants: true
body1: {
fontSize: '14px'
}
},
props: {
MuiListItemText: {
primaryTypographyProps: {
variant: "body1"
},
secondaryTypographyProps: {
variant: "body2"
}
}
}
})
But a second component wants the font size to be 12 px, so I did it this way
const innerTheme = createMuiTheme({
typography: {
body1: {
fontSize: '12px'
}
},
props: {
MuiListItemText: {
primaryTypographyProps: {
variant: "body1"
},
secondaryTypographyProps: {
variant: "body1"
}
}
}
});
and wrapped the second component in new Theme
<MuiThemeProvider theme={innerTheme}>
<ListItems itemsList={secondItem}/>
</MuiThemeProvider>
It works fine, but the drawback is that I lose all the styles set in main theme when I wrap it in an inner theme
How can I do this so that I do not lose all that in the first theme.
There is a good example of how to do this here: Nesting the Theme
MuiThemeProvider accepts a function, so you can redefine innerTheme as:
const innerTheme = {
typography: {
body1: {
fontSize: '12px'
}
},
props: {
MuiListItemText: {
primaryTypographyProps: {
variant: "body1"
},
secondaryTypographyProps: {
variant: "body1"
}
}
}
}
And then change your markup to:
<MuiThemeProvider theme={theme => createMuiTheme({...theme, ...innerTheme})}>
<ListItems itemsList={secondItem}/>
</MuiThemeProvider>

Resources