Closed emmatown closed 5 years ago
That's odd but yes, it works! Thanks a lot :)
@Emiliano-Bucci, have you tried setting the jsx pragma in your babel config?
@mitchellhamilton in emotion 10, how would you handle the case where you have a base button and a theme button? https://gist.github.com/lifeiscontent/0c025a2fcb36cc9dc0848054411649c7
I'm really unsure what the refactor would look like here for theme button.
@mitchellhamilton thanks a lot. Sorry, just 1 more question in the BaseButton, there is an option to have a disabledClassName
, pressedClassName
prop, how would you forward that if it was created in this case?
I would probably use a child selector and target [disabled]
and [aria-pressed]
instead of the class names.
hmm ok, I guess I could do that.
@mitchellhamilton so with this refactor it looks like I can't use the component as a selector somewhere else.
e.g. css({[Button]: {...someStyle}});
how would I do that?
css`
${Button} {
color: red;
}
`
is how it works with template literals, I'm not sure about object notation
@FezVrasta it doesn't work with either in this case, probably due to something special that happens when you wrap a component using styled.div, etc.
@mitchellhamilton how would you use useContext
with a styled(Button)
?
@mitchellhamilton does css in Emotion 10 become the same as a styled component at render time. From what i can see in the react tab it appears to be the case, can you confirm?
does css in Emotion 10 become the same as a styled component at render time. From what i can see in the react tab it appears to be the case, can you confirm?
What do you mean by become the same as a styled component at render time
?. They have different implementations if that's what you're asking.
how would you use useContext with a styled(Button)?
After hooks are stable and #967 is in, you'll be able to use hooks like useContext inside of interpolations.
@mitchellhamilton would
Example1: const MyRedBox = <div css={css({backgroundColor:'red'})}></div>
be the same as
Example2: const MyRedBox = styled.div({backgroundColor:'red'})
I know the styles are obviously the same. From what i could tell it seemed like Example1
was wrapping itself around the <div>
tag that it was assigned to.
This must be part of the babel transforms that rewrite the output. This changes a lot of things and the expectation around the component and how they are being used. Maybe I'm wrong so i'm just trying to verify my thoughts. Thanks.
It's wrapping the output but the examples are different, the first one is creating an element, the second is creating a component.
This changes a lot of things and the expectation around the component and how they are being used.
such as?
such as?
The css prop becomes magical higher order components that are attaching to the ref of your element to add a class name. It seems like a lot of work just to add a class name. Is this so css will work with react-native, and other devices that don't support style sheets? What are the advantages to this approach (vs v9)
magical
Using magical to describe something is very unhelpful because it doesn’t really describe what’s wrong with something. Anything could be described as magical.
attaching to the ref of your element
We don’t use refs at all, refs are forwarded to the inner element.
What are the advantages to this approach (vs v9)
Also, something that’s important to note, we’re not getting of the old APIs, if you want to keep using them, you still can, you just won’t get the advantages of the new APIs.
@mitchellhamilton looks like there was an option to set displayName for a styled component in the babel plugin for emotion, how would you achieve the same thing in emotion@10? Is the babel plugin still required?
Yes, the babel plugin is still required for labels(except with the css prop with function components). It's enabled by default in the v10 babel plugin.
Does this work with react-native and are there any performance concerns?
You can literally just write a random jsx; statement anywhere in the file. Linters hate it!
Is there a workaround to having to add jsx
? I'm using CRA with TS and the @jsx
pragma and the unused jsx
statement make for a pretty ugly look. I suppose it's related to: https://github.com/babel/babel/issues/8958
Unfortunately, because CRA does not allow babel configuration, you cannot update the pragma via @emotion/babel-preset-css-prop
.
@slikts For CRA v1 you can use https://github.com/timarney/react-app-rewired to extend the config without ejecting. For the v2 there is https://github.com/sharegate/craco which I use and it works great! 👍 I'm not using TS so I'm not sure about the compatibility.
I added craco
and babel-plugin-emotion
and put this in craco.config.js
:
module.exports = function({ env, paths }) {
return {
babel: {
plugins: ["babel-plugin-emotion"],
},
};
};
Also: plugins: ["emotion"],
Then ran craco start
, with no effect, --verbose
just says craco: Added Babel plugins.
, and removing the jsx
statement still causes ReferenceError: jsx is not defined
.
I suppose there were reasons for these changes, but from my perspective emotion has taken a big step backward; it used to take just importing the template tag, but now I need to add 3 additional lines of noise: the babel pragma, the unused jsx import, and also an unused jsx
statement.
@slikts I don't think the @emotion/babel-preset-css-prop
preset is included in babel-plugin-emotion
.
See here : https://emotion.sh/docs/css-prop#babel-preset
I installed @emotion/babel-preset-css-prop
and added presets: ["@emotion/babel-preset-css-prop"],
to craco.config.js
, and now it claims to have applied the presets, but the only configuration that works is still with the 4 lines.
I liked emotion because it was minimal and elegant and allowed me to write CSS instead of object literals. Now it's Babel pragmas, unused imports, incompatibility with CRA/TS, and object literals in the main examples. It should have at least been released as -beta or -rc in the current state.
@slikts while I agree this takes more work, you can still use import { css } from 'emotion'
or import styled from '@emotion/styled'
just like you have been before. You do not have to use the css prop.
import styled from '@emotion/styled'
const Button = styled.button`
color: turquoise;
`
Now it's Babel pragmas, unused imports, incompatibility with CRA/TS, and object literals in the main examples.
We've always supported both objects and strings, still do. I don't know where you got this idea.
I didn't say they're unsupported, just that the examples in the readme and elsewhere used to use template literals. It would be just:
import { css } from "emotion";
render(<div className={css`
color: red;
`} />, root);
This was what I found elegant and why I used emotion; using CSS syntax, and having a clear model that, for example, you wouldn't have to explain to a colleague if they read your code. In contrast, the changes with pragmas and seemingly unused imports are hacky and fiddly. They're using a feature of Babel that I can't even find where it's documented, and I had to piece together what it is from a random blog post. The emotion readme just drops it there as if you'd be supposed to be familiar with it. Then, to actually use CSS syntax, I have to add an another import. I basically wouldn't even try to sell the new pattern to someone else who's possibly skeptical of CSS-in-JS as such, because it doesn't look good, requires an explanation, and even with an explanation it's like magic.
This was what I found elegant and why I used emotion; using CSS syntax, and having a clear model that, for example, you wouldn't have to explain to a colleague if they read your code.
Your example still works.
In contrast, the changes with pragmas and seemingly unused imports are hacky and fiddly. They're using a feature of Babel that I can't even find where it's documented, and I had to piece together what it is from a random blog post. The emotion readme just drops it there as if you'd be supposed to be familiar with it.
While it needs to be better documented, you do not have to use the css prop if you don't want it. https://emotion.sh/docs/css-prop is the only page in the documentation that shows object styles before string styles simply because that is what I prefer to use and it does not require and additional import. In order to use emotion you've always had to import the css
function just as you showed in your example. Using objects with the css
prop allows you to write styles without imports.
Your example still works.
It doesn't, the css
tag function returns an object, and I'd have to know to use the vanilla package, which anyone familiarizing themselves with the library would probably miss and just see the css prop and Babel pragmas. The very first example in the readme also uses object literals.
I basically wouldn't even try to sell the new pattern to someone else who's possibly skeptical of CSS-in-JS as such, because it doesn't look good, requires an explanation, and even with an explanation it's like magic.
This is a real issue, it is unacceptable to use the pragma as it seems hacky compared to styled-components. I won't introduce emotion because of this issue in a project...
The good thing is that no one is forcing you to do that. You also have @emotion/styled
API for grabs if you prefer using styled-components-like API.
We just don't believe that jsx pragma is a hack - you are free to feel to think differently.
Emotion 10 is going to introduce some new APIs for React users.
The main aim with these new APIs is to move all insertion to inside the React tree, this enables a couple of things:
createElement
(this isn't necessarily a result of moving things inside the React tree but a side-effect of the new implementation)The main new APIs are a custom
createElement
for the css prop and aGlobal
component for global styles.Example
If you want to try this, look at https://github.com/emotion-js/next but note that there will be breaking changes very often for now.
Another change that emotion@10 will bring is that
styled.div
and etc. will work without a babel plugin. The tag list will be included in@emotion/styled
but if you use@emotion/styled.macro
with babel-plugin-macros or the babel plugin,styled.div
will be replaced withstyled('div')
and@emotion/styled-base
will be imported instead which doesn't include the tag list.Compatibility with Preact and non-React-like libraries
While the majority of Emotion users use React, there are some users who don't use React and we have to figure out how to cater for them.
Non-React-like libraries
Since all the packages on the
@emotion
scope are very modular, we can build the current emotion APIs with the packages on the@emotion
scope. This should be pretty simple.Preact
There are only a few APIs that we use that are new.
Fragment
Fragments are only used for SSR so we could have an alternative SSR API for that similar to
extractCritical
now.createContext
We could tell people to use
create-react-context
and essentially polyfillcreateContext
.forwardRef
We could conditionally use forwardRef so if it's not available then we don't use it. I'm not a huge fan of this because I think it would be confusing to tell people they should use
ref
when using React andinnerRef
when using Preact but I'm not totally sure yet.The other option to all of this is to not support the new APIs on Preact and have Preact users use the current emotion API.
Migration
This is something I'm still thinking about and I've got some ideas about but nothing concrete yet. I'm thinking of migrating emotion.sh and seeing what's difficult, how to make incremental migration easy, what can be done automatically with codemods and what warnings would be useful to provide.
Removing
extractStatic
extractStatic
hasn't been something that we've encouraged for a long time so @tkh44 and I think it's time to remove it. For people who like static extraction, libraries like Linaria and css-literal-loader do static extraction much better than Emotion does so those people should use those libraries.Only do transformations when emotion is imported
babel-plugin-emotion
currently transforms anything with the names of emotion's exports. While this works it transforms things for other libraries (#626 and #344) so we should only transform . I want to do this in Emotion 10 since it could be a breaking change for some people.TODO
@emotion
keyframes
API more convenient@emotion/styled.macro
:first-child
and selectors like it are used and recommend replacements because of problems when rendering style elements in SSR and those selectors targeting the style elements.extractStatic
in babel-plugin-emotion and add a notice to the docs (if anyone wants to submit a PR for this, that would be great!!)extractStatic