#How would I deep merge two MantineThemes?
70 messages · Page 1 of 1 (latest)
are these custom themes you've made?
Ehm, if I understand correctly, then yes. The idea is to provide an interface for users to provide their own theme, while providing a default theme.
*creating our own library on top of mantine
you could possibly use Object.assign() to copy the user themes over the original theme object
you might need nested copying, there's some solutions for that
Hm, I was wondering, if there is an interface or an approach that you use internally.
this is the interface definition
Look at this: https://mantine.dev/theming/mantine-provider/ under Nested MantineProviders. Aren't you essentially doing the same here?
Or is this only a shallow merge? I can look into it myself though.
yes, that is one way of doing it
your outermost mantineprovider can be the default theme
you can then have an inner mantineprovider that provides overrides
yes, exactly here: https://github.dev/mantinedev/mantine under src/mantine-styles/src/theme/utils/merge-theme
this doesn't seem to be exposed
This won't be exposed I guess? I could copy paste the code...
it is exposed
but, you likely do not need to do it this way
you could simply follow this
have an outermost provider with default theme, then an innermost provider with overrides
If I look into the code, what it does is a shallow copy, no?
const mergedTheme = mergeThemeWithFunctions(
DEFAULT_THEME,
inherit ? { ...ctx.theme, ...theme } : theme
);
the full implementation of the merge is defined here
The deep merge is used with the internal DEFAULT_THEME
DEFAULT_THEME is the base of all themes, yes
Yes, what you suggested regarding inherit only works with shallow copy. Meaning, if there is a theme on the child, it will shallow copy it.
i do not follow
your use case seems to be that you want a base theme, and secondary theme options that override it
yes, DEFAULT_THEME is the base of all themes
but that is overlooking the line immediately below it
inherit ? { ...ctx.theme, ...theme } : theme
which is saying
if inherit is set to true, merge the theme context with whatever theme params are provided
I can only repeat, it is a shallow merge*.
I have to use mergeThemeWithFunctions which is not exposed
In other words, if I have a theme and now another otherTheme is provided, what inherit essentially does is a shallow merge of the both. Meaning, if there is a components property on otherTheme with a nested object, let's say Tooltip: {styles: ....}, this will override ALL components in theme, right?
This is what I want to avoid, but rather merge Tooltip: { styles: ...} into the existing theme. Not overwrite components....
Do you know what I mean? Might be I'm not clear enough 🤐
I just had a look into the merge-theme module. This covers only one level of nesting:
acc[key] =
typeof themeOverride[key] === 'object'
? { ...currentTheme[key], ...themeOverride[key] }
: typeof themeOverride[key] === 'number' || typeof themeOverride[key] === 'boolean'
? themeOverride[key]
: themeOverride[key] || currentTheme[key];
return acc;
The key part being: typeof themeOverride[key] === 'object' ? { ...currentTheme[key], ...themeOverride[key] }
You could use something like lodash mergeWith and a customizer to override how it handles arrays specifically (it merges arrays instead of overriding)
I'm trying to replace arrays of an old object with values from a new object which has arrays... I guess it will make sense when you see an example and desire result:
https://jsfiddle.net/redlive/9c...
You don't need all of lodash either. You can install each function as a separate module. lodash.mergewith
Basically you have 3 themes, Default Mantine Theme, Your Base App Theme, User Defined Theme is that it?
I think you could just merge your Base App Theme + User Defined Theme at MantineProvider level, with something like mantine internal mergeThemeWithFunctions, immutability helper, or something similar
Thank you, the question was rather, if there is an existing approach. Merging two nested objects in js is a rather general problem, that I have an idea of solving. I jsut wanted to leverage something that exists, if it exists...
A little bit above, I mentioned two things regarging mergeThemeWithFunctions :
-
It only merges one level deep (which can be fine I guess)
-
It isn't exposed. Was I wrong? If so, can you tell me, which package exposes it? Like how would the import statement look?
isn't that just
theme={{ { // custom theme }, ...DEFAULT_THEME }}?
it will fill in the missing things a user might not provide
or missing peaces
I use this lib for deep merging in typescript
https://www.npmjs.com/package/ts-deepmerge
It works well for merging theme data together.
I've created some MUI projects (similar themeing) where I broke up the theme into sections. Colors, typography, components, etc... along with dark and light adjustments and then just merged to the final.
It can help with a larger team on some organization and reduce git conflicts.
@final bronze 👆
If you read above, the approach is the other way around. There is already a theme and the user should be able to provide his own theme. What you suggest is, as I mentioned above, a shallow copy, which might overwrite too much...
One could delegate the problem to the developer, but that is what I want to avoid. It adds a complexity layer, which imo leads to bad developer experience.
Thank you for the insight. I'll go with a similar approach.
How often in your code are you doing this that you need improved DX over something like lodash mergeWith or just rolling your own function to deep merge? Even then you just end up w/ your own function that is deepMerge and then you've matched the dev experience of it being baked into Mantine
Regarding your question: It feels like you understood, that I want to go with my own deepMerge implementation which will provide a better user experience than lodash's deepMerge. I don't know where I said something like that?
We could discuss, what I would do in detail, but that is unrelated to the initial question, which literally is asking if there is a simple(suggested) way/exisiting api to do it.
Regarding the rest, i don't quite understand what you are saying. You mean deeply merging won't give me any benefits over the functionality mantine provides (baked in)? What functionality provided by mantine* are you talking about?
@ember hare friendly ping: What functionality provided by mantine are you talking about?
I think his point was just that why would you need a deepMerge function with improved functionality (in this case, better TS support) over just using lodash' or a self-written one.
Either way this thread seems extremely long for what should've just been a simple answer:
Use a utility function that does it for you, whether that be from lodash, or ts-deepmerge or something else, it doesn't matter
yup