Skip to content

Understanding how the sx prop works, sx prop object composition, etc #839

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
erikdstock opened this issue Apr 10, 2020 · 6 comments
Closed

Comments

@erikdstock
Copy link

erikdstock commented Apr 10, 2020

I think understand the jsx pragma but have a couple questions about sx.
1: The pragma does not seem to be necessary for theme-ui components such as <Box />, but is is for the native/intrinsic html elements such as <div />s. Is this correct?

2: Perhaps ill-advised, I wanted to create a custom component that would have its own internal styles that could be overridden, essentially ({ sx = {}, ...props }) => <Text sx={ ...rootStyles, ...sx } ...props />. This did not work when using the jsx pragma, which leads me to think babel is actually wiping away my non-standard sx prop - I can even log it and see that it is always {}. Is this assumption correct? I can probably just work around it using variants and plain text in any case, but wondering.

@dburles
Copy link
Contributor

dburles commented Apr 10, 2020

  1. Correct, though there's no reason not to use it as you'll probably be mixing them with your own components or elements.

  2. All you need to do is ensure that the className prop is passed through to the child element.

const Button = (props) => {
  return (
    <button
      {...props}
      sx={{
        backgroundColor: 'red',
        padding: 3,
      }}
    />
  );
};

export default Button;

@erikdstock
Copy link
Author

erikdstock commented Apr 11, 2020

Ah, thank you. I probably would have continued overlooking that. Caught some bugs, forgotten spread operators mostly thanks to this. For the record this is what I was trying to do to match a legacy api- if anyone has thoughts on ways to clean it up more I'd love to hear them:

export const StyledText: StyledTextComponent = ({
  bold,
  italic,
  danger,
  faded,
  sx = {},
  children,
  ref,
  ...props
}) => {
  // { color, fontWeight, etc }
  const textOverrides = getTextStyle({ bold, italic, faded, danger })

  return (
    <Text
      as="p"
      sx={{ ...textOverrides, ...sx }}

      // necessary for type-checking: Type 'string' is not assignable to type 'Ref<HTMLDivElement>
      ref={ref as any}
      {...props}
    >
      {children}
    </Text>
  )
}

// usage with text variant
export const Lead: StyledTextComponent = ({ sx, ...props }) => {
  return <StyledText as="h3" variant="lead" sx={sx} {...props} />
}

// usage with an html tag
const aStyles = themeGet<SystemStyleObject>("styles.a")
export const StyledA: StyledTextComponent<React.ComponentProps<"a">> = ({
  sx = {},
  ...props
}) => <StyledText as="a" sx={{ ...aStyles, ...sx }} {...props} />

@dburles
Copy link
Contributor

dburles commented Apr 13, 2020

There's no need to try to capture the sx prop as it's not passed through, just freely use sx on any components where you've defined the theme-ui pragma and they'll work magically.

@erikdstock
Copy link
Author

There's no need to try to capture the sx prop as it's not passed through, just freely use sx on any components where you've defined the theme-ui pragma and they'll work magically.

Does this apply if i'm specifically trying to override an inner component's styles for some reason? What about (hope my long-term understanding of react isn't off here) components that perform some side effect but pass their children through without rendering a DOM element of their own?

@dburles
Copy link
Contributor

dburles commented Apr 16, 2020

If you wish to override inner styles, you can use child selectors, or for constraint, implement a variant prop which gives a fixed range of styles applied across each element (See: #294 and #800) for some ideas on that.

A component that only renders children will swallow any styles applied to them since they'll ignore the className prop they receive.

Hope that helps some!

@erikdstock
Copy link
Author

Thanks! Closing as my immediate issue is resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants