'How do I extend the color palette from mui with Typescript
I'm trying to extend the color palette that mui provides. The overriding of primary, secondary etc colors works well but if I want to create a custom set of colors just after, I can't figure out how to make it works. There are plenty of examples without typescript but when this guy comes into the game it makes it trickier. Let's say I have this:
theme.tsx
palette: {
primary: {...}, // override works
custom: {
main: 'color',
dark: 'color1',
light: 'color2',
contrastText: 'color3'
}
}
from what mui document says, I should use module augmentation:
declare module "@material-ui/core/styles/createPalette" {
interface Palette {
custom: Palette['primary'];
}
interface PaletteOptions {
custom: PaletteOptions['primary'];
}
}
Nothing is yelling, but when I use it for a Box component for example, it doesn't work (others like primary.dark works well). It's been several days that I'm trying to find out how to do this, but I have to say I'm out of knowledge there.
I'd appreciate some help! Thanks! :)
Ps: Someone already posted the same question but it didn't help me here
Solution 1:[1]
As others mentioned, the documentation shows how to add a color to the theme interface, but not for the color property of components. I think I found a proper solution in the source code. This example is using Material UI 5, so I'm not sure if it works in 4, and I couldn't find any official docs on it.
In my example, the Chip component exports several interfaces which you can extend with declaration merging. The following code should allow you to set the color of a chip to "facebook" or "twitter"
// define custom colors: https://material-ui.com/customization/palette/
declare module '@mui/material/styles/createPalette' {
interface Palette {
facebook: Palette['primary'];
twitter: Palette['primary'];
}
interface PaletteOptions {
facebook: PaletteOptions['primary'];
twitter: PaletteOptions['primary'];
}
}
// Extend color prop on components
declare module '@mui/material/Chip' {
export interface ChipPropsColorOverrides {
facebook: true
twitter: true
}
}
Solution 2:[2]
From looking at the source code, you should be using:
declare module "@material-ui/core/styles/createPalette" {
interface Palette {
custom: PaletteColorOptions;
}
interface PaletteOptions {
custom: PaletteColorOptions;
}
}
I'm not sure why this is documented like that though.
Solution 3:[3]
This is from my current project. I reuse the primary type.
declare module '@material-ui/core/styles/createPalette' {
interface Palette {
magic: Palette['primary'];
}
interface PaletteOptions {
magic: PaletteOptions['primary'];
}
}
export const Theme = createMuiTheme({
palette: {
magic: { main: '#1a1a1a' },
}
})
Solution 4:[4]
MUI 5
This is the approach I took for extending the palette in MUI 5.
You can remove the extends
however you still need to import the Palette
and PaletteOptions
without the aliases. This might cause some issues with the linter, though (unused imports).
To avoid any gross eslint disable
stuff, I just overwrote the types and extended them with the existing types by importing them under an alias.
import {
Palette as MuiPallete,
PaletteOptions as MuiPaletteOptions,
} from '@mui/material/styles/createPalette';
declare module '@mui/material/styles/createPalette' {
interface Palette extends MuiPallete {
neutralShade: {main: string};
}
interface PaletteOptions extends MuiPaletteOptions {
neutralShade?: {main: string};
}
}
No idea if there is a better way but this seemed the cleanest to me.
Solution 5:[5]
You can extend it like this
import { Color, Palette, PaletteOptions } from '@mui/material';
export interface MyGrey extends Color {
custom: string;
}
export const myGrey: MyGrey = {
custom:'#FFFFFF'
}
interface MyPaletteExtensions {
myGrey: MyGrey;
}
declare module '@mui/material/styles' {
interface Palette extends MyPaletteExtensions {}
interface PaletteOptions extends MyPaletteExtensions {}
}
export const myPalette: PaletteOptions = {
primary: {
light: '#FFFFFF',
main: '#FFFFFF',
dark: '#FFFFFF',
},
secondary: {
light: '#FFFFFF',
main: '#FFFFFF',
},
myGrey,
};
This will then allow
theme.palette.myGrey.custom
One thing to bear in mind with the above approach you can't extend the default palette keys e.g grey
it must be a custom name had we done theme.palette.grey.custom
this would work but give a TS error.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Chris |
Solution 3 | japrescott |
Solution 4 | Steve |
Solution 5 | Joel Davey |