I have a classic atoms/molecules/organisms monorepo with storybooks in order to create a custom components library. At the same time, such a library is based on MUI which has applied a custom theme. All of this is built with TypeScript.
I decided to base our library on MUI because it could be easier and faster for us to develop our custom components, but while I'm saving time on making them I'm putting the rest of my time trying to fix issues with the built :(
The theme
On atoms repo I have added our custom theme json which is imported by other repos (molecules and organisms) and it also gets exported as part of the atom's library and can be applied on an external project.
It uses a basic MUI as a base theme, which has been updated with some branding changes and also some custom colours (here is the problem). To make those custom colours available I have created a createPalette.d.ts file on the same Theme/ folder to declare the additions:
import '@mui/material/styles';
declare module '@mui/material/styles' {
interface Palette {
myColor: Palette['primary'];
}
interface PaletteOptions {
myColor?: PaletteOptions['primary'];
}
}
// Updated Button's props so it allows the color
declare module '@mui/material/Button' {
interface ButtonPropsColorOverrides {
myColor: true;
}
}
The them is then applied to each repo's .storybook/preview.js file like follows:
import { ThemeProvider as MUIThemeProvider, createTheme } from '@mui/material/styles';
import { ThemeProvider } from 'emotion-theming';
import theme from '../stories/Theme';
import { withThemes } from '@react-theming/storybook-addon';
const providerFn = ({ theme, children }) => {
// this fixes some issues between emotion and mui theming
const serialTheme = JSON.parse(JSON.stringify(theme));
const muiTheme = createTheme(serialTheme);
return (
<MUIThemeProvider theme={muiTheme}>
<ThemeProvider theme={muiTheme}>{children}</ThemeProvider>
</MUIThemeProvider>
);
};
const themingDecorator = withThemes(null, [theme], {
providerFn,
});
export const decorators = [themingDecorator];
And it all works just fine. I can make use of the MUI components and my theme easily. Well, not exactly....
The problem
While I can access the theme from any other repo, it seems to fail to find the custom colours declaration and therefore every time I try to use something like theme.palette.myColor.main (as per our sample above) I get a
Property 'myColor' does not exist on type 'Palette'.ts(2339)
I have found out that, obviously, if I just replicate createPalette.d.ts on, let's say, molecules repo, it doesn't complain when I use it and also it autocomplete it with its main, dark, light... options. However, it does still through an error on 'build':
stories/ComponentFolder/index.tsx: error TS2339: Property 'myColor' does not exist on type 'Palette'.
My thoughts
- What I think would be the most obvious solution is to import/extend
createPalette.d.tson any other repo but I don't seem to find a way of doing so, but also then there is the problem when building. - I'm not convinced this will work if I import the theme on any other project because maybe it would complain again about the property not existing on type 'Palette'.
- I might as well just be doing this all wrong and the Theme should be stored and applied in a different way. What would be the best approach for something like this?
Notes
I'm also exporting the Theme as part of my library because I have also not been able to find a way of building and publishing my library with my theme applied. At the moment I am importing it: import theme from '@mylibrary/atoms/lib/Theme' and applying it with <ThemeProvider />. In some way, it's basically the same problem but instead of affecting other repos within my monorepo, it's affecting any other react app that tries to make use of the library.
I really, really hope someone can shed some light on this or share their way of creating something similar, please :D