styled-components / xstyled

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

Styles are not overwritten #287

Closed ivanbanov closed 3 years ago

ivanbanov commented 3 years ago

Im not really sure if it's intended or an actual bug.

The styles props are not being overwriten when extending the "default box" x.div

image

A repo with a quick reproduction can be found here https://github.com/ivanbanov/xstyled-styles-override-bug/

ivanbanov commented 3 years ago

ok, nevermind I will close this one since adding the importMap fixes the problem

ivanbanov commented 3 years ago

actually the first css prop was not transpiled when using the plugin image

agriffis commented 3 years ago

@ivanbanov You are reporting two things here:

  1. Styles aren't overriding the way you expect
  2. Theme values aren't being replaced

The second issue is #285 so let's not repeat it here.

For the first issue, the problem is that you're wrapping a system component (that receives props) with a styled component (that sets styles in a style object). The wrapper wins, and this is correct! It would be unexpected for an inner component's styling to override a wrapper component.

To make it work the way you want, pass system to the styled wrapper as an additional style generator:

const InfoBox = styled(Box)({ backgroundColor: 'info' }, system)

At this point, you no longer need Box, you might as well use div:

const InfoBox = styled.div({ backgroundColor: 'info' }, system)

and there is also a shortcut for this, which automatically applies system:

const InfoBox = styled.box({ backgroundColor: 'info' })

Alternatively you can use <x.div> which works the same as styled.box:

const InfoBox = props => <x.div backgroundColor='info' {...props} />

I made a fork to demonstrate each of these approaches, see https://github.com/agriffis/xstyled-styles-override-bug/blob/master/index.js#L5-L9

ivanbanov commented 3 years ago

Cool thanks, I ended up using a utility which is also working with the importMap settings

import styled from '@xstyled/emotion'
import { system } from '@xstyled/system'

export const box = (...styles) => styled.div(...styles, system)

// usage

const StyledComponent = box({ color: 'info' })
<StyledComponent color='error' />

Using styled.div instead of styled.box somehow works better, it doesn't forward props to DOM. For me it's nice because I don't have to adjust my code to use transient props while migrating from v1 to v3 :)

Again, I appreciate your support :)