QwikDev / qwik

Instant-loading web apps, without effort
https://qwik.dev
MIT License
20.84k stars 1.31k forks source link

[🐞] PandaCSS Plugin Doesn't Allow CSS Object To Be Passed As Props #5102

Closed Kesmek closed 1 year ago

Kesmek commented 1 year ago

Which component is affected?

Qwik Rollup / Vite plugin

Describe the bug

I would like to pass some CSS to a component that's using PandaCSS css() function. Everything works correctly unless I try to pass CSS to the component as props, as shown on the PandaCSS docs here. The CSS does get passed to the component, as I'm able to log it for example. However attempting to use in the the css() function in that component is what brings up this error. The issue seems to be related to the vite-plugin-macro package somehow, although I'm not sure exactly what is causing the issue. The error:

[vite] Internal server error: cssProp is not defined
  Plugin: vite-plugin-macro
  File: /home/justin/Projects/test/test-app/src/components/test/test.tsx
      at eval (eval at transform (file:///home/justin/Projects/test/test-app/node_modules/.pnpm/@builder.io+vite-plugin-macro@0.0.7_@types+node@20.5.9/node_modules/@builder.io/vite-plugin-macro/dist/index.js:472:34), <anonymous>:3:12)
      at TransformContext.transform (file:///home/justin/Projects/test/test-app/node_modules/.pnpm/@builder.io+vite-plugin-macro@0.0.7_@types+node@20.5.9/node_modules/@builder.io/vite-plugin-macro/dist/index.js:476:28)
      at async Object.transform (file:///home/justin/Projects/test/test-app/node_modules/.pnpm/vite@4.4.7_@types+node@20.5.9/node_modules/vite/dist/node/chunks/dep-3b8eb186.js:44240:30)
      at async loadAndTransform (file:///home/justin/Projects/test/test-app/node_modules/.pnpm/vite@4.4.7_@types+node@20.5.9/node_modules/vite/dist/node/chunks/dep-3b8eb186.js:54896:29) (x2)

And this is how I'm attempting to use the css in props:

// components/test.tsx
import { component$ } from "@builder.io/qwik";
import { css } from "~/styled-system/css";
import type { SystemStyleObject } from "~/styled-system/types";

interface Props {
  css: SystemStyleObject;
}

export default component$<Props>(({ css: cssProp }) => {
  return <div class={css(cssProp)} />;
});

// routes/index.tsx
import { component$ } from "@builder.io/qwik";
import type { DocumentHead } from "@builder.io/qwik-city";
import Test from "~/components/test/test";

export default component$(() => {
  return (
    <>
      <h1>Hi 👋</h1>
      <p>
        Can't wait to see what you build with qwik!
        <br />
        Happy coding.
      </p>
      <Test css={{ bg: "blue" }} />
    </>
  );
});

Reproduction

https://github.com/Kesmek/qwik-pandacss-css-props

Steps to reproduce

  1. pnpm create qwik@latest
  2. pnpm qwik add pandacss
  3. pnpm upgrade @pandacss/dev -L (The version that gets added by Qwik is quite outdated)
  4. Create a component that accepts a style object as a prop.
  5. Use that style object in PandaCSS css(style) function.

System Info

System:
    OS: Linux 6.4 Arch Linux
    CPU: (16) x64 AMD Ryzen 7 7700 8-Core Processor
    Memory: 20.87 GB / 30.48 GB
    Container: Yes
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.5.1 - /usr/bin/node
    Yarn: 1.22.19 - /usr/bin/yarn
    npm: 9.8.1 - /usr/bin/npm
    pnpm: 8.7.1 - /usr/bin/pnpm
  npmPackages:
    @builder.io/qwik: ^1.2.10 => 1.2.10 
    @builder.io/qwik-city: ^1.2.10 => 1.2.10 
    @builder.io/vite-plugin-macro: ~0.0.7 => 0.0.7 
    undici: 5.22.1 => 5.22.1 
    vite: 4.4.7 => 4.4.7

Additional Information

I'm not certain that this is actually an error based in Qwik/vite-plugin-macro so if I'm mistaken, please let me know and I'll gladly bring up this issue to the appropriate project.

ulic75 commented 1 year ago

This is strange indeed. I'm not sure what's different between my repo (private project) and yours, but I'm using this technique and not receiving any errors.

mhevery commented 1 year ago

So this works as intended....

PandaCSS is compile time (not runtime) which means that css() calls get computed at build time. There is no access to the prop at build time; hence, this can't work.

To solve your issue, create a CSS variable and pass it to PandaCSS through styles. Here is an example:

import { component$, useSignal } from "@builder.io/qwik";
import { css } from "~/styled-system/css";

export default component$(() => {
  const opacity = useSignal(0.5);
  return (
    <div>
      Opacity:{" "}
      <input
        type="range"
        min="0"
        max="1"
        step="0.05"
        value={opacity.value}
        onInput$={(e) =>
          (opacity.value = (e.target as HTMLInputElement).valueAsNumber)
        }
      />{" "}
      {opacity.value}
      <Child opacity={opacity.value} />
    </div>
  );
});

export const Child = component$<{ opacity: number }>(({ opacity }) => {
  return (
    <div
      class={css({
        opacity: "var(--myOpacity)",
      })}
      style={{ "--myOpacity": opacity }}
    >
      Hello Qwik!
    </div>
  );
});

I am going to close this as working as intended... But feel free to continue the discussion or create new issues.

Kesmek commented 1 year ago

Oh I see, thanks for the clarification!