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.73k stars 252 forks source link

When using the "css" prop, locally should scoped tokens ignore 'undefined' values? #978

Open bartels opened 2 years ago

bartels commented 2 years ago

Bug report

One can set a default value for locally scoped tokens, e.g. $$color: 'magenta'. These can be overriden with the css prop, css={{ $$color: 'red' }}

However, when passing an undefined value for a locally scoped token to the css prop, e.g. css={{ $$color: undefined }}, the resulting stylesheet will set an empty value instead of using the default value.

To Reproduce

An example: https://codesandbox.io/s/heuristic-gates-hur85g?file=/src/App.js:43-77

import { styled } from "@stitches/react";

export const Text = styled("p", {
  $$color: "magenta",
  color: "$$color"
});

export default function App() {
  return (
    <div className="App">
      <Text>I default to magenta</Text>
      <Text css={{ $$color: undefined }}>I should also default to magenta but do not</Text>
    </div>
  );
}

The second instance of <Text> component above will result in --color: ; in the stylesheet instead of --color: magenta.

The above is a trivial example, but ignoring undefined values would be useful when passing optional props for a React component to the css prop of a styled component. For example css={{ $$color: props.maybeColorOrUndefined }}. The current behavior requires a the user to write a utility function to filter out the undefined values before passing down to the css prop.

Additional context

I see issue #666 was closed as fixed, but I'm still seeing this behavior present in v1.2.7

It seems the behavior for regular css properties are to ignore undefined values. Perhaps locally scoped tokens should do the same?

sunny-to commented 2 years ago

Thanks for posting this. I ran into this as well, on both v1.2.7 and v1.2.6, and wasn't sure if this was intended behavior for the css prop.

As you said, I had to manually filter out undefined entries in the css object before passing it to a Stitches component.

Code Sandbox

import { styled } from "@stitches/react";

export const BaseText = styled("p", {
  $$color: "magenta",
  color: "$$color"
});

const Text = ({color, children, ...props}) => {
  const css =  {
    ...(color && { $$color: color }),
  }

  return <BaseText css={css} {...props}>{children}</BaseText>;
};

export default function App() {
  return (
    <div className="App">
      <Text>I should default to magenta</Text>
      <Text color={undefined}>
        I default to magenta because color was filtered
      </Text>
      <Text css={{ $$color: "red" }}>I should be red</Text>
    </div>
  );
}

I'm not sure if this is a regression or not. If I have some time later, I can try confirming against older versions.

hadihallak commented 2 years ago

because of https://github.com/stitchesjs/stitches/issues/666 I would consider this as a bug that needs to be fixed.