styled-components / xstyled

A utility-first CSS-in-JS framework built for React. 💅👩‍🎤⚡️
https://xstyled.dev
MIT License
2.27k stars 107 forks source link

The order of props should not matter #326

Closed thobas-dnvgl closed 2 years ago

thobas-dnvgl commented 2 years ago

💬 Questions and Help

I noticed that

<x.div borderBottom={2} borderColor="blue-400">
  hello
</x.div>

and

<x.div borderColor="blue-400" borderBottom={2} >
  hello
</x.div>

will produce different results. It's because the last one will generate:

border-color: #60a5fa;
border-bottom: 2px solid;

and the default color (black) for border-bottom will override border-color. Is there a better way to write it so that I don't have to remember that ordering props matter?

Ideally, is it possible to make the following code a reality?

<x.div borderBottom="2px solid blue-400">
  hello
</x.div>

Thanks! :)

agriffis commented 2 years ago

That's a fascinating bug, and well-explained, thanks!

Order matters in CSS, therefore order matters in props. Without preserving order, you wouldn't have a workaround. Additionally, the order of props is important because otherwise the caller has to know the specific props to override:

const Foo = props => <x.div borderColor="red" {...props} />

<Foo border="2px solid green" />

The final border should be green, not red, and the caller shoudn't need to know that the inner component used borderColor instead of the border shorthand. That wouldn't work if the order weren't preserved.

About your ideal case, we might be able to do something for simplistic cases. The problem is that it gets tricky with complex space-separated values, and there's limited value to increasing the complexity of the code to handle them. But I can imagine handling the simple cases at some point.

For now, though, have you considered using borderBottomStyle and borderBottomWidth to avoid the effect of the border shorthand?

thobas-dnvgl commented 2 years ago

Glad it got your attention :D.

I can use borderBottomStyle and borderBottomWidth indeed.

rfsr commented 3 months ago

What's even more interesting about this behavior is that the docs generate something entirely different:

<x.input border={2} borderColor="red-600" />

produces:

border: 2px solid rgb(220, 38, 38);

Doing that same thing locally I get:

border: 2px solid;
border-color: rgb(220, 38, 38);