-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[system] Introduce theme scope for using multiple design systems #36664
Conversation
Netlify deploy preview
@material-ui/core: parsed: +0.15% , gzip: +0.21% Bundle size report |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so exciting!
We just discussed the pain of theme merging yesterday and this solution looks awesome! 🎉
packages/mui-joy/src/Box/Box.tsx
Outdated
|
||
const Box = createBox<Theme>({ | ||
identifier: IDENTIFIER, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe call it themeIdentifier
instead of a generic identifier
? Or even shorten it to themeId
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good to me.
For developers calling emotion or styled-components directly, without going through |
I think it should be <0.1%. You have to enable a prop to turn on theme scoping so if this PR is merged, the existing projects will still work as it is before even you use emotion/styled-components directly. It will break once you turn on this feature and you read the theme from emotion: import styled from '@emotion/styled';
const Foo = styled('div')(({ theme }) => ({ color: theme.palette.primary.main }))
<ThemeProvider enableThemeScope>
<Foo /> // Error: cannot read `primary` of undefined
</ThemeProvider However, the fix is easy by changing - import styled from '@emotion/styled';
+ import { styled } from '@mui/material/styles'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we simplify the API and remove the enableThemeScope
prop and just teach developers that if they are using different design systems, they can add our design systems (Material Design and Joy's) under the key THEME_INDENTIFIER
. With this, developers will have the complete control in terms of what should go in which theme - this is basically what you have in Material UI + Chakra UI codesandbox. I find it a bit complex and confusing what exactly will be merged where if the enableThemeScope
prop is used.
@@ -52,14 +52,19 @@ function ThemeProvider(props) { | |||
} | |||
|
|||
const theme = React.useMemo(() => { | |||
const output = outerTheme === null ? localTheme : mergeOuterLocalTheme(outerTheme, localTheme); | |||
let internalTheme = localTheme; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we move this logic inside the ThemeProvider
in @mui/system? This package was created initially only to serve as a common context for @mui/system & @mui/styles, it shouldn't contain anything that is specific to only one of the packages.
if (identifier && typeof localTheme !== 'function') { | ||
internalTheme = localTheme[identifier] || localTheme; | ||
} | ||
const output = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This step is a bit confusing to me. Mainly because we are merging the two themes, regardless of whether we use the identifier
. This means that the theme inside the identifier will have the merged theme from context together with the user-defined theme. As the newly define theme overrides anyway it should be fine, but I am not sure if this is the expected behavior. For e.g. I can access mixins from MD in Joy UI's theme.
Agree, having one way of doing this is better. |
…iple-design-systems
@mnajdova I think it is ready for review. Latest changes:
|
Signed-off-by: Siriwat K <[email protected]>
docs/data/joy/guides/using-joy-ui-and-material-ui/using-joy-ui-and-material-ui.md
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SO EXCITED about this 🎉 Let's ship it!
From reading the guide, it might not be obvious to everyone that they need to upgrade their MUI, especially if they like me installed MUI only a few weeks back because TLDR; if this doesn't work for you, you need to update MUI. |
Good point, thanks for the feedback. I will update the page to include "You need >= v5.12.0" |
@jakub-stastny speaking of this, would you like to submit a PR to add it to the docs? including this as well https://mui.com/material-ui/guides/styled-engine/#theme-scoping |
@siriwatknp let me see if I can manage to find a minute on the weekend. |
Is there a reason why the documentation for this was added to the "Styled engine" page (rather than creating a new doc)? IMO this topic is separate from that of using styled-components in place of Emotion, which is what "Styled engine" is mainly concerned with. I've proposed splitting these into two separate docs in #37774 (as well as changing the name of the original doc to make it more informative). |
Continuation of #31392 (comment)
Problem
The style engine we supports are emotion and styled-components. Both of them use a singleton React context for theming, here is the singleton of emotion. This means if you are using multiple UI libs that uses emotion theming, the theme will override each other in the tree.
Existing workaround
Joy UI provides this guide to use with Material UI by merging themes into one but the feedbacks are not good because the intensive setup and confusion of the merging process.
New Solution
This PR introduces the theme scope for Material UI and Joy UI for using theme together or with other UI libraries that depend on emotion/styled-components.
All you need to do is wrap the theme inside a special identifier that the library use.
All of these user facing APIs (
styled
,sx
,useTheme
,useThemeProps
), basically every APIs that can interact withtheme
will lookup for the special identifier first and return the corresponded theme.This means there is no breaking change and all of the logics will remain the same if
THEME_IDENTIFIER
is not used.Proof that it works
Todos
THEME_ID
export name,$$material
for Material UI and$$joy
for Joy UI.