Theme-ui: [Question] How to implement custom component aware of `sx`?

Created on 17 Jun 2020  Â·  7Comments  Â·  Source: system-ui/theme-ui

Hi, I'd like to write a custom component based on theme-ui elements with a structure where children are aware of sx prop of the parent.

Let say:

export const FooComponent = forwardRef(
  (
    { sx: sxParent, ...rest },
    ref,
  ) => {
    console.log(sxParent, rest)

    return (
      <Box {...rest} ref={ref}>
        <Text sx={{ backgroundColor: sxParent.backgroundColor || 'black' }}>
           foo
        </Text>
      </Box>
    )
  },
)

I noticed that if in the file where I call FooComponent the jsx pragma is present then sxParent is converted to a { className: 'css-wo3z44' }, otherwise it is the original object (let say a valid SxStyleProp object).

How can I handle this? Should I need to parse the css-wo3z44 somehow?

Most helpful comment

I never use the jsx pragma, and instead passthrough sx to the underlying theme-ui component, eg.

export const Foo = ({ sx, ...props }) => (
  <Box sx={{ m: 3, ...sx }} {...props}>…</Box>
)

All 7 comments

jsx pragma parse sx object to className before component will be rendered, if you want to pass object itself then you need to remove pragma in file you pass that sx prop

Yes, sx prop is transformed by jsx pragma, similarly to how Emotion's jsx pragma consumes css prop.

You can use any other prop name. If you want to reuse a name you're already using, style should be okay, albeit a little confusing. I'd probably go with styles or pass just backgroundColor as a prop.

Yeah, other prop name than sx also will help :)

I ended up moving most of my customizations into a variant prop and then merging styles in the parent and the variant passed by the child.

https://github.com/ccontrols/component-controls/blob/99c25f1a3bd3481b8a8df4ddc7310a4f5ff41cda/ui/components/src/Tag/Tag.tsx#L44

I never use the jsx pragma, and instead passthrough sx to the underlying theme-ui component, eg.

export const Foo = ({ sx, ...props }) => (
  <Box sx={{ m: 3, ...sx }} {...props}>…</Box>
)

Thanks!

Also you could just pass the className :

export const Foo = ({ className }) => (
  <Box sx={{m: 3}} className={className}>…</Box>
)

Then both sx (Parent and Children) will be gather
https://codesandbox.io/s/theme-ui-children-sx-d4940?file=/index.js

Was this page helpful?
0 / 5 - 0 ratings

Related issues

muhajirdev picture muhajirdev  Â·  3Comments

Everspace picture Everspace  Â·  3Comments

VinSpee picture VinSpee  Â·  3Comments

moshemo picture moshemo  Â·  3Comments

blummis picture blummis  Â·  4Comments