This is how you create a theme and propagate it using MUI.
import { ThemeProvider } from "#mui/material";
const myTheme = createTheme({
backgroundColor: {
primary: "#f9f9fb",
secondary: "#ededf3",
tertiary: "#cbcbdc",
},
})
const Index: FC = () => {
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
};
Now, for some reason, I need to get the context of the MUI theme in my app.
I've search everywhere but it seems that they do not expose the context anywhere. I found 3 contexts in private-theming, styled-engine and styled-engine-sc but none of them worked.
How can I do that ?
The way you create the theme it wrong should be like following:
const theme = createTheme({
palette: {
primary: {
main: red[500],
},
},
});
with the property palette.
and the way to get values you could use the hook useTheme .
first import
import { useTheme } from "#mui/material";
and inside your components you can use the palette you set to your theme like:
const { palette } = useTheme();
MUI uses the context provided by the styled engine:
import { ThemeContext } from '#mui/styled-engine';
It can also be imported directly from your engine of choice (emotion in the example below):
import { ThemeContext } from '#emotion/react';
Related
I'm trying to theme and customize MUI components to align them with our company design, but I stumbled across a problem.
I have defined my custom colors, for some reason we have color "danger" instead of "error".
I was following the documentation https://mui.com/material-ui/customization/palette/#adding-new-colors and everything works great for Button component.
But when I moved on to the Alert component, the same approach doesn't work, and I just simply don't know why. All I'm getting is Uncaught TypeError: Cannot read properties of undefined (reading 'type')
I also tried it to add it to the stackblitz example from the docs page mentioned above but got the same result: https://stackblitz.com/edit/react-z3xjhf?file=demo.tsx
import * as React from 'react';
import { createTheme, ThemeProvider } from '#mui/material/styles';
import Button from '#mui/material/Button';
import Alert from '#mui/material/Alert';
const theme = createTheme({
palette: {
neutral: {
main: '#64748B',
contrastText: '#fff',
},
},
});
declare module '#mui/material/styles' {
interface Palette {
neutral: Palette['primary'];
}
// allow configuration using `createTheme`
interface PaletteOptions {
neutral?: PaletteOptions['primary'];
}
}
// Update the Button's color prop options
declare module '#mui/material/Button' {
interface ButtonPropsColorOverrides {
neutral: true;
}
}
declare module '#mui/material/Alert' {
interface AlertPropsColorOverrides {
neutral: true;
}
}
export default function CustomColor() {
return (
<ThemeProvider theme={theme}>
<Button color="neutral" variant="contained">
neutral
</Button>
<Alert color="neutral">ALERT</Alert>
</ThemeProvider>
);
}
Does anybody have any idea what I'm doing wrong?
You need to add light: '<whatever_your_light_color_hex>' to your theme, too. Like this:
const theme = createTheme({
palette: {
neutral: {
main: '#64748B',
light: '#64748B',
contrastText: '#fff',
},
},
});
This stackblitz is a live working example of this solution.
I'm not sure if this is possible or not, after looking at Material UI's documentation on How to Customize, but I'm trying to isolate styleOverrides for a given component using styled() rather than applying a lot of overrides within a global theme file.
Currently, my theme file looks something like this, with some typography and palette overriding Material UI's default theme:
const theme = createTheme({
palette: { ...
},
typography: { ...
}
});
When I use a Chip component (rendered in Storybook currently) and pass in success, primary, secondary, etc. into the color prop, the corresponding theme colors are applied. However, when I try to override the theme files, using styled(), the colors defined in the theme are still being applied - as opposed to my overrides defined. My component file looks like the following:
import { styled } from '#mui/material/styles';
import MuiChip, { ChipProps } from '#mui/material/Chip';
const Chip = styled(MuiChip)<ChipProps>(({ theme }) => ({
colorPrimary: {
backgroundColor: theme.palette.primary.light
},
colorSecondary: {
backgroundColor: theme.palette.secondary.light
}
}));
export default Chip;
You can create your own custom variant and define your own styles to it
const theme = createTheme ({
components : {
MuiButton : {
variants : [
{ props : { variant : 'YouVarName'},
style: { //..your styles } ,
},},
From the Material UI website, there seem to be multiple ways of theming, and I'm not sure which to use.
There's this method, which just seems to use pure React context. However, I don't see how main relates to the color. I'm not sure how it is a field that Checkbox is able to extract from, given we don't specify it in the HTML.
import * as React from 'react';
import { createTheme, ThemeProvider } from '#mui/material/styles';
import Checkbox from '#mui/material/Checkbox';
import { green, orange } from '#mui/material/colors';
const outerTheme = createTheme({
palette: {
primary: {
main: orange[500],
},
},
});
const innerTheme = createTheme({
palette: {
primary: {
main: green[500],
},
},
});
export default function ThemeNesting() {
return (
<ThemeProvider theme={outerTheme}>
<Checkbox defaultChecked />
<ThemeProvider theme={innerTheme}>
<Checkbox defaultChecked />
</ThemeProvider>
</ThemeProvider>
);
}
There's this method, which seems to make more sense. Here we explicitly extract the theme color via theme.status.danger and place it into the color field.
import * as React from 'react';
import Checkbox from '#mui/material/Checkbox';
import { createTheme, ThemeProvider, styled } from '#mui/material/styles';
import { orange } from '#mui/material/colors';
declare module '#mui/material/styles' {
interface Theme {
status: {
danger: string;
};
}
// allow configuration using `createTheme`
interface ThemeOptions {
status?: {
danger?: string;
};
}
}
const CustomCheckbox = styled(Checkbox)(({ theme }) => ({
color: theme.status.danger,
'&.Mui-checked': {
color: theme.status.danger,
},
}));
const theme = createTheme({
status: {
danger: orange[500],
},
});
export default function CustomStyles() {
return (
<ThemeProvider theme={theme}>
<CustomCheckbox defaultChecked />
</ThemeProvider>
);
}
I could also change the MUI nested component:
import * as React from 'react';
import { ThemeProvider, createTheme } from '#mui/material/styles';
import Button from '#mui/material/Button';
const theme = createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
fontSize: '1rem',
},
},
},
},
});
export default function GlobalThemeOverride() {
return (
<ThemeProvider theme={theme}>
<Button>font-size: 1rem</Button>
</ThemeProvider>
);
}
Which is the right way to theme?
Good evening, I've recently started using UI stuff and from what I've seen in version 5, the theme as you mentioned is used. Another way I'm styling it is using the SX props on the element.
https://mui.com/pt/system/the-sx-prop/
I spend a few days trying to customize the primary color and add two more colors to the palette. I was able to declare properly the new colors...but at the moment to see those new colors reflected on the button doesnt work. The button are taking the default properties even when I wrapped under the Themeprovider. I'm using storybook.
import React from "react";
import { Meta } from "#storybook/react/types-6-0";
import { Button } from "#mui/material";
import { createTheme, ThemeProvider, styled } from '#mui/material/styles';
const theme = createTheme({
palette: {
primary: {
contrastText: "#ff0000",
light: "#ff0000",
main: "#ff0000",
dark: "#ff0000"
},
tertiary: {
main: "#ff0000"
},
failure: {
main: "#ff0000"
}
}
});
const CustomStyles = () => {
return (
<ThemeProvider theme={theme}>
<Button variant="contained">Click me</Button>
</ThemeProvider>
);
}
const Template = () => {
return (
<CustomStyles />
);
};
export const Default = Template.bind({});
export default {
title: "mylib/Theme"
} as Meta;
This is how it looks
default button style
Themeprovider custom palette
As you may see, the ThemeProvider has the palette color definition...but some how the button doesnt take it.
Thanks in advance
Adding this to.storybook/preview.js was enough to solve my case. Follow the official migration guide on this matter to learn more.
//.storybook/preview.js
import { ThemeProvider } from '#mui/material/styles';
import { ThemeProvider as Emotion10ThemeProvider } from 'emotion-theming';
import { theme } from '../your/system/customTheme/path';
const defaultTheme = theme;
const withThemeProvider = (Story, context) => {
return (
<Emotion10ThemeProvider theme={defaultTheme}>
<ThemeProvider theme={defaultTheme}>
<Story {...context} />
</ThemeProvider>
</Emotion10ThemeProvider>
);
};
export const decorators = [withThemeProvider];
//another storybook exports.
EDIT: this issue seems to be related to stackoverflow.com/a/70254078/17724218 as OP commented below.
I am struggling to change the font family on Material-UI. I am trying to set it for the whole project using MuiTheme. How can I do this using a font from Google Fonts?
Someone did this in another topic
import { createMuiTheme } from 'material-ui/styles';
import createPalette from 'material-ui/styles/palette';
import createTypography from 'material-ui/styles/typography';
const theme = createMuiTheme({
typography: createTypography(createPalette(), {
fontFamily: '"Comic Sans"',
})
});
class App extends Component {
render() {
return (
<MuiThemeProvider theme={theme}>