Emotion: Getting descriptive CSS class names on all components?

Created on 9 Jul 2018  路  22Comments  路  Source: emotion-js/emotion

I've enabled the autoLabel feature and I'm getting nice descriptive CSS class names generated when I use css, as per the documentation.

Other components, or components from Rebass are still generated with base64 style random class names. Why is this? Is there any way to get descriptive class names for all components in development mode?

In the screenshot below, all of the war-garbled class names are actual Rebass Row components - I would expect them to have class names along the lines of Row css-112h9ht. Since emotion is able to generate a class name in the first place, it seems odd that it doesn't use the Display name in that process when using autoLabel.

screen shot 2018-07-08 at 4 28 04 pm

Most helpful comment

Any updates on this? Would make development a lot easier with descriptive names.

All 22 comments

From what I remember autoLabel is generates those readable classes at build time - would be harder to read .displayName for 3rd party components. Anyhow - algorithm certainly could be improved if possible, but you would have to share a code sample of those components which didnt get their readable names.

@Andarist Rebass has dozens of components in it, but here's one and they're all pretty much the same: https://github.com/jxnblk/rebass/blob/master/src/Button.js. The DisplayName is definitely set in the source.

One thing I noticed is that Rebass achieved emotion support via a simple Babel transform-rename-import pass: https://github.com/jxnblk/rebass/blob/master/.babelrc#L11-L26 I don't know if that would affect the autoLabel but it seems to be just doing a simple rename operation.

I would need to see how you coded to give you a definite answer but the fact is we can't see or infer all that much during compile time. We use a variable name if available or the name of the component being rendered in if we can't find anything else. We do not have access to the internal code structure for 3rd party components or even components you create yourself for that matter. We can only see what is in the code at the moment of compilation.

Just to be clear, in order to read a displayName from a component at compile time we would need to import the component, evaluate the code, and then check its displayName. With a library like rebass there are several layers of abstraction between when the style is defined and when it used. The className that emotion creates is not generated in the same code it is being used in so we do not have any additional context to add a label.

I'm going to close this issue because there is nothing we can do for it at the moment. Feel free to expand on the autoLabel feature and put in a PR.

https://github.com/emotion-js/emotion/blob/master/packages/babel-plugin-emotion/src/babel-utils.js#L86 is a good starting point.

What could be done though is compiling rebass/emotion with autoLabel option. Optionally they could expose dev build with it and prod one without.

It would depend on if the end user (developer) was importing compiled code or the es modules directly.

One possible solution that may work for everyone is adding the labels to the styles generated by rebass (system-components)

https://github.com/jxnblk/rebass/blob/master/src/Button.js#L24

For example a PR could be put into the rebass repo adding

{
  ...
  label: 'Rebass-Button'
  ...
}

It would depend on if the end user (developer) was importing compiled code or the es modules directly.

One possible solution that may work for everyone is adding the labels to the styles generated by rebass (system-components)

https://github.com/jxnblk/rebass/blob/master/src/Button.js#L24

For example, a PR could be put into the rebass repo adding

{
  ...
  label: 'Rebass-Button'
  ...
}

Sorry for the multiple comments. Github is having issues.

@tkh44 Thanks for the detailed explanation, I'll look into the label approach.

Any updates on this? Would make development a lot easier with descriptive names.

This is what you're looking for:
https://github.com/emotion-js/emotion/tree/master/packages/babel-plugin-emotion

Generated class names include the name of the variable or component they were defined in.

Hello. I know this issue is closed and hasn't been active for a while, but I just came across the problem with Rebass and I worked up a minimal example with create-react-app if that might help anyone troubleshoot: https://github.com/baddox/rebass-emotion-autolabel

I explained a bit more in this comment: https://github.com/rebassjs/rebass/issues/434#issuecomment-606805872

Hi all. We aren't using Emotion directly, but indirectly through theme-ui.

How do we set the autoLabel to be true, so we can have this being the case at build time? I can see when we are running in development enough of the classes have descriptive names to be useful, but want to know how to make this the case in production also.

@Andarist

Thanks! So what am I doing here? Adding theme-ui as one of these, then what?

{
  "theme-ui": {
    "?????": {
      "????": ["@emotion/react", "autoLabel as an option somewhere in here?"]
    }
  }
}

Thanks so much!

@conatus I've taken a look at the theme-ui API right now and it seems it's sufficiently different from ours that this won't be possible. I thought that it's closer and that this could work - sorry for that.

@Andarist

Thanks for that, really appreciated. My hope was that it, as it consumes Emotion as a dependency, would work.

I guess I could fork it, modify Babel configuration within to make the change, then just use this temporary fork for a while? It would be a one line change to the configuration.

It depends on what they do under the hood - I wont have time to check right now. I assume you are interacting with theme-ui mainly through their sx prop? If yes - try to add a label property manually to the object passed to that prop and check if the label has been applied to the generated class name

Thanks @Andarist - I will check that out and see how it goes. Really appreciate you taking the time to take a look for me.

@conatus Theme UI passes label along to Emotion's CSS, so you can work around it manually like Andarist said.
This is something to do on Theme UI's side. Let's move to the discussion you made in theme-ui.

It could be checked how do we handle adding labels for cases like this:

;<div css={{ color: 'hotpink' }}/>
var identifier = { color: 'hotpink' }
;<div css={identifier}/>

If it works OK then maybe we could add an option to configure the "css prop name" - although we'd have to recheck what else would be influenced by this and I'm worried that this might have too quirky consequences.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

MrFungusEli picture MrFungusEli  路  3Comments

AlexanderProd picture AlexanderProd  路  3Comments

mitchellhamilton picture mitchellhamilton  路  3Comments

kentcdodds picture kentcdodds  路  3Comments

Aaron-Pool picture Aaron-Pool  路  3Comments