Skip to content
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

Error when using the CSS prop with an object #240

Closed
Henrixounez opened this issue Dec 17, 2024 · 12 comments
Closed

Error when using the CSS prop with an object #240

Henrixounez opened this issue Dec 17, 2024 · 12 comments
Labels
bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request types Typescript types related

Comments

@Henrixounez
Copy link

When using the CSS Prop as an object, as shown in the docs here, it fails to compile and give a TypeError

✅ Working Example with the CSS Utility Function:

  <p
    css={css`
      color: green;
    `}
  >
    CSS Prop works if this is green
  </p>

image

❌ Not working using as an object:

  <p
    css={{
      color: "green"
    }}
  >
    CSS Prop works if this is green
  </p>

image

 ⨯ TypeError: {(intermediate value)} is not a function
    at Home (app/page.tsx:144:10)
  142 |           css={{
  143 |             color: "green"
> 144 |           }}
      |          ^
  145 |         >
  146 |           CSS Prop works if this is green
  147 |         </p> {
  digest: '2695420628'
}
 GET / 500 in 73ms
@jantimon
Copy link
Collaborator

oh you are right - objects are not supported

@Mad-Kat can remember why we added the css prop docs like this?

currently the css prop only works like this:

<div css={csscolor:green}>

@Henrixounez
Copy link
Author

Henrixounez commented Dec 17, 2024

Ok thanks, good to know !

I was also wondering if it was possible to have dynamic values inside the css props instead of having to create a dedicated styled variable with props, when needed for quick inline styling on tags like whats possible with styled-components / emotion ?

❌ Not working example:

export default function Home({ isDarkMode }: { isDarkMode: boolean }) {
  return (
    <p
      css={css`
        font-size: 20px;
        font-weight: bold;
        font-family: "Inter";
        color: ${isDarkMode ? "white" : "black"};
      `}
    >
      Text
    </p>
  );
}
./src/app/[locale]/hosts/[host]/new/page.tsx
 ○ Compiling /_not-found ...
 GET /fr 500 in 512ms
 ⨯ ./src/app/[locale]/hosts/[host]/new/page.tsx
Error:   × Dynamic values in CSS properties must be wrapped in arrow functions to make runtime behavior explicit.
  │ Example: ${() => getValue()} instead of ${getValue()}
    ╭─[/src/app/[locale]/hosts/[host]/new/page.tsx:20:1]
 17 │           font-size: 20px;
 18 │           font-weight: bold;
 19 │           font-family: "Inter";
 20 │           color: ${isDarkMode ? "white" : "black"};
    ·                    ──────────────────────────────
 21 │         `}
 22 │         // css={
 23 │         //   isDarkMode
    ╰────
  × Dynamic mixins must not be used within JSX attributes. Please ensure that this mixin requires no props.
    ╭─[/src/app/[locale]/hosts/[host]/new/page.tsx:16:1]
 13 │         <div>
 14 │           <h1>App Router</h1>
 15 │           <p
 16 │ ╭─▶         css={css`
 17 │ │             font-size: 20px;
 18 │ │             font-weight: bold;
 19 │ │             font-family: "Inter";
 20 │ │             color: ${isDarkMode ? "white" : "black"};
 21 │ ╰─▶         `}
 22 │             // css={
 23 │             //   isDarkMode
 24 │             //     ? css`
    ╰────

✅ Working (but superfluous)

I know it is possible as of now by using a ternary around the entire css prop, which may lead to code duplication (but at some point, it seems logical to create a styled component variable if needed...)

export default function Home({ isDarkMode }: { isDarkMode: boolean }) {
  return (
    <p
      css={
        isDarkMode
          ? css`
              font-size: 20px;
              font-weight: bold;
              font-family: "Inter";
              color: white;
            `
          : css`
              font-size: 20px;
              font-weight: bold;
              font-family: "Inter";
              color: black;
            `
      }
    >
      Text
    </p>
  );
}

@Mad-Kat
Copy link
Collaborator

Mad-Kat commented Dec 17, 2024

Thanks a lot for posting this :) We're always happy for input.

@Mad-Kat can remember why we added the css prop docs like this?

I don't remember exactly. I assume it worked with our babel plugin, but doesn't work currently with the SWC plugin. I really need to overhaul the docs. 🙈

I was also wondering if it was possible to have dynamic values inside the css props instead of having to create a dedicated > styled variable with props, when needed for quick inline styling on tags like whats possible with styled-components / emotion ?

We implemented the css prop in a very limited scope. It only works on native elements and without any interpolation. To support the interpolation we would have to extract a styled component for you in the correct scope the same way as styled-components does it. I'm not a huge fan of it, as it makes the code way more error prone and it's a complex task.

So #241 doesn't work, as it's already a styled component and our simple implementation just takes care of it on native HTML elements.

I assume your problem is mainly that your codebase is full with the css prop and it's very tedious to migrate? Or what is the use case here? Is it only for the light-dark theming or do you need to have other dynamic properties?

@Mad-Kat
Copy link
Collaborator

Mad-Kat commented Dec 17, 2024

And btw: Thank you for the very clear issue

@jantimon
Copy link
Collaborator

jantimon commented Dec 17, 2024

Is the scope really an issue in this case?

We don't move the code around so actually the scope should be unchanged - or am I wrong?

import { styled, css } from "next-yak";

export const Example = () => {
  return (
    <p
      css={css`
        color: ${() => (isDarkMode ? "white" : "black")};
      `}
    >
      Hello world
    </p>
  );
};

shot-IOdo5Nea@2x

import { styled, css } from "next-yak";

export const Example = () => {
  return (
    <p
      css={css`
        ${() => (isDarkMode && css`color: white`)};
      `}
    >
      Hello world
    </p>
  );
};

shot-FRAozihc@2x

@Mad-Kat
Copy link
Collaborator

Mad-Kat commented Dec 17, 2024

Sorry I was wrong. I didn't have enough coffee 😅

You're right @jantimon this could work.

@Henrixounez
Copy link
Author

We implemented the css prop in a very limited scope. It only works on native elements and without any interpolation. To support the interpolation we would have to extract a styled component for you in the correct scope the same way as styled-components does it. I'm not a huge fan of it, as it makes the code way more error prone and it's a complex task.

So #241 doesn't work, as it's already a styled component and our simple implementation just takes care of it on native HTML elements.

Actually it does work to apply the style to the component, the only problem here as detailed on the other issue is the Typescript error that results on using the css prop. I forgot to add a screenshot there but the html result is correct with the font color applied.

✅ Working example using css prop on styled component

/* @jsxImportSource next-yak */
import { css, styled } from "next-yak";

export default async function Test() {

  return (
    <div>
      <Text
        css={css`
          color: red;
        `}
      >
        test
      </Text>
    </div>
  );
}

const Text = styled.p`
  font-size: 20px;
  font-weight: bold;
  font-family: "Inter";
`;

image

(but i have a typescript error in code and when building)

❌ Not working example with parent container with css prop

However if I try to have two elements with css props with one inside the other, the styling doesn't seem to be applied on the children, they seem to be inheriting the styling on the parent

/* @jsxImportSource next-yak */
import { css, styled } from "next-yak";

export default async function Test() {
  return (
    <div
      css={css`
        background-color: blue;
        padding: 20px;
      `}
    >
      <p
        css={css`
          color: red;
        `}
      >
        test
      </p>
      <p
        css={css`
          color: green;
        `}
      >
        test
      </p>
    </div>
  );
}
image

📄 HTML output:

<div class="page_yak__b_FCE">
  <p class="page_yak__b_FCE">test</p>
  <p class="page_yak__b_FCE">test</p>
</div>

👨‍🎨 Css file output:

.page_yak__b_FCE {
  background-color: blue;
  padding: 20px;
}
.page_yak-01__NSkmr {
  color: red;
}
.page_yak-02__i6J5G {
  color: green;
}

@Henrixounez
Copy link
Author

I assume your problem is mainly that your codebase is full with the css prop and it's very tedious to migrate? Or what is the use case here? Is it only for the light-dark theming or do you need to have other dynamic properties?

Yes ! We were actively trying to find a replacement for our existing codebase using emotion (very similar to styled-components) but with something that would work inside Next and React Server Components.
We tried a lot of different packages for a simple migration but most didn't work, or some used a babel compiler that slowed everything down.

In the end yours checks the most boxes for us to try and have a gradual migration from existing codebase even if we need to change some things mostly on the css prop that we use copiously for quick inline styling with variables (that would help us a lot if you can find ways to apply dynamic properties but we could work around that).

@Mad-Kat
Copy link
Collaborator

Mad-Kat commented Dec 18, 2024

This looks like a bug we should fix. Thank you for posting it. Regarding some dynamic properties within css props, the idea of @jantimon should work and I will prepare a PR to make it possible.

Thank you for clarifying in which situation you are. It always helps us to get a feel from the outside and where we should head next.

@jantimon
Copy link
Collaborator

With next-yak 4.0.2 you can now use logic inside css properties

We also added it to our (not very meaningful) example:

https://github.com/jantimon/next-yak/blob/11261b772ff5d26a5d7684e275d28dbb0a4d30c0/packages/example/app/page.tsx#L145-L156

@Mad-Kat Mad-Kat added bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request types Typescript types related labels Jan 7, 2025
@Mad-Kat
Copy link
Collaborator

Mad-Kat commented Jan 9, 2025

We fixed more issues with the css prop in [email protected]. You can see the changes here: #258 and for [email protected] that also shipped a fix for css props can be read here: #246.

Let us know if you find something else that doesn't work with the css prop. We're always happy to help & fix

@jantimon
Copy link
Collaborator

Resolved - please let us know if it does not work correctly

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working documentation Improvements or additions to documentation enhancement New feature or request types Typescript types related
Development

No branches or pull requests

3 participants