Creating a defaultProps with createTheme in MUI v5 not working - reactjs

I'm using Material-UI v5 for the first time, and I want to create a custom theme with createTheme to style a button component. According to the documentation:
The theme's components key allows you to customize a component without wrapping it in another component. You can change the styles, the default props, and more.
They provide a code example:
const theme = createTheme({
components: {
// Name of the component
MuiButtonBase: {
defaultProps: {
// The props to change the default for.
disableRipple: true, // No more ripple!
},
},
},
});
But when I try to implement it there doesn't seem to be a components key with the createTheme. I get the following error:
Argument of type '{ components: any; }' is not assignable to parameter of type 'ThemeOptions'.
Object literal may only specify known properties, and 'components' does not exist in type 'ThemeOptions'
What might be the problem here?

You're using MUI v5, but you import createTheme from v4, which doesn't have the components property in createTheme, so change the import path to:
import { createTheme } from "#mui/material/styles";
From:
import { createTheme } from "#material-ui/core";

Related

Typescript styled component "The type of this node cannot be serialized because its property '[$$PropertyValue]' cannot be serialized"

I am building a server-side rendered website using NextJS, TypeScript and the Stitches CSS library.
When using Stitches styled function to create styled components I get this lint error:
The type of this node cannot be serialized because its property '[$$PropertyValue]' cannot be serialized.ts(4118)
Here is part of my stitches.config file:
// ...
export const {
styled, // using this to create styled components
css,
theme,
createTheme,
globalCss,
} = createStitches({
theme: {
colors: {
...gray,
...mauve,
}
}
})
Here is one of the component files that has the lint error:
import { styled } from "../stitches.config"
// Lint error on button: The type of this node cannot be serialized because its property '[$$PropertyValue]' cannot be serialized.ts(4118)
export const Button = styled('button', {
backgroundColor: '$gray',
color: '$mauve',
})
Using import { styled } from "#stitches/react" instead removes the lint error but then I can't use custom styles defined in stitches.config
Any help or info about what this error means would appreciated. Thanks
There's currently an issue with ui-stitches and typescript 4.8. Downgrade to 4.7
https://github.com/stitchesjs/stitches/issues/1078

MUI Override Slider color options with module augmentation

I'm trying to solve a typescript error regarding the chosen color on my slider component:
<Slider
color="brown"
/>
The error is: Type '"brown"' is not assignable to type '"primary" | "secondary" | undefined'.
I have set the brown color on my theme, by augmenting the createPalette file.
declare module '#mui/material/styles/createPalette' {
interface Palette {
brown: PaletteColor
}
interface PaletteOptions {
brown: PaletteColorOptions
}
}
So now that I still have the error I looked in the Slider.d.ts file and found an interface: SliderPropsColorOverrides.
export interface SliderPropsColorOverrides {}
...
color?: OverridableStringUnion<'primary' | 'secondary', SliderPropsColorOverrides>;
I try to merge it with my brown color:
declare module '#mui/material/Slider' {
interface SliderPropsColorOverrides {
darkest_blue: PaletteColorOptions
}
}
But with no luck. Either my IDE (PhpStorm 2021.3) isn't compiling the new typescript code, or I'm missing something.
You were very close to something that would work, but the value for the augmentation of SliderPropsColorOverrides should just be true rather than PaletteColorOptions.
In my example sandbox I have the following key pieces:
createPalette.d.ts
import "#mui/material/styles/createPalette";
declare module "#mui/material/styles/createPalette" {
interface Palette {
brown: PaletteColor;
}
interface PaletteOptions {
brown: PaletteColorOptions;
}
}
Slider.d.ts
import "#mui/material/Slider";
declare module "#mui/material/Slider" {
interface SliderPropsColorOverrides {
brown: true;
}
}
There was one other problem that I addressed in a rather ugly fashion. The Slider prop-types were still causing a runtime validation message for the color prop. I found comments in some open issues about color customization that mention this prop-types aspect and I suspect it will eventually be addressed by MUI, but it might not be addressed for a while. In my sandbox, I work around this by creating a SliderPropTypesOverride.ts file in which I copied MUI's SliderRoot.propTypes.ownerState and then modified the color portion to include "brown". This copying of the prop-types definitely isn't ideal from a maintenance standpoint, but at the moment I don't see another way to address the runtime warning in dev mode.
Then this all gets used as follows:
demo.tsx
import React from "react";
import { createTheme, ThemeProvider } from "#mui/material/styles";
import "./SliderPropTypesOverride";
import Slider from "#mui/material/Slider";
const defaultTheme = createTheme();
const theme = createTheme({
palette: {
brown: defaultTheme.palette.augmentColor({
color: {
main: "#A52A2A"
},
name: "brown"
})
}
});
export default function Demo() {
return (
<ThemeProvider theme={theme}>
<Slider color="brown" />
</ThemeProvider>
);
}
Related answers:
Typescript Module augmentation is not working: Property 'main' does not exist on type 'PaletteColorOptions'
How to add custom colors name on Material UI with TypeScript?
I would review the documentation on this.
https://mui.com/customization/palette/
It doesn't seem that you're able to override the color of the component directly and instead (if you have one) need to create a global theme object with the appropriate declaration files in order to override the color.
Also see this answer:
Extending the color palette with TS

Typescript error says property does not exist on type

Note! I have managed to mitigate the problem by using "theme: any" in the below declaration but I would prefer a better approach.
I am using React (v17.0.2) for front-end with material-ui (v5.0.0) and I get the following error:
Property 'palette' does not exist on type 'Theme'.
whenever I try to access my theme like so:
import { useTheme } from '#emotion/react';
export default function MyComponent() {
const theme = useTheme()
return (
<Box
sx={{
backgroundColor: theme.palette.mode === 'dark' ? 'primary.dark' : 'primary',
}}
></Box>
);
}
I logged the object with console.log(theme) underneath the declaration, and it logged my theme succesfully. So it is there but I cannot access it like shown above.
Here is some of what was logged:
{breakpoints: {…}, direction: 'ltr', components: {…}, palette: {…}, spacing: ƒ, …}
> breakpoints: {keys: Array(5), ...}
> components: {MuiTypography: {…}, ...}
direction: "ltr"
> mixins: {toolbar: {...}}
> palette: {mode: 'dark', ...}
...
Also, I found the file where the type "Theme" is located and the property "palette" definitely exists. Here is a snippet of the file:
export interface Theme extends SystemTheme {
mixins: Mixins;
components?: Components;
palette: Palette;
shadows: Shadows;
transitions: Transitions;
typography: Typography;
zIndex: ZIndex;
unstable_strictMode?: boolean;
}
I also tried importing and using Theme like so:
import { Theme } from '#mui/material/styles';
...
const theme: Theme = useTheme()
...
And this gave me a new error ( underlining the "theme" variable ):
Type 'Theme' is missing the following properties from type 'Theme': mixins, palette, shadows, transitions, and 6 more.
I tried like this too:
import { Theme } from '#mui/material/styles';
...
const theme = useTheme<Theme>()
...
And this gave me a new error ( underlining "Theme" in useTheme<Theme>() )
Expected 0 type arguments, but got 1.
and also
Property 'palette' does not exist on type 'Theme'.
I am new to typescript, so any help is appreciated.
EDIT
Got the answer thanks to Alex Wayne (and maybe also windowsill if I initially misunderstood the answer). Here's the code that worked:
import { useTheme, Theme } from '#mui/material';
const theme: Theme = useTheme()
<Box sx={{backgroundColor: theme.palette.mode}}></Box>
In order to get proper type checks you can extend emotion Theme interface with MUI's.
import { Theme as MuiTheme } from "#mui/material/styles";
declare module '#emotion/react' {
export interface Theme extends MuiTheme {}
}
As specified in
https://emotion.sh/docs/typescript#define-a-theme
#emotion/react exports a Theme type, returned by useTheme() from the same package.
#mui/material/styles exports a Theme type, returned by createTheme from the same package.
These are not the same type.
They have the same name in each package, but are completely unrelated.
This is why this fails:
import { useTheme } from '#emotion/react';
import { Theme } from '#mui/material/styles';
const theme: Theme = useTheme()
// Type 'Theme' is missing the following properties from type 'Theme': mixins, palette, shadows, transitions, and 2 more.(2740)
Playground
But this succeeds.
import { useTheme, Theme } from '#emotion/react';
const theme: Theme = useTheme()
Playground
I don't know exactly which one you intend to use, but here are the docs on emotion themes and here are the docs on Material UI themes. They are separate things, and you need to use each according to their intended use.

How to use react-admin with material ui version 5

How to use react-admin with Material UI version 5. Is it possible to make it independent from material ui 4?
You'll need to use the latest theme and the legacy theme. The legacy theme should be set on the Admin component and the latest theme should be set via the ThemeProvider.
MUI v5 and MUI v4.x aren't that different in terms of the basic default theme. Given some things have been moved around and one or two keys removed. You can create an object to be the global theme (containing the typography, palette, breakpoints, etc if you customize these values).
A key difference in v5.x and v4.x is how style overrides and default props for components are defined. You will need to create a function to loop over all themeV5.components and grab the values in defaultProps and styleOverrides and assign them under the themeV4.props and themeV4.overrides.
import { ThemeProvider } from '#mui/material/styles';
import { createTheme } from '#mui/material/styles';
import { createTheme as createThemeV4 } from '#material-ui/core/styles';
const theme = {
sidebar: {...},
palette: {...},
typography: {...},
}
let latestTheme = createTheme({
...theme,
components: {},
});
let legacyTheme = createThemeV4({
...theme,
overrides: {},
props: {},
});
<ThemeProvider theme={latestTheme}>
<Admin
title={APP_NAME}
authProvider={authProvider}
dataProvider={dataProvider}
i18nProvider={i18nProvider}
history={history}
theme={legacyTheme}
>
{resources}
</Admin>
</ThemeProvider>
Looks like the next major version (4) of React-Admin adds support for MUI v5

What is the preferred way to theme a composed component using styled-components?

Can anyone recommend the best way to compose styled-components that need to be themed?
Here's my code: https://gist.github.com/aaronmcadam/7bfd63a6bc4cfc36f9947a449c6f494a.
I have an Avatar component which composes an Image component, which is itself a styled-component.
If I use Avatar.styled.js with <ThemeProvider>, the theme can be successfully overridden.
If I use Avatar.withTheme.js, the theme can only be overridden if I use withTheme.
Which is the preferred way of doing things like these?
from the official docs: https://github.com/styled-components/styled-components/blob/master/docs/theming.md
We export a component that takes a theme prop. The
theme you provide there is injected into your styled components via
props.theme
If you ever need to get the current theme outside styled components
(e.g. inside big components), you can use the withTheme Higher Order
Component
import { withTheme } from 'styled-components'
class MyComponent extends React.Component {
render() {
const { theme } = this.props
console.log('Current theme: ', theme);
// ...
}
}
export default withTheme(MyComponent)

Resources