stitchesjs / stitches

[Not Actively Maintained] CSS-in-JS with near-zero runtime, SSR, multi-variant support, and a best-in-class developer experience.
https://stitches.dev
MIT License
7.72k stars 251 forks source link

Support for Next.js 13 #1109

Open hmbrg opened 1 year ago

hmbrg commented 1 year ago

Since Next.js 13 was released yesterday, the beta docs list Stitches as not being support as of right now.

There is however a guide on how to integrate styled-jsx that look very similar to how Stitches could be integrated: https://beta.nextjs.org/docs/styling/css-in-js

Are there any plans to officially offer support for Next.js 13?

jpmaga commented 1 year ago

I barely tested this, but seems to be working. Again, I tested this for like 2 mins, so take that into consideration. Based on the example:

"use client"

import React from "react"
import { useServerInsertedHTML } from "next/navigation"
import { getCssText } from "../../stitches.config"

export function ServerStylesheet({ children }) {
  useServerInsertedHTML(() => {
    return <style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
  })

  return children
}

and on the layout:

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <title>Create Next App</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </head>
      <body>
        <ServerStylesheet>{children}</ServerStylesheet>
      </body>
    </html>
  )
}
darklight9811 commented 1 year ago

@jpmaga css utility method breaks the app (both on client and server). And stitches should update the docs for next 13 app dir. Because its a totally different way of doing things than the pages directory

rodrigodh commented 1 year ago

It seems to only work with client-side rendering, is it right?

vitharanagedonjani-i2e commented 1 year ago

@rodrigodh yes

rodrigodh commented 1 year ago

Is there any way for making the app awaits for css before loads?

darklight9811 commented 1 year ago

@rodrigodh you need to force the prop into a string, then it works, this is actually a bug on react dom server, need to post an issue about this there.

I noticed that sometimes the style dont load at all too.

rodrigodh commented 1 year ago

@rodrigodh you need to force the prop into a string, then it works, this is actually a bug on react dom server, need to post an issue about this there.

I noticed that sometimes the style dont load at all too.

'use client';

import { useServerInsertedHTML } from 'next/navigation';
import { getCssText } from './stitches.config';

export function ServerStylesheet({
  children,
}: {
  children: JSX.Element;
}): JSX.Element {
  useServerInsertedHTML(() => {
    return (
      <style
        id="stitches"
        dangerouslySetInnerHTML={{ __html: String(getCssText()) }}
      />
    );
  });

  return children;
}

Tried this but did not work, is it another prop?

vitharanagedonjani-i2e commented 1 year ago

@rodrigodh getCssText() returns a string @darklight9811 could you elaborate?

darklight9811 commented 1 year ago

@rodrigodh @vitharanagedonjani-i2e, sorry for the delay, but I meant the css utility, not the getCssText(), another part of the issue.

const buttonProps = css({})

function Button (props) {
  return <button className={buttonProps(props)}>{props.children}</button>
}
vitharanagedonjani-i2e commented 1 year ago

Does this fix the issue where styles are not loading in server side? @darklight9811

rodrigodh commented 1 year ago

Does this fix the issue where styles are not loading in server side? @darklight9811

Absolutely not

gabriel-mend commented 1 year ago

This link shows how it worked for me, but only on the client side. https://stackblitz.com/edit/nextjs-ftij4p?file=app/ServerStylesSheet.tsx

But all pages and components you need to use with stitches, you put this flag on top the code 'use client'. This specify the component or page is run on client side.

jvgreenaway commented 1 year ago

I‘d love to see support for this too.

I don't 100% understand the issue but I suspect getCssText is too magical and something like a StyleSheet API needs to be exposed.

b2rsp commented 1 year ago

I am also on the need for a migration for Nextjs 13 and i would the support for this as well!

DavidRojas1612 commented 1 year ago

This works for me, inside of the Layout.tsx file generated in the app directory folder, but i dont sure.

import {getCssText, globalStyles} from '@/ui'
import './globals.css'

export default function RootLayout({children}: {children: React.ReactNode}) {
  globalStyles()
  return (
    <html lang="en">
      <head>
        <style id="stitches" dangerouslySetInnerHTML={{__html: getCssText()}} />
      </head>
      <body>{children}</body>
    </html>
  )
}
timweightman commented 1 year ago

@DavidRojas1612 That's great! Seems extremely simple, thanks for commenting to let us know. Have you noticed any gaps or issues since last week?

jbowa commented 1 year ago

@DavidRojas1612 @timweightman The above seems to work albeit I am seeing a few errors:

Screenshot 2023-01-27 at 1 19 08 pm
thomas-negrault commented 1 year ago

This works for me, inside of the Layout.tsx file generated in the app directory folder, but i dont sure.

@DavidRojas1612 Does this work for you with fast refresh ? It does work on my side but if I do a change, the app refresh without stitches style and I have to manually refresh to get the style back.

timweightman commented 1 year ago

@DavidRojas1612 @timweightman The above seems to work albeit I am seeing a few errors: Screenshot 2023-01-27 at 1 19 08 pm

I am not certain why you're getting this error - the content of your RootLayout component should match @DavidRojas1612 example exactly. Is there anything you've done differently, maybe show us some code?

@DavidRojas1612 Does this work for you with fast refresh ? It does work on my side but if I do a change, the app refresh without stitches style and I have to manually refresh to get the style back.

I'm in the same boat - must manually refresh to get styles back. I believe the CSS generated and put into the <style id="stitches" element is being mangled. When I modify CSS for a Stitches styled component and compare the content of that style element, the whole block of styles for all components has been removed, only the global styles remain.

I wonder if it's related to NextJS Fast Refresh...?

hipstersmoothie commented 1 year ago

@timweightman I think getCSsText is broken in general on the client https://github.com/stitchesjs/stitches/issues/1094

I too am only seeing the global styles in the output

hipstersmoothie commented 1 year ago

Ooo I just did a setTimeout to use getCssText and it has all the styles now. I'm thinking that if you call it too soon it doesn't work

jackguoAtJogg commented 1 year ago

Ooo I just did a setTimeout to use getCssText and it has all the styles now. I'm thinking that if you call it too soon it doesn't work

@hipstersmoothie What does your code looks like? I'd like to have it as a reference.

hipstersmoothie commented 1 year ago

CleanShot 2023-02-20 at 15 38 57

ferreira029 commented 1 year ago

I solved this problem creating a isolated component, and applying the getCssText there for example:

MyComponent:

import { getCssText } from '@/styles/stitches.config'

export const StyleSheet = () => {
  return (
        <style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
    )
}

layout.tsx

import { StyleSheet } from '@/components/StyleSheet'
import { GlobalCss } from '@/styles/global'

export default function RootLayout({
    children,
}: {
    children: React.ReactNode
}) {
    return (
        <html lang="en" className={inter.className}>
            <head>
                <StyleSheet />
            </head>
            <body>
                {children}
                {GlobalCss()}
            </body>
        </html>
    )
}

This way work because that in nextjs 13 all component are SSR (Server Side Rendering), then this stitche style is load on SSR and the screen already work with this style!

I hope that help everyone! Thank you guys!

wolffbruno commented 1 year ago

I solved this problem creating a isolated component, and applying the getCssText there for example:

MyComponent:

import { getCssText } from '@/styles/stitches.config'

export const StyleSheet = () => {
  return (
      <style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
  )
}

layout.tsx

import { StyleSheet } from '@/components/StyleSheet'
import { GlobalCss } from '@/styles/global'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
      <html lang="en" className={inter.className}>
          <head>
              <StyleSheet />
          </head>
          <body>
              {children}
              {GlobalCss()}
          </body>
      </html>
  )
}

This way work because that in nextjs 13 all component are SSR (Server Side Rendering), then this stitche style is load on SSR and the screen already work with this style!

I hope that help everyone! Thank you guys!

For me, this solution works well, but fast refresh does not immediately work (the styles are not applied), requiring a manual refresh.

joneslloyd commented 1 year ago

I solved this problem creating a isolated component, and applying the getCssText there for example:

MyComponent:

import { getCssText } from '@/styles/stitches.config'

export const StyleSheet = () => {
  return (
      <style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
  )
}

layout.tsx

import { StyleSheet } from '@/components/StyleSheet'
import { GlobalCss } from '@/styles/global'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
      <html lang="en" className={inter.className}>
          <head>
              <StyleSheet />
          </head>
          <body>
              {children}
              {GlobalCss()}
          </body>
      </html>
  )
}

This way work because that in nextjs 13 all component are SSR (Server Side Rendering), then this stitche style is load on SSR and the screen already work with this style!

I hope that help everyone! Thank you guys!

This worked for me only when it's an isolated component with no other functionality (ie, global styles in a separate file)

jbowa commented 1 year ago

The above solutions seem to be working for me too with: stylesheets.tsx

export default function StyleSheet() {
    return (
        <style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
    );
}

globalCSS.tsx

export default function GlobalCSS() {
    return globalStyles();
}

and

layouts.tsx

export default function RootLayout({ children }: Props) {
    return (
        <html lang="en" className={Graphik.className}>
            <head>
                <StyledSheet />
            </head>
            <body>
                <Providers>{children}</Providers>
                <Analytics />
                {GlobalCSS()}
            </body>
        </html>
    );
}
IvanKuzyshyn commented 1 year ago

@jbowa I'm wondering why {GlobalCSS()} goes as last body children and not the first?

jbowa commented 1 year ago

@IvanKuzyshyn Either way I am still having issues. As much as I hate it, I think the smart move here would be to move to TailwindCSS.

cassiocsantana commented 1 year ago

I've followed the steps to set up Stitches with Next.js 13, but I'm having issues with rehydration. Sometimes it works, sometimes it doesn't, and I have to do a manual refresh. Additionally, the styles are not being applied consistently and sometimes load without any styling before eventually applying the correct styles. Is there anything I can do to improve this? Any other tips or suggestions?

gutsyphilip commented 1 year ago

I've followed the steps to set up Stitches with Next.js 13, but I'm having issues with rehydration. Sometimes it works, sometimes it doesn't, and I have to do a manual refresh. Additionally, the styles are not being applied consistently and sometimes load without any styling before eventually applying the correct styles. Is there anything I can do to improve this? Any other tips or suggestions?

Having this issue as well. Had to revert to using the pages folder to avoid these issues.

ricardolandolt commented 1 year ago

Hi guys!

Based on these examples: https://beta.nextjs.org/docs/styling/css-in-js, this works for me:

app/registry.tsx

"use client";

import React, { useState } from "react";
import { useServerInsertedHTML } from "next/navigation";
import { getCssText } from "@/styles/styles.config";

export default function StitchesRegistry({ children }: { children: React.ReactNode }) {
  const [isRendered, setIsRendered] = useState(false);

  useServerInsertedHTML(() => {
    if (!isRendered) {
      setIsRendered(true);
      return <style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />;
    }
  });

  return <>{children}</>;
}

app/layout.tsx

import { Providers } from "./providers";
import StitchesRegistry from "./registry";

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head />
      <body>
        <StitchesRegistry>
          <Providers>{children}</Providers>
        </StitchesRegistry>
      </body>
    </html>
  );
}

Hope to help someone! Cheers!

maxichrome commented 1 year ago

@ricardolandolt that registry does seem to make fast refresh work just fine in my (very limited) testing!

matt-hai commented 1 year ago

It should still be noted that only client components will get any styling by using the 'stitches registry' solution.

Server components do not get styling output. They will get a CSS class applied, but it won't be flushed within the generated style element content.

@ricardolandolt do server components get styling in your use-case?

MuLoo commented 5 months ago

Hi guys!

Based on these examples: https://beta.nextjs.org/docs/styling/css-in-js, this works for me:

app/registry.tsx

"use client";

import React, { useState } from "react";
import { useServerInsertedHTML } from "next/navigation";
import { getCssText } from "@/styles/styles.config";

export default function StitchesRegistry({ children }: { children: React.ReactNode }) {
  const [isRendered, setIsRendered] = useState(false);

  useServerInsertedHTML(() => {
    if (!isRendered) {
      setIsRendered(true);
      return <style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />;
    }
  });

  return <>{children}</>;
}

app/layout.tsx

import { Providers } from "./providers";
import StitchesRegistry from "./registry";

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html>
      <head />
      <body>
        <StitchesRegistry>
          <Providers>{children}</Providers>
        </StitchesRegistry>
      </body>
    </html>
  );
}

Hope to help someone! Cheers!

Hi, thank you for the solution you provided. I am a beginner of NEXTJS, I have a doubt, if the registry is “use client”, then its subcomponents need to be rendered on the client side, does this affect the SEO of the entire application? What is the best way to do it? For example, use other css solutions?

dzek69 commented 5 months ago

@MuLoo "use client"; does NOT mean that component is rendered only in the browser. You can easily verify that, reload current url (f5), then press ctrl+U, that's the HTML sent by the server. (Adjust hotkeys if you are on Mac)

React Server Component and SSR are two different topics basically.

MuLoo commented 5 months ago

@MuLoo "use client"; does NOT mean that component is rendered only in the browser. You can easily verify that, reload current url (f5), then press ctrl+U, that's the HTML sent by the server. (Adjust hotkeys if you are on Mac)

React Server Component and SSR are two different topics basically.

Thank you buddy, I got it, Hope you have a nice day ! ❤️

lcberaldo commented 2 months ago

hey guys !

I'm still having the same problem reported in this thread.

The browser does the auto refresh, but without the styles. I need to manually update the page

Did anyone find a solution?

MuLoo commented 2 months ago

hey guys !

I'm still having the same problem reported in this thread.

The browser does the auto refresh, but without the styles. I need to manually update the page

Did anyone find a solution?

Stitches does not support styled function in server-side components, which means it can only be used in client-side components. therefore, There are two sets of css methods for client components and server components. I've switched all to css modules. In this way, the css methods of server and client components are unified. Basically no one has the energy to maintain stitches now, so it is recommended to replace it as soon as possible.