solidjs / solid-styled-components

A 1kb Styled Components library for Solid
MIT License
280 stars 26 forks source link

Using styled components in rules #1

Closed modmanx closed 3 years ago

modmanx commented 3 years ago

Hello, I'm using solid-styled-components for a project. What I would like to do is to use component in rule like shown below as available in documentation https://github.com/cristianbote/goober#usage

<ComponentA>
  <ComponentB>
  </ComponentB>
</ComponentA>

export const ComponentB= styled('div')`
  width: 80px;
`;

export const ComponentA= styled('div')`
 &:hover ${ComponentB}{
    filter: brightness(1.5);
  }
`;

Unfortunately I'm getting error and do not know how to fix

solid.js:558 Uncaught (in promise) RangeError: Maximum call stack size exceeded
    at runComputation (solid.js:558)
    at updateComputation (solid.js:544)
    at createRenderEffect (solid.js:184)
    at spreadExpression (web.js:328)
    at spread (web.js:172)
    at index.js:49
    at goober.esm.js:1
    at Array.reduce (<anonymous>)
    at i (goober.esm.js:1)
    at Object.p (goober.esm.js:1)

Would anyone have any idea on how to proceed?

ryansolid commented 3 years ago

Thanks for reporting. I wasn't aware of this use case. I'm not using their styled-components directly, but also not doing much differently. I'll take a look.

modmanx commented 3 years ago

The best! Really appreciate your fast response.

ryansolid commented 3 years ago

Goober is expecting VDOM nodes here. It calls the component with the same props as the hosting component and compiles the styles to grab their class. Given we are dealing with real DOM nodes this is not a good plan. It also seems to be causing an infinite loop. Been trying to think of other ways to achieve this.

modmanx commented 3 years ago

Do not worry if there isn't simple solution. Will then move to sass and use styled for other cases! Thank you for taking time.

ryansolid commented 3 years ago

I think I figured out a way to do this. Expose a helper(className) on each Styled component specifically for this case. It is a bit of a weird one though. In that to get the className we calculate it based on the template and props. The props being passed in, in this case, are from the parent. I guess you could control your own props passed in.

Ie..

<ComponentA>
  <ComponentB>
  </ComponentB>
</ComponentA>

export const ComponentB= styled('div')`
  width: 80px;
`;

export const ComponentA= styled('div')`
 &:hover ${ComponentB.className}{
    filter: brightness(1.5);
  }
`;

But technically className is a function that takes props. It just returns a class instead of executes the component

ryansolid commented 3 years ago

Ok released in 0.26.4.