Rebass: Theme overrides component props

Created on 16 Dec 2018  Â·  12Comments  Â·  Source: rebassjs/rebass

Maybe this is the intended behavior but when I set props on individual components they are overridden by the ThemeProvider. For instance, I have a color set on all Heading elements in my theme.js but for one in particular, I'd like to override the default setting by passing in the color prop. What's the recommended way to do this?

Most helpful comment

Hmm ok. I've been using theme.js to set a standard style for all rebass components on my site and wanted to use the occasional style prop to override those settings. For anything more complex, I'm using the styled components library aka styled(Text). For a first time user, this behavior is kind of confusing as I'm not sure when to use rebass style props or define a styled component but I can say that it's been useful to easily access bg, color, etc except when they conflict with my theme.js settings.

Seems like the best solution is just to remove rebass components from my theme.js and use defaultProps instead

All 12 comments

In case anyone is wondering, as a workaround, I am wrapping the content in another un-themed element. For instance, my Heading elements have a text color defined in theme.js. If I want to override that text color I do the following:

<Heading>
  <Box color="different_color">Heading Text</Box>
</Heading>

Not sure if this is the best way to do it but it works.

I have a color set on all Heading elements in my theme.js

Can you share your code for that? You shouldn't need to do it the way you have above with the nested Box.

The way you can do this is extend the rebass component with your desired defaults, then overwrite when necessary:

import { Heading } from 'rebass';

const ExtendedHeading = props => <Heading color="blue" {...props} />;


<ExtendedHeading>Blue Heading</ExtendedHeading>
<ExtendedHeading color="red">Red Heading</ExtendedHeading>

Here is an example in a sandbox: https://codesandbox.io/s/5k9rx0z5ql

Seems like unnecessary boilerplate just to override a default setting. Isn't the purpose of theme.js to allow easy configuration of default styles?

Ah, I didn't know you could set component defaults within the theme.

In that case I totally see what you're saying, you should be able to override those default values when using the component if needed.

Unless I'm also missing something it feels like a bug to me.

@steverecio Not a great and overly verbose, but this seems to solve it inline for now:

<Heading theme={{ Heading: { color: 'red' } }}>Red Heading</Heading>

🤔

Unfortunately setting a new theme also clears out all other default settings (fontSize, fontFamily, etc...)

This is related to CSS source order. The functions are applied in this order: https://github.com/rebassjs/rebass/blob/master/src/index.js#L42-L46 which means theme.Box styles will override any style props – the theme.Box object isn't really intended to set colors or other styles that have style props. If you want a default color on Box, I'd suggest extending the component and adding a default prop

I'm not trying to set a default color on Box. The issue is that I have default color set for Text and Heading elements in theme.js and I'd like to override those values inline. It seems like any props set inline on elements should trump any values set elsewhere.

I'm using Box as a shim to override Text and Heading defaults. doesn't override the color value set on Heading elements in theme.js

Sample code here: https://codesandbox.io/s/5k9rx0z5ql

Code copied here for clarity

Component code

<Heading color="red">Example</Heading>
<Heading>
     <Box color="red">Example Shim</Box>
</Heading>

theme.js

const blue = "blue";
const red = "red";

export default {
  colors: {
    foo: blue,
    bar: red
  },
  Heading: {
    color: blue
  },
  Text: {
    color: blue
  }
};

screen shot 2018-12-20 at 1 11 16 pm

The same applies to any of the components; I used Box as an example. There's a fundamental difference between style objects (which is 1:1 with CSS) and style props (which are functions from styled-system). theme.Text.color is setting the CSS property color, whereas the color prop, although it ends up as CSS, uses styled-system to pick up a color value from theme.colors. If you're trying to set a default color on a Text component, use defaultProps.color but if you have non-styled-system styles that you want to add (e.g. anything that's not available as a prop) , use theme.Text

With the addition of the css prop support in babel-plugin-styled-components I'm considering dropping the theme style objects altogether for the official release since they seem more confusing than useful

Hmm ok. I've been using theme.js to set a standard style for all rebass components on my site and wanted to use the occasional style prop to override those settings. For anything more complex, I'm using the styled components library aka styled(Text). For a first time user, this behavior is kind of confusing as I'm not sure when to use rebass style props or define a styled component but I can say that it's been useful to easily access bg, color, etc except when they conflict with my theme.js settings.

Seems like the best solution is just to remove rebass components from my theme.js and use defaultProps instead

@jxnblk Does that mean that variants would go away too?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ferdinandsalis picture ferdinandsalis  Â·  5Comments

romainquellec picture romainquellec  Â·  3Comments

jamesknelson picture jamesknelson  Â·  4Comments

JaKXz picture JaKXz  Â·  4Comments

contra picture contra  Â·  5Comments