Closed TamjidAhmed10 closed 1 year ago
I'm working on Mantine 7.0. It will be migrated to native CSS – there won't be any issues related to styles during ssr.
Great to hear this and thank you so much for this awesome progress until today. I absolutely love Mantine.
That is why I would like to know how to be prepared. If I start a project today, would it be enough to omit Emotion styling and use regular classnames instead? Would that make the later migration easier or not really? As soon as your thoughts are ready, let us know.
I feel uncomfortable that some people contributed no single commit to a repo but love to keep convincing the maintainers in an issue thread to do an opinionated thing that they've already said they don't like to do. If you want a solution in your way, you are very welcome to fork this repo or make a peripheral tool yourself. (I appreciate the thoughtful and passionate discussion above but that's too much to me. Just my personal opinion. Sorry.)
I recommend to de-attach those feelings from such discussions because it could give a difficult view on "who is allowed to say something and who is not" and it could lead to "you need to justify why you are allowed to say something".
E.g. I, for myself, can definitely say that I proposed to provide the code contribution to Mantine more than one time but it didn't make it and the reason wasn't the code (we didn't get to that point). I probably have also committed in one or another library that you are already using.
But all that really diverges way too much from the discussion.
What i am reading in all the above is:
As I said above -> I have no doubts whatever is being done in v7 will be good. But discussions like these can bring up tooling proposals or ideas which I think should be beneficial and is in fact a way of contribution.
That feels like a wonderful discussion (people caring) other Libraries would wish for so I would love it if we could treat this like a benefit and not like a burden. What do you think?
As the best UI component library, If possible, I think the separation of style, state and aria could also be considered in v7, like ark, to preserve the possibility of supporting future ecologies such as Solid.
As the best UI component library, If possible, I think the separation of style, state and aria could also be considered in v7, like ark, to preserve the possibility of supporting future ecologies such as Solid.
+1 for Solid, I would love to see support for it!
@rtivital, I fully support you, CSS-in-JS is more of a big problem than any advantage. And switching to vanilla css is a very correct decision. The fewer dependencies there are on various tools, the more stable and predictable your application is.
I've read the discussion but I'm not sure if this surfaced:
Is app dir support waiting on mantine 7?
App dir is already working. @rtivital had provided a working solution which I am in fact using and it's part of this thread. And removing more deps e.g. @emotion will certainly help improving that support (even if it's being potentially a breaking change)
After searching through numerous cases I'd like to share my "current" workaround for Next.js 13 + Mantine + Emotion setup. It seems like working without FOUC/layout shifting for my minimal POC but this might break in certain cases. Please do share your experiences.
Also I've extracted out critical logic into a single hook. You can merge the extracted hook into the 'emotion.tsx' if that's your jam.
// 1. /app/layout.tsx // use relative imports if you have to import EmotionProvider from '$/components/Providers/emotion'; export default function RootLayout({ children }: { children: JSX.Element }) { return ( <html> <head></head> <body> <EmotionProvider> {children} </EmotionProvider> </body> </html> ); } // since layout.tsx & page.tsx is a Server Component you can do... // const metadata : MetaData = { title: 'Awesome Mantine' }; jazz as you wish // 2. /components/Providers/emotion.tsx 'use client'; import { useGluedEmotionCache } from '$/lib/emotionNextjsGlue'; import { CacheProvider } from '@emotion/react'; import { MantineProvider } from '@mantine/core'; export default function EmotionProvider({ children }: { children: JSX.Element }) { const cache = useGluedEmotionCache(); return ( <CacheProvider value={cache}> {/* You can wrap ColorSchemeProvider right here but skipping that for brevity ;) */} <MantineProvider withGlobalStyles withNormalizeCSS emotionCache={cache}> {children} </MantineProvider> </CacheProvider> ); } // 3. /lib/emotionNextjsGlue.tsx import createCache from '@emotion/cache'; import { useServerInsertedHTML } from 'next/navigation'; import { useState } from 'react'; export const useGluedEmotionCache = (key = 'emotion') => { const [cache] = useState(() => { const cache = createCache({ key }); cache.compat = true; return cache; }); useServerInsertedHTML(() => { const entries = Object.entries(cache.inserted); if (entries.length === 0) return null; const names = entries .map(([n]) => n) .filter((n) => typeof n === 'string') .join(' '); const styles = entries.map(([, s]) => s).join('\n'); const emotionKey = `${key} ${names}`; return <style data-emotion={emotionKey} dangerouslySetInnerHTML={{ __html: styles }} />; }); return cache; };
I don't use css=
{...}
prop at the moment but if you set up jsx import source properly to@emotion/react
, css prop works as expected too.Edit: simplified hook a bit
This solution works for preventing the layout shifting, but it seems like theme toggling only kind of works. I am seeing the button styles shift when I toggle, but backgrounds and other text do not.
Has anyone got theme toggling fully working with the above set up?
"use client";
import { CacheProvider } from "@emotion/react";
import { MantineProvider, type MantineThemeOverride } from "@mantine/core";
import { useGluedEmotionCache } from "../lib/emotionNextjsGlue";
import { useHotkeys, useLocalStorage } from "@mantine/hooks";
import darkTheme from "@/themes/darkTheme";
import lightTheme from "@/themes/lightTheme";
export default function EmotionProvider({
children,
}: {
children: JSX.Element;
}) {
const cache = useGluedEmotionCache();
const [theme, setTheme] = useLocalStorage<MantineThemeOverride>({
key: "mantine-color-scheme",
defaultValue: darkTheme,
getInitialValueInEffect: true,
});
const toggleTheme = (value?: MantineThemeOverride) =>
setTheme(value || (theme === lightTheme ? darkTheme : lightTheme));
useHotkeys([["mod+J", () => toggleTheme()]]);
return (
<CacheProvider value={cache}>
<MantineProvider
withGlobalStyles
withNormalizeCSS
emotionCache={cache}
theme={theme}
>
{children}
</MantineProvider>
</CacheProvider>
);
}
The most versatile option is the unstyled UI system. Which provides maximum flexibility and accessibility. For example, radix-ui. It doesn't require any additional settings, you just install and use it. You can use native css or css-in-js or tailwindcss. There are no complex emotion type dependencies. If mantine follows the path of unstyled UI while maintaining its variety of components and functionality, then this will be the best solution.
Additionally, you can offer a stylized version of the components, but this should be as an addition for those who do not want to write styles.
In v7 if you do not want Mantine styles, then simply do not import them in your application and style components from scratch.
Also, font family isn't being changed in app dir. It would be nice if an example is given.
In v7 if you do not want Mantine styles, then simply do not import them in your application and style components from scratch.
When will Mantine 7 be released, I am looking forward to his arrival ❤️
It is hard to tell, you can follow discord to follow development progress
Will the use of emotion/css (createStyle
api) be preserved in v7?
I don't choose to use scss less any css build tool it would make it difficult to handle css styles uniformly in development (e.g. themes, uniform component styles)
I have already refactored most of the components using mantine, so if v7 does not retain the current usage, it will be impossible to upgrade/use the new components in v7.
No, createStyles is not a part of v7, as it relies on emotion. You can continue using 6.x if this feature is important to you.
I also recommend to take a look at panda, which combines the best parts of all the css currently available in terms of design
Linaria is another build time CSS-in-JS compiler. However I haven't used it yet.
@FlatMapIO @cyantree It doesn't make sense for Mantine to replace emotion library with panda or linaria, because doing so would just constitute as replacing one dependency for another. I believe @rtivital would prefer to avoid a similar situation in the future, where a dependency becomes incompatible with the mainstream direction that web development is going in or just becomes abandonware, which would force yet another rewrite of the whole Mantine library. Native CSS isn't going anywhere and that's why it makes much more sense from the perspective of resource consolidation to base Mantine directly onto native CSS.
I got it working based on this issue (emotion-js/emotion#2928) – https://github.com/mantinedev/mantine-next-template/tree/next-13-app/app
Thanks for providing this.
Sorry for my confusion, but what does this mean in terms of SSR/CSR? Does this mean that an app using Mantine is essentially entirely client side rendered, or does it just mean the styles are client side rendered, or something else?
@FlatMapIO @cyantree It doesn't make sense for Mantine to replace emotion library with panda or linaria, because doing so would just constitute as replacing one dependency for another. I believe @rtivital would prefer to avoid a similar situation in the future, where a dependency becomes incompatible with the mainstream direction that web development is going in or just becomes abandonware, which would force yet another rewrite of the whole Mantine library. Native CSS isn't going anywhere and that's why it makes much more sense from the perspective of resource consolidation to base Mantine directly onto native CSS.
I see your point and it's completely valid, but if these tools output native CSS I don't see how could they become incompatible in the future? I just think it could be worth to explore any alternative to keep the createStyles
API since it's such a core feature of Mantine.
There's plenty of people adopting Mantine right now expecting full server components compatibility in the future and when Mantine V7 comes out the overhead of migrating will probably be quite significant for those projects.
@alessandrojcm I would then suggest for those to bite down on something other than their tongue when they have to suffer the torture of migrating from Mantine v6 to v7.
just think it could be worth to explore any alternative to keep the createStyles API since it's such a core feature of Mantine.
You can use these tools in your project, Mantine 7.0 supports any styling solution. Mantine 7.0 is built with CSS modules, but it should not really bother you because in the end you will get a single .css
file that you need to import in your application, so from the user side it is not relevant how Mantine styles are managed.
createStyles
function is a pure css-in-js – it is impossible to implement it the same way with any of the libraries listed above. Also, it adds more complexity to the maintenance of the library – I basically had to maintain a mini css-in-js library. In 7.0 you will get more flexibility in choosing the styling library – you can use styled-components, vanilla extract, linaria, css modules, sass, tailwind, you can even create your own createStyles function with emotion.
There's plenty of people adopting Mantine right now expecting full server components compatibility in the future
That is why I'm working on 7.0 to provide full compatibility with app dir. Note that server components in their current implementation will not be supported by Mantine anyway – all components use useContext
and useState
hooks.
when Mantine V7 comes out the overhead of migrating will probably be quite significant for those projects
It is not required to migrate to 7.0. You can continue using 6.x with emotion as long as you need, the library is stable enough, patches are planned to be released for 6.x until 7.0 is out. If you decide to follow the hype, then of course there will be an overhead for you. Please do remember that it was not my decision to introduce features to React/Next.js which are incompatible with css-in-js – I would be happy to continue using emotion, but React forces everyone to switch to the static css. Well, maybe that's for the better.
just think it could be worth to explore any alternative to keep the createStyles API since it's such a core feature of Mantine.
You can use these tools in your project, Mantine 7.0 supports any styling solution. Mantine 7.0 is built with CSS modules, but it should not really bother you because in the end you will get a single
.css
file that you need to import in your application, so from the user side it is not relevant how Mantine styles are managed.
createStyles
function is a pure css-in-js – it is impossible to implement it the same way with any of the libraries listed above. Also, it adds more complexity to the maintenance of the library – I basically had to maintain a mini css-in-js library. In 7.0 you will get more flexibility in choosing the styling library – you can use styled-components, vanilla extract, linaria, css modules, sass, tailwind, you can even create your own createStyles function with emotion.There's plenty of people adopting Mantine right now expecting full server components compatibility in the future
That is why I'm working on 7.0 to provide full compatibility with app dir. Note that server components in their current implementation will not be supported by Mantine anyway – all components use
useContext
anduseState
hooks.when Mantine V7 comes out the overhead of migrating will probably be quite significant for those projects
It is not required to migrate to 7.0. You can continue using 6.x with emotion as long as you need, the library is stable enough, patches are planned to be released for 6.x until 7.0 is out. If you decide to follow the hype, then of course there will be an overhead for you. Please do remember that it was not my decision to introduce features to React/Next.js which are incompatible with css-in-js – I would be happy to continue using emotion, but React forces everyone to switch to the static css. Well, maybe that's for the better.
Perfect I understand @rtivital thanks for the detailed explanation just wanted to add my two cents. I agree that the less overhead the better :ok_hand:
I haven't dug into SSR frameworks like Next or Remix so forgive me for being a little confused by the following point that @rtivital made:
Note that server components in their current implementation will not be supported by Mantine anyway – all components use
useContext
anduseState
hooks.
Can someone explain this in more detail? I realize that Next has a 'use client'
directive, so does the above comment mean that Mantine will only work in the client context? And if so, how will 7.0 be any different than the current version that uses emotion?
Also, isn't the whole point of SSR frameworks to render as much as possible on the server? From the above comment, it sounds like very little will be able to be rendered on the server. Am I wrong?
Server components are executed only on server, client components are executed both on server and client.
Server components are executed only on server, client components are executed both on server and client.
If I'm to understand what you're writing, Mantine 7.0 will organize components based on server or client?
No, Mantine components cannot be used as server components because they use useState
/useContext
hooks
No, Mantine components cannot be used as server components because they use
useState
/useContext
hooks
If that is the case, then is there any need to configure anything when using Mantine with Next 13?
To me, Mantine works fine soon after install and using the components directly in your project, without any further set up or configuration, like I am seeing in the other replies. But the only issue is to use the 'use-client' directive on every page and component that uses Mantine, which is the whole app if you're gonna style anything at all. Wouldn't that defeat the purpose of using server components if every single page that uses a Mantine component has to have the 'use-client' directive?
No, Mantine components cannot be used as server components because they use
useState
/useContext
hooksIf that is the case, then is there any need to configure anything when using Mantine with Next 13?
To me, Mantine works fine soon after install and using the components directly in your project, without any further set up or configuration, like I am seeing in the other replies. But the only issue is to use the 'use-client' directive on every page and component that uses Mantine, which is the whole app if you're gonna style anything at all. Wouldn't that defeat the purpose of using server components if every single page that uses a Mantine component has to have the 'use-client' directive?
No it wouldn't. I feel there a big misunderstandings of how Server vs. Client Components work.
use client;
only tells the compiler that it cannot throw the clientside js away. In very simple terms. That's basically it. If you don't use use client;
it will throw the FE JS away literally making your interactive app non-interactive/unusable. Normally this isn't even possible because the compiler will complain about using interactive
-indicating things such as useState
.
So rendering on the server isn't affected by this.
No, Mantine components cannot be used as server components because they use
useState
/useContext
hooksIf that is the case, then is there any need to configure anything when using Mantine with Next 13? To me, Mantine works fine soon after install and using the components directly in your project, without any further set up or configuration, like I am seeing in the other replies. But the only issue is to use the 'use-client' directive on every page and component that uses Mantine, which is the whole app if you're gonna style anything at all. Wouldn't that defeat the purpose of using server components if every single page that uses a Mantine component has to have the 'use-client' directive?
No it wouldn't. I feel there a big misunderstandings of how Server vs. Client Components work.
use client;
only tells the compiler that it cannot throw the clientside js away. In very simple terms. That's basically it. If you don't useuse client;
it will throw the FE JS away literally making your interactive app non-interactive/unusable. Normally this isn't even possible because the compiler will complain about usinginteractive
-indicating things such asuseState
.So rendering on the server isn't affected by this.
Ok, I see. So is that to say SSR is still possible, but client components get hydrated and server components don't?
No, Mantine components cannot be used as server components because they use
useState
/useContext
hooksIf that is the case, then is there any need to configure anything when using Mantine with Next 13? To me, Mantine works fine soon after install and using the components directly in your project, without any further set up or configuration, like I am seeing in the other replies. But the only issue is to use the 'use-client' directive on every page and component that uses Mantine, which is the whole app if you're gonna style anything at all. Wouldn't that defeat the purpose of using server components if every single page that uses a Mantine component has to have the 'use-client' directive?
No it wouldn't. I feel there a big misunderstandings of how Server vs. Client Components work.
use client;
only tells the compiler that it cannot throw the clientside js away. In very simple terms. That's basically it. If you don't useuse client;
it will throw the FE JS away literally making your interactive app non-interactive/unusable. Normally this isn't even possible because the compiler will complain about usinginteractive
-indicating things such asuseState
. So rendering on the server isn't affected by this.Ok, I see. So is that to say SSR is still possible, but client components get hydrated and server components don't?
Simply said: yes.
No, createStyles is not a part of v7, as it relies on emotion. You can continue using 6.x if this feature is important to you.
@rtivital Im starting a new project and I was wondering, if createStyles
is not going to be part of v7, what can I use now so I don't have to suffer a big change when v7 is out
You can use CSS modules
A template for Next.js app directory with 7.0.0 alpha is available:
A template for Next.js app directory with 7.0.0 alpha is available:
played around with this and very happy with it. How long till we can expect the beta release? Months?
Great work @rtivital. This lib is incredible. I can't wait for update to this version.
This is fantastic! Are notifications/carousel etc still in the works? @rtivital
A template for Next.js app directory with 7.0.0 alpha is available:
played around with this and very happy with it. How long till we can expect the beta release? Months?
Many components are not present. Hope will be updated soon.
I wanna migrate from v6 to v7. As said, there are missing components(AppShell ,Flex vs). What time do you plan to publish all components that is already in v6.
Today the main mind responsible by Mantine is @rtivital... I imagine how difficult it is to reconcile time to maintain Mantine. I wish I had more knowledge to help you in this endeavor...
@rtivital I really appreciate and love your work. I am a software trainer and planning to use Mantine in my frontend developer education program. I will record videos about the usage of Mantine, 2 months from now I guess. Well, React ecosystem is going weird after these NextJS updates and seems like Mantine is not dependent on emotion anymore.
I want to record videos that will stay updated as much as they can. I am not sure about using v7 alpha on my videos since there are fewer components, especially components like "Grid" are important imo. What is your recommendation? Should I use v6 with emotion in my videos? Are you planning to release the grid component (and other important components like that) in the near next future weeks? Thank you
What is your recommendation? Should I use v6 with emotion in my videos?
Just do v6.
At least since I started using Mantine the project isn't afraid to change things up. The rich text editor component for example I recall switched packages to TipTap and IIRC that required migration for users to update to, similar with the dropping of emotion for anyone that leveraged the features relying on that in the past. I think it's happened with other components too :sweat_smile:
That has it's perks but isn't for everyone, maybe structure your Mantine content with that in mind. Focus on v6 and make a mention that the upcoming v7 is going with this larger change that will be somewhat disruptive initially, not all users will be able to migrate early. You can do a follow up v7 content when that lands/progresses if it suits.
Chakra last I heard while doing a similar big refactor (but better approach IIRC) may be less jarring. Depends on what's important to you and your audience.
I second the idea of using v6.
Over the weekend I've tested out both Mantine v6 stable and Mantine v7-alpha (13 atm) with Next.js app router & vanilla React 18 and, albeit a lot of components are yet indeed missing, it is already totally possible to use them in a toy project, but I'd suggest you to stay at v6 for anything you want it to be immediately robust at the moment.
Few reasons:
ps: Thanks @rtivital again for the great work! Me likey v7.
I might have missed it in the long thread, but did anybody manage to get Mantine working with the app router + was able to use dark/light mode switching properly? nothing I tried worked somehow :/
Would appreciate the advice/example repo! thanks!
EDIT: just for clarity purposes - 👎 reactions meaning that it's not possible or me being downvoted? :D
I might have missed it in the long thread, but did anybody manage to get Mantine working with the app router + was able to use dark/light mode switching properly? nothing I tried worked somehow :/
Would appreciate the advice/example repo! thanks!
Nope theme toggling is not fully working on my end with v6 and app router.
With the workarounds in this thread, the theme does toggle on the client components (cards, buttons, etc), however the page backgrounds do not so you are left with a half dark/half light theme.
Removing the workarounds in this thread does allow the theme to toggle properly, but re-introduces the layout shifting issue.
If anyone has solved the issue please let us know! Otherwise I am waiting for V7 to hopefully address the issue
No it wouldn't. I feel there a big misunderstandings of how Server vs. Client Components work.
use client;
only tells the compiler that it cannot throw the clientside js away. In very simple terms. That's basically it. If you don't useuse client;
it will throw the FE JS away literally making your interactive app non-interactive/unusable. Normally this isn't even possible because the compiler will complain about usinginteractive
-indicating things such asuseState
.So rendering on the server isn't affected by this.
This topic isn't completely solved for me yet and please educate me. With my current understanding I would opt out of Mantine if we were to chose NextJS even if I really like the library for it's UI components. We are using it extensively.
While SSR still works to show the pre rendered html before hydration, which is good for SSO and initial page load (not TTFB!), isn't one of the strong suits and arguments for NextJS in the next iteration that you have Server Components and reduce the bundle size of client js code dramatically?
Isn't the goal to keep the client module graph as slim as possible to not require to send it to the browser in the first place? In order to not pollute the application I believed it is desired to keep client components at the leaf of the application or at least inject them via child props for decoupling.
If I need to have a use client
directive in each file where basic layout components, such as <Box>
, <Flex>
or <Grid>
are used, doesn't this implicitly converts all components imported in those files into client components as well?
I am well aware that for interaction and complex inputs use-client
is required, but couldn't layouting with the components above be solved completely with gutting a few features such as polymorphic components and relying entirely on css vars?
I just think this is the wrong thread for explaining client vs Server Components. And as said above:
Server Component: SSR + No client-side JS. Client Component: SSR + Client-side JS.
That's it. That's really it (super tl;dr though. I'd recommend my own YouTube Channel but i don't have this comparison yet, I might make a Video for it, but it's some work, so be patient or try to check out a few others . If you like you can subscribe YT/@activenode but as I said: It's quite some work so I am hoping I find the time soon)
You CANNOT have a Server Component for Mantine Components because they NEED client-side JS for interactivity. Or in other words: Try making an autocomplete with HTML only, no JS. Won't work. Try making an Overlay that's triggered on button click and closes on button click without client-side JS, won't work.
Server Components don't need use client
to include Components that use use client
.
Yes, I am fully aware of the javascript aspect. I was specifically not talking about interactive components, but components necessary for layouting, which might be able to get away without the javascript part.
I don't see a reason why
<Grid>
<Grid.Col span={4}></Grid.Col>
<Grid.Col span={4}></Grid.Col>
<Grid.Col span={4}></Grid.Col>
</Grid>
shouldn't get away without "interactivity"
all mantine components use useState
and useContext
to get the theme and other global configs u provide in MantineProvider
What package has an issue
@mantine/core
Describe the bug
I use mantine dev as regular basis with next12. But when i put MantinProvider in app/pages.tsx or app/layout.tsx forlder. The app doesnt seems too work. Where to put __app.tsx requirements? sorry for bad english.
What version of @mantine/hooks page do you have in package.json?
"@mantine/hooks": "^5.6.2",
If possible, please include a link to a codesandbox with the reproduced problem
No response
Do you know how to fix the issue
No
Are you willing to participate in fixing this issue and create a pull request with the fix
No
Possible fix
Server Component support