linaria icon indicating copy to clipboard operation
linaria copied to clipboard

CSS var has wrong value when using child selector with a prop and having a child component of the same component

Open m59peacemaker opened this issue 5 years ago • 1 comments

Tested on Linaria 1.0.0, 1.3.3, 2.0.0-alpha.5 and projects using rollup and webpack.

Here is an example of problematic code:

const Column = styled.div`
  & > * + * {
    margin-top: ${({ spacing }) => spacing == null ? '0' : spacing};
  }
`
<Column spacing='30px'>
  <Column/></Column>
  <Column></Column>
</Column>

The nested Column divs should have margin-top: 30px, but they will instead have margin-top: 0, because they have the relevant variable set on their styles to 0, meaning that the child selector they are being affected by from their parent, is having its value determined by them (the child). So, anytime the parent tries to use a prop to affect a child this way, if the child is the same component, its prop (or lack thereof) affects itself (via its parents child-selecting rule), not only its children.

Reproduced here: https://github.com/m59peacemaker/bug-repro-linaria-child-selector-variable

For further verification, I swapped out linaria for styled-components to see that it works as expected. The reproduction repo includes both.

screenshot

m59peacemaker avatar Sep 21 '20 19:09 m59peacemaker

Hi @m59peacemaker, I bumped into your issue as well. If I'm not too late, one possible work around that would help out here is to provide an invalid margin value as the default such as /**/ or "''".

const Column = styled.div`
  & > * + * {
    margin-top: ${({ spacing }) => spacing == null ? '/**/' : spacing};
  }
`
<Column spacing='30px'>
  <Column/></Column>
  <Column></Column>
</Column>

This would stop the margin property from being unintentionally overriden by the defaults in this case.

Demo: https://codesandbox.io/s/lively-monad-y5s8v?file=/src/App.js

afzalsayed96 avatar Dec 15 '20 15:12 afzalsayed96