-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Emotion 10 #637
Comments
This looks great. I like this API quite a bit. Are there any downsides that we should address? |
The main downside is that it'll be hard to get class names outside of render if you're using the new APIs, that's intentional though. Another smaller thing that I haven't really figured out yet is /** @jsx jsx */
import jsx from '@emotion/jsx'
import keyframes from '@emotion/keyframes'
import css from '@emotion/css'
const animation = keyframes(css`
from {
color: green;
}
to {
color: hotpink;
}
`)
const Comp = () => (
<div
css={[
{
animation: `1s ${animation.name}`
},
animation.styles
]}
/>
) which is pretty inconvenient since you have to pass in the name and the styles, for string styles we could interpolate the animation object and insert the animation but for object styles we can't do that since we only have a string when we interpolate the object. Any thoughts on how we could solve this? |
What is the argument behind this? IMHO it brings unnecessary config right from the start when one wants to use
IMHO consistency is better, so I'd vote for keeping
Even if the feature is not actively developed and in non-ideal state, I don't quite see why should it be removed. It surely has some audience, brings some benefits to the users and having it might encourage outside contributors to make it cover more cases. |
I'm not sure if you're referring to using a babel macro or including the tag list by default so I'll talk about both
It requires some runtime code for styled so removing it would mean styled would be slightly smaller. (I know the amount of code it uses isn't very big, it still helps though) While extractStatic may have some small audience, other libraries do a better job of it so there's no reason people should use emotion over those other libraries. Also, explaining it in the docs is hard because we have to essentially say "we have this thing, it doesn't work very well, we don't recommend it and we're not planning on improving it but it's still here". If we did keep it and contributors improved it, it would still likely require you to follow certain rules to make it statically analyzable which would limit the power of css-in-js. |
That is true, |
Never liked |
Really excited about the direction of this. Had a couple of questions while thinking about what I might need to update. If the css prop will be the favored approach do you envision most components having a bunch of outer scope variables for these styles? I really enjoy the css prop pattern, but it messes with the readability of a complexly styled components. This will somewhat involve class naming for the variables. e.g.
Does this means for optimal perf we'll need to use
Does this mean doubling the number of dom elements or is it just a React implementation of the element? |
Could you give an example of what you would write now for that case?
It only means you'll always be able to use
I'm not sure if I totally understand what you mean but the only time when there will be more dom elements is when doing SSR and style elements get rendered. You can look at how it works here |
Here's a meaty one:
Ok, so nothing changes if we're using the babel plugin already. 👍 My concern was that it would be more performant in dev to use the whitelist, but fewer bytes over the wire with the macro (hence a different import depending on env.)
Cool, then this won't affect my project atm, but my concern was adding another dom node for every css prop used on the page. For large pages I'd imagine this could add overhead. Losing |
Sorry, I meant one that would be different with the css prop in regards to this comment. As in, how would the readability change from how it is now and how do you have to name more than in the past?
The reason that it isn't done automatically is that if we did it in the babel plugin there would be cases where it wouldn't work and if we did it at runtime it would mean checking every single selector which would be expensive. |
Most of the examples and docs so far use inline styles for the css prop. It seems like the goal is to move toward that and away from I thought this might work |
Hey guys! Quick question: Wouldn‘t it be cleaner to have a customized Just a thought 😉 Btw, great stuff, though 😊 |
@andywer Thank you for your opinion! However, as far as I think, it will make emotion too strongly depending on reconciling mechanism of react. The element structure of react is not that big stuff, but reconciling mechanism, especially after React@16, is quite big and complex one... |
@andywer Just to be clear, we're not patching createElement, we're providing a function that you explicitly use instead of createElement. IMO, creating a custom reconciler would be so much more complex, require a lot of work(and maintenance over time since it would have to be changed every time that react-dom was changed) and wouldn't really have any significant advantages over a custom createElement. Also, what do you mean by "cleaner" and why is having a custom reconciler "cleaner"? Also, having a custom reconciler would make it harder to share components since you would have to make people use the custom reconciler as well rather than just exporting a component and using it with react-dom. This is especially important because one of the goals with this was to make it possible to create components with styles that can be imported from npm and just work without any configuration including with server-side rendering. |
Can you point me in the direction of what you mean by this? I've done some experimenting with https://github.com/emotion-js/next and its worked an absolute treat. Feels really clean/simple, and as you said, SSR just works since the style tags come out as part of the standard rendered react component tree. One good argument in favour of using things like the Is that something that is or could be addressed with this new approach of rendering style tags within react? This has got me thinking though - already with SSR you duplicate the HTML (the SSR HTML version and the javascript/React version). I guess this is just an extension of that. |
@hedgepigdaniel The caveat I'm referring to is that The new approach doesn't change anything with regards to static extraction. I'm not very interested in static extraction right now, I personally find the trade offs not worth the benefits. I think that the only practical way to do static extraction without big trade offs is with something like prepack. |
Ah cool. Since the box is checked... where is the alternative SSR API? If I do |
@hedgepigdaniel the alternative api is using the current emotion ssr apis with the compat cache. You can see an example of it in the tests, |
How's going to work the custom Do they support the |
I highly doubt they disallow jsx pragma, so it should "just work" with the mentioned |
Is there a way to disable pragma with |
@mitchellhamilton so with this refactor it looks like I can't use the component as a selector somewhere else. e.g. 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 |
@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? |
What do you mean by
After hooks are stable and #967 is in, you'll be able to use hooks like useContext inside of interpolations. |
@mitchellhamilton would 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.
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) |
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.
We don’t use refs at all, refs are forwarded to the inner element.
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? |
Is there a workaround to having to add |
Unfortunately, because CRA does not allow babel configuration, you cannot update the pragma via |
@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 added
Also: Then ran 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 |
@slikts I don't think the |
I installed 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
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. |
Your example still works.
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 |
It doesn't, the |
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 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
The text was updated successfully, but these errors were encountered: