emotion-js / emotion

👩‍🎤 CSS-in-JS library designed for high performance style composition
https://emotion.sh/
MIT License
17.41k stars 1.11k forks source link

Difficulty understanding the usage of `cx` between packages #2152

Open neefrehman opened 3 years ago

neefrehman commented 3 years ago

Description:

I've just started migrating a project to emotion, and am struggling to understand the usage patterns of the cx function from @emotion/css, specifically around two areas.

  1. Short circuiting values for conditional classNames: cx(state && className)

    There's no mention of this in the documentation, only the object-based { [className]: state } method, but I see it is possible after testing it out. Is this considered a bad or deprecated pattern? I'm coming from another library which supports it, and prefer the approach.

  2. Including SerializedStyles from @emotion/react's css

    This doesn't work in cx, and forces me to use css from @emotion/css instead, but leaves me wondering if I'm choosing the right method for adding extra classNames? It feels like the react package should be the best css function to use, since I'm styling a React component. I think I would prefer there to be a version of cx exported from /react, which supports combining SerializedStyles as well so that I can remove the /css package, if that's possible.

Overall I feel like I'm juggling between three packages (/styled, /css, /react) a little too much, which often leaves me confused. Some extra documentation around these choices would be helpful.

Edit: in case it's useful, I prefer the styled method over the css prop method.

Documentation links: https://emotion.sh/docs/@emotion/css#cx

Primajin commented 3 years ago

Also weirdly looking at the node_modules/@emotion/react/types/index.d.ts it states an interface cx but it doesn't work to import cx from import {cx} from '@emotion/react';.

export interface ClassNamesContent {
  css(template: TemplateStringsArray, ...args: Array<CSSInterpolation>): string
  css(...args: Array<CSSInterpolation>): string
  cx(...args: Array<ClassNamesArg>): string
  theme: Theme
}

I would also prefer to only import one single module and then work with it the same way https://github.com/JedWatson/classnames works. So I'd rather import that for now than using three different packages of emotion.

Andarist commented 3 years ago

Those types don't declare a standalone cx helper but rather a function available to render prop of the ClassNames component.

max8hine commented 3 years ago

Same here, confusing on how to import cx method from @emotion/react instead of installing @emotion/css

masterambi commented 3 years ago

same here

cjnoname commented 2 years ago

Same. Anyone can help? It’s a pain people cannot import cx from emotion/react

vivaslj1 commented 2 years ago

I am using a hook within I need to use cx because there is a property called cellClass and i need to merge two classes. If i try use emotion/react, i can only use cx with (?? no sense, i don't render nothing there ???) so i must use cx from emotion/css...

It seems like i kind an error....

pietrop commented 2 years ago

I run into the the same issue. But Isn't this this supposed to be the answer? https://emotion.sh/docs/@emotion/react#cx

srmagura commented 2 years ago

If you're using @emotion/react or @emotion/styled, there is no need to install the @emotion/css package at all. The cx function from @emotion/css should only be used when generating class names with @emotion/css.

You can use the css function from @emotion/react to combine multiple object styles, CSS strings, SerializedStyles, .etc. The css function and css prop also support conditional styles like this:

const baseCss = css({ color: 'blue' })
const activeCss = css({ backgroundColor: 'gray' })

function MyComponent({ active }) {
    return <div css={[baseCss, active && activeCss]} />
}

The only context where cx is relevant when using @emotion/react or @emotion/styled is when using <ClassNames>, which is documented here.

I'm going to try to improve the documentation around combining CSS & conditional CSS using the css function since we don't currently have a great example of it.

gerardnico commented 6 months ago

Thanks all for this thread.

I add also my confusion and what I have understood about the migration from Emotion Css to Emotion React.

I landed here because I just needed to add a class string to a className from an external stylesheet (in my case for a icon class Name) and I didn't understand how to do it with Emotion React.

Before using Emotion React with Emotion CSS, I could do:

<div
  className= {cx('my-icon-class-name', props.className, css`....`)}
>
</div>

Easy to read (minimal boilerplate), easy to write, great! Thanks.

It took me some time to go over to Emotion React. From what I understand,

I didn't see any added value of Emotion React, except Server side rendering and a sort of cascading optimization. The css prop adds also an extra burden (typescript does not like it by default as any third-party UI library).

I'm just lost now on which option I need to take.

gerardnico commented 6 months ago

Quick Update: I migrated to the styled interface as:

It would be great to have one package (or documentation) that is configured towards the styling interface.

Example:

As a newbie, I was so confused.

And for cx, I have recreated it to concatenate classNames.

cx(...classes: (string | undefined | null)[]) {
        // Filter out null and undefined values
        const validClasses = classes.filter(arg => arg !== null && arg !== undefined);
        // Join the non-null and non-undefined strings with a space
        return validClasses.join(' ');
}

Thanks