Skip to content
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

Classname not compiled/passed-through for wrapper components #713

Open
JohnRoseDev opened this issue Mar 20, 2021 · 7 comments
Open

Classname not compiled/passed-through for wrapper components #713

JohnRoseDev opened this issue Mar 20, 2021 · 7 comments

Comments

@JohnRoseDev
Copy link

JohnRoseDev commented Mar 20, 2021

Do you want to request a feature or report a bug?

Not sure if bug or feature

What is the current behavior?

When using a native div element like <div className='bla' /> things work as expected and a "jsx-1234 bla" class name is generated, however, if set to a wrapper component like <Container className='bla' />, which under the hood passes className to a div, the classname is not compiled but simply stays "bla" on the div element, consequently the styles are not applied.

What is the expected behavior?

I would not expect styled-jsx to be limited to native elements since building wrappers and abstractions is a very common pattern in react. I would think the "jsx-1234" should be passed down to the div element inside the wrapper component.

Environment (include versions)

  • Browser: Latest Chrome
  • styled-jsx (version): 3.4.4

Did this work in previous versions?

Not sure

@EduardoRicardez
Copy link

I'm having the same issue, i can't style my formik forms :(

@ThetripGr
Copy link

same here and following the example for using css.resolve does not work either

@JohnRoseDev
Copy link
Author

JohnRoseDev commented Jul 14, 2021

Hello @vercel, are you aware of this? This is a major problem for this library to be used in realistic react use cases. Everybody creates (or uses existing) wrappers and ui component libraries for their react projects, and for all these components the className is not compiled correctly by styled-jsx.

@jaspersorrio
Copy link

Due to this behaviour, we are forced to create wrapper components around 3rd party components causing an excessive DOM size.

https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Feezee.sg%2Fbrands%2Faccsafe&tab=desktop

@vercel, if possible please look into this as it has become antithesis to what next.js is trying to achieve.

@errnesto
Copy link

errnesto commented Aug 11, 2021

Right now if I have a wrapper component that looks like this:

const Wrapper = (props) => {
  return <div className={props.className}></div>
}

And I use it in a container:

const Container = (props) => {
  return <section className='container'><Wrapper className='my-wrapper' /></section>
}

When parsed with styled-jsx the html would look something like this:

<section className='jsx-1 container'>
  <div className='jsx-2 my-wrapper'></div>
</section>

So what we all are missing is the jsx-1 in the div.
I would be happy if I was able to add it manually like:

const Container = (props) => {
  const cssScope = useCssScope()

  return (
    <section className='container'>
      <Wrapper className=`${cssScope} my-wrapper` />
      <style jsx>{`
        .my-wrapper {
          color: red;
        }
     `}</style>
    </section>
  )
}

I could do something similar with resolve but that means I can't write my style definitions in the style tag which means they are kind of all over the place…


Right now my workaround is to use :global():

const Container = (props) => {
  return (
    <section className='container'>
      <Wrapper className='my-wrapper' />
      <style jsx>{`
        .container :global(.my-wrapper) {
          color: red;
        }
     `}</style>
    </section>
  )
}

@errnesto
Copy link

Oh also this is not the first time this is discussed… #573

@tobyleye
Copy link

tobyleye commented Jan 24, 2023

Here's a simple workaround for those still struggling with this issue. Essentially we apply a classname on a wrapper element in the parent and use it in combination with the :global() selector to target the child and style from it parent. it's also a good way to override child styles from the parent.

function Child({ className='' }: { className?: string }) {
  return (
    <div className={`child ${className}`}>
      child..
      <style jsx>{`
        .child {
          border: 1px solid red;
          width: 40px;
          height: 40px;
        }
      `}</style>
    </div>
  );
}

function Parent() {
  return (
    <div className="parent">
      <Child className="parent-child" />

      <style jsx>{`
        .parent :global(.parent-child) {
          border: 1px solid green;
        }
      `}</style>
    </div>
  );
}

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

6 participants