twin.macro
twin.macro copied to clipboard
Error when passing props to the css attribute in solid/stitches
When using the SolidJS integration, the following results in Uncaught ReferenceError: props is not defined
in the browser:
const BrokenInput = (props: InputProps) => (
<input
css={{
...tw`border`,
...(props.hasHover && tw`hover:border-red-600`),
}}
/>
)
On the other hand, this works fine:
const WorkingInput = styled.input((props: InputProps) => ({
...tw`border`,
...(props.hasHover && tw`hover:border-red-600`),
}))
Thanks for posting this bug, I've seen the issue too and I haven't settled on a good solution yet.
Here's the broken transformation:
const BrokenInput = (props) => (
<input css={{ ...(props.hasHover && tw`block`) }} /> // < Any conditionals like `props` here will lose their reference
)
// โ โ โ โ โ โ
import { styled } from "solid-styled-components";
const TwComponent = styled("input")({
...(props.hasHover && { "display": "block" }) // < `props` reference is lost
});
const BrokenInput = props => <TwComponent />; // < `props` isn't passed to the component
The css prop doesn't exist in solid-styled-components so twin converts the element into a styled component. The problem is that during that process all the variables used in the conditional are severed and rather than chasing a complex solution in babel I'm looking into adding a new conversion type instead.
The new conversion for the css prop would use the css import from solid-styled-components:
const BrokenInput = (props) => (
<input css={{ ...(props.hasHover && tw`block`) }} />
)
// โ โ โ โ โ โ
import { css } from "solid-styled-components";
const BrokenInput = props => (
<input class={css({ ...(props.hasHover && { display: "block" }) })} />
)
This option would simplify the conversion and the conditionals wouldn't be affected.
One issue is that if there's already a class on the element then a merge needs to happen - perhaps something as simple as this would work:
<input class="box" css={{ ... }} />
// โ โ โ โ โ โ
<input class={"box " + css({ ... }) } />
and if css is defined before the class attribute:
<input css={{ ... }} class="box" />
// โ โ โ โ โ โ
<input class={css({ ... }) + " box" } />
Thanks for the explanation. Would Solid's classList
help with that merge?
<div classList={{ ...{ [css`color: rebeccapurple;`]: true }, ...{ myClass: true, otherClass: false } }}>My text</div>
mark. same problem.