What is the recommended way to override border props on an extended component, since the border props from styled-system are not available on the Box or Card components.
For example, if I create a component like this:
import { Card as BaseCard } from 'rebass/styled-components'
const Card = React.forwardRef((props, ref) => {
return (
<BaseCard
ref={ref}
as="section"
sx={{
borderRadius: 's',
boxShadow: 'm',
p: 3,
bg: 'primaryColor',
color: 'primaryText',
}}
{...props}
/>
)
})
How can I override borderRadius when using the component? I would expect to be able to do something like this:
<Card borderRadius="m">A card with a bigger border radius</Card>
But since borderRadius styled-system prop is not available, then maybe I could try this:
<Card sx={{borderRadius: 'm'}}>A card with a bigger border radius</Card>
But this doesn't work as expected because the sx prop from the base Card component gets completely overridden.
One workaround I have found is to do this:
import { Card as BaseCard } from 'rebass/styled-components'
import merge from 'lodash/merge'
const Card = React.forwardRef(({ sx, ...rest }, ref) => {
return (
<BaseCard
ref={ref}
as="section"
{...rest}
sx={merge(
{
borderRadius: 's',
boxShadow: 'm',
p: 3,
bg: 'primaryColor',
color: 'primaryText',
},
sx
)}
/>
)
})
Then I can do this with the expected result:
<Card sx={{borderRadius: 'm'}}>A card with a bigger border radius</Card>
But it feels pretty horrible...
Another solution is to use the __css prop that is in rebass, which also frees me up to be able to use the sx prop to apply overrides:
const Card = React.forwardRef(({ sx, ...rest }, ref) => {
return (
<BaseCard
ref={ref}
as="section"
{...rest}
__css={{
borderRadius: 's',
boxShadow: 'm',
p: 3,
bg: 'primaryColor',
color: 'primaryText',
}}
/>
)
})
But this also feels bad because presumably __css is named with a double underscore because it's not part of the public interface and you don't want people using it.
Suggestions...?
I think this approach would be the most straight-forward for what you're looking to do (I don't think you'd need a deep merge), and yeah, the __css prop is not part of the public API:
sx={{
borderRadius: 's',
boxShadow: 'm',
p: 3,
bg: 'primaryColor',
color: 'primaryText',
...sx
)}
Ok, that makes senes. I guess if I need to do anything that requires a deep merge I could use the css prop for that since that overrides sx.
Out of interest, is there a specific reason why you don't expose the border props on the Box?
Great library by the way. We've been using this extensively in https://github.com/LN-Zap/zap-desktop for the last year or so and the latest versions are rock solid :)
Thanks! I鈥檒l have to check this project out!
Because there are so many CSS border properties and shorthand properties, it鈥檚 very easy to run into gotchas with the cascade. I鈥檇 rather limit the number of places for defining border properties so that things like defaultProps, inline props, and props set on extended components don鈥檛 cause styling issues, and borders in particular have been tricky for users of this library and Styled System. I鈥檇 rather set people up for the pit of success, and by keeping border properties in the sx prop, I think the styles can be easier to manage. You can always create extensions with custom props to make setting different border styles easier if needed. Hope that makes sense
@jxnblk I'm here because of __css! Any reason why that's not a part of the docs, with a better name perhaps? (like baseCss?). I see that the order of application is base, variant, sx & then others, but as you said, __css (base) is not exposed to public.
Something like that gives me the ability to localize base styles (for eg. in Button component, like you do in rebass), while also letting me use sx etc. as if my component library was a part of rebass.
I think this makes a lot of sense for reflexbox, as it extends it's use case as a component library builder
Currently I have frozen version of reflexbox & am using __css to create components similar to rebass Button.
Not sure if this idea has been proposed/discussed earlier. If we can agree on some API, I could raise a PR :)
(Also, thanks for making this great library & all the patterns, especially styled-system/theme spec! I have been reading a lot of your blogs & it's very helpful!)
@palashkaria the __css API is private because it's not an ideal solution and it could break with an update, but I would like some public API to support similar functionality. You can use the sx prop like described above for the time being
@jxnblk Solution with spreading both objects works fine until you work with objects but sx allows also a function. Current types shows errors when you try to merge that way. I've skimmed through rebass/styled-system repo to find some helpers for merging styles and failed to find one.
It would be nice to use css from @styled-system/css but right now it accepts only one object. Extending it that it'll accept array will solve merging problems. It could work the same as in css from @emotion/core. https://emotion.sh/docs/composition
@jxnblk Solution with spreading both objects works fine until you work with objects but
sxallows also a function. Current types shows errors when you try to merge that way. I've skimmed through rebass/styled-system repo to find some helpers for merging styles and failed to find one.It would be nice to use
cssfrom@styled-system/cssbut right now it accepts only one object. Extending it that it'll accept array will solve merging problems. It could work the same as incssfrom@emotion/core. https://emotion.sh/docs/composition
@jxnblk I think based on the fact that sx can be a function, this should be reopened
Most helpful comment
@jxnblk Solution with spreading both objects works fine until you work with objects but
sxallows also a function. Current types shows errors when you try to merge that way. I've skimmed through rebass/styled-system repo to find some helpers for merging styles and failed to find one.It would be nice to use
cssfrom@styled-system/cssbut right now it accepts only one object. Extending it that it'll accept array will solve merging problems. It could work the same as incssfrom@emotion/core. https://emotion.sh/docs/composition