react material-ui v5 theming doesnt work with storybook - reactjs

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.

Related

React MUI - custom colors in Alert component - Cannot read properties of undefined (reading 'type')

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.

How can i get the context of the MUI theme?

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';

Right way to theme in Material UI components

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/

How to get the label in the material-ui text field to the right?

I'm using material-ui and typescript for my react project (rtl layout) and i don't know how to get the label of text field to the right?
Found a better way without external libraries.
export const theme = createTheme({
components: {
MuiInputLabel: {
styleOverrides: {
root: {
left: 'inherit',
right: '1.75rem',
transformOrigin: 'right',
},
},
},
MuiOutlinedInput: {
styleOverrides: {
notchedOutline: {
textAlign: 'right',
},
},
},
},
})
You need jss-rtl to support rtl for css. This library provides its Provider to support rtl in any library.
import React from "react";
import { create } from "jss";
import rtl from "jss-rtl";
import JssProvider from "react-jss/lib/JssProvider";
import { createGenerateClassName, jssPreset } from "#material-ui/core/styles";
// Configure JSS
const jss = create({ plugins: [...jssPreset().plugins, rtl()] });
// Custom Material-UI class name generator.
const generateClassName = createGenerateClassName();
function RTL(props) {
return (
<JssProvider jss={jss} generateClassName={generateClassName}>
{props.children}
</JssProvider>
);
}
export default RTL;
Then in your main app use this provider.
ReactDOM.render(
<RTL>
<Demo />
</RTL>,
document.querySelector("#root")
);
Working demo here

Material-UI Changing default color

How can I change the default color ?
What is the object I need to modify in the theme.js ?
EDIT
I want to modify the defaut (grey color) who isn't primary or secondary or error.
I came across a similar issue to the OP, specifically I wanted to change the default Button color from grey to white. The question commenters are correct, each component has its own specific styles and colors versus a global default color. These need to be overridden via a custom theme. Below is an example of overriding Button's default class contained, by creating a theme override to change the default button color. CONTANTS is used to define the specific colors, etc.
import React from 'react';
import { createMuiTheme } from '#material-ui/core/styles';
import { ThemeProvider } from '#material-ui/styles';
import * as CONSTANTS from './Constants'
const theme = createMuiTheme({
palette: {
primary: {
// light: will be calculated from palette.primary.main,
main: CONSTANTS.BLUE,
// dark: will be calculated from palette.primary.main,
contrastText: CONSTANTS.CONTRAST_TEXT,
},
},
overrides:{
MuiButton:{
contained:{
color: CONSTANTS.BLUE,
backgroundColor: CONSTANTS.CONTRAST_TEXT,
'&:hover': {
backgroundColor: CONSTANTS.LIGHT_BLUE,
// Reset on touch devices, it doesn't add specificity
'#media (hover: none)': {
backgroundColor: CONSTANTS.CONTRAST_TEXT,
},
}
}
}
}
});
interface IThemeProps{
children:any;
}
export default function Theme(props: IThemeProps) {
return (
<ThemeProvider theme={theme}>
{props.children}
</ThemeProvider>
);
}
And to use the new theme:
import React from 'react';
import Theme from './Theme';
import { Header, Home } from './Components';
const App: React.FC = () => {
return (
<Theme>
<Header>
<Home />
</Header>
</Theme>
);
}
export default App;
const customTheme = createTheme({
components: {
MuiButton: {
styleOverrides: {
outlined: {
color: "red",
},
},
},
},
});
I found on Material UI documentation about overriding the default properties
You need to modify the palette object in the theme.
`palette: {
primary: {
light: palette.primary[300],
main: palette.primary[500],
dark: palette.primary[700],
contrastText: getContrastText(palette.primary[500]),
},
secondary: {
light: palette.secondary.A200,
main: palette.secondary.A400,
dark: palette.secondary.A700,
contrastText: getContrastText(palette.secondary.A400),
},enter code here
error: {
light: palette.error[300],
main: palette.error[500],
dark: palette.error[700],
contrastText: getContrastText(palette.error[500]),
},
},`

Resources