This is maybe a question about design rather than a specific bug.
emotion version: 10.0.6react version: 16.4.2Relevant code:
Previous emotion 9 code:
let carousel = css`
.. some carousel styles
`;
let dots = css`
..some dots styles
`;
<div className={cx(carousel, className)}>
<Slider dotsClass={dotsClassName || dots}>
{children}
</Slider>
</div>
className and dotsClassName are custom class names you can pass down to the component to customize it.
What you did:
Now with emotion 10 im not even sure how I would write this in a clean and concise way.
I did get it to work with this:
let carousel =`
.. some carousel styles
`;
let dots = `
..some dots styles
`;
<ClassNames>
{({ css, cx }) => (
<div
className={cx(
css`${carousel};`,
className,
)}
>
<Slider
dotsClass={dotsClassName || css`${dots};`}
>
{children}
</Slider>
</div>
)}
</ClassNames>
But this seems like a really cumbersome / hard to read with ClassNames (alot more jsx and harder to follow imo)
I know its probably not the best practice to be passing class names to components (anti pattern) but in this case Slider is a 3rd party component and the only way to customise its styles is to pass down a class name.
Suggested solution:
Not sure - maybe there is a better way to write the above that im missing from the docs.
Facing the same here, that's a really ugly approach and I agree with your points. Sailing through de docs I couldn't figure out a better way to solve it. Now I got something like when styling a disabled button:
in style.js:
let bigStyle1 =`
.....
`;
let disabledStyle = `
.....
`;
in my component return:
<ClassNames>
{({ css, cx }) => {
const buttonStyle = cx(
css`${bigStyle1}`,
{[css`${disabledStyle}`]: disabled}
)
return (
<button
type={type}
disabled={disabled}
onClick={onClick}
className={buttonStyle}
{...props}
>
{text}
</button>
)
}}
</ClassNames>
@lucasgdev - This issue involves passing a proprietary prop to a 3rd party component that expects a CSS className (e.g. dotsClass from the Slider component).
I think you still have the straightforward case of styling an HTML button with multiple style definitions and can pass an array to the css prop as follows. When disabled is false, the second array value (false) is ignored by emotion.
return (
<button
type={type}
disabled={disabled}
onClick={onClick}
css={[bigStyle1, disabled && disabledStyle]}
{...props}
>
{text}
</button>
)
Just import css and cx from 'emotion' instead of '@emotion/core'.
It returns the name of the class.
@acnebs can do that but im no longer using that dependancy - only installed @emotion/core as per docs
Prefer not to use the legacy emotion lib
The proper way to pass classes to 3rd party components is to use the ClassNames component from @emotion/core.
<ClassNames>
{({ css }) => {
const classNameUsableOn3rdParty = css`color: red;`;
return <Foo someClassName={classNameUsableOn3rdParty} />
}}
</ClassNames>
@FezVrasta The purpose of this issue is that this is a very clunky solution in many use-cases. I don't want to define my css in-line except in the rarest of cases, but the <ClassNames /> solution requires you to define your css in your render.
I'm sorry I didn't understand that was the issue's purpose, reopening 馃憣
Something I do very often is this:
<ClassNames>
{({ css, foo = css`color: red;` }) =>
<Foo someClassName={foo} />
}
</ClassNames>
But it has issues with Flow types because the signature is invalid, I opened a PR to fix that but it's stuck.
https://github.com/emotion-js/emotion/pull/1324
I would propose to close this and focus on a React Hook solution as proposed in this issue. What do you think?
I don't want to define my css in-line except in the rarest of cases, but the
solution requires you to define your css in your render.
@acnebs this is not quite true - you can define your styles outside of render and only call css with them as an argument inside the render callback, like here: https://codesandbox.io/s/emotion-z8jpe
That being said - we'll rethink how this problem can be handled right now. We are working on a v11, so we'd like to address problems like this. The solution is not obvious - so no promises yet, but please know that we are going to think about this.
@lucasgdev - This issue involves passing a proprietary prop to a 3rd party component that expects a CSS className (e.g. dotsClass from the Slider component).
I think you still have the straightforward case of styling an HTML button with multiple style definitions and can pass an array to the css prop as follows. When disabled is false, the second array value (false) is ignored by emotion.
return ( <button type={type} disabled={disabled} onClick={onClick} css={[bigStyle1, disabled && disabledStyle]} {...props} > {text} </button> )
Thanks @ryanswanson I was looking how to do this conditional classes based in boolean props and you save me! ;)
Most helpful comment
Just import
cssandcxfrom 'emotion' instead of '@emotion/core'.It returns the name of the class.