emotion-js / emotion

👩‍🎤 CSS-in-JS library designed for high performance style composition

Home Page:https://emotion.sh/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

The docs have taken a sharp downhill turn with v10

jaredLunde opened this issue · comments

The documentation for v10 needs some work. v10 isn't a small API change, it completely changes the way a user has to interact with the library. I have used emotion on all of my projects for over a year so it's not like I'm a newb to this library. If it's hard for me to understand just what is going on I can't imagine the hurdle for actual newcomers.

Given the obscure API that comes with this version (@emotion/core vs emotion, jsx as an used import?This pragma is supposed to be more clear/easy to use than a babel plugin? ), it would be nice if each of these new packages had their own documentation, since apparently they're all completely different. As it stands you have them all randomly strewn about with notes like 'you only need this if...'

Grant you I'm coming at this from a place of general negativity because I've disagreed with this direction from the start (gave a thumbs down on your initial proposal for example), but those feelings are compounded by the fact that the migration guide isn't at all clear. It makes suggestions about moving from emotion to @emotion/core but still says elsewhere in the docs you can still use emotion. OK. Well, when should I use each? Why should I use @emotion/core over emotion? What am I missing out on by not doing so?

I really hope this issue with the docs gets ironed out. I'd help, but clearly I don't understand the API as it is so I don't have anything to offer. The only concrete suggestions I have are that you create completely separate sites for emotion and @emotion/core and highlight whatever the differences are somewhere in addition to explaining more clearly what jsx is for. Some more clarity about the new css prop usage would also be nice.

I have to agree here. I am a huge fan of this project, but I can imagine looking at v10 with fresh eyes and being too confused to jump in, or deciding to look at other projects. The opposite was true when I saw the first version of the docs circa v6 (or 7?). Intuitive, simple, powerful.

This is a completely valid criticism. I think we can address a few items to make this better for our users.

  • Link to the v9 docs at the top(merged in #1070)

  • Introduction needs to be rewritten and should proabably reflect the docs we had for the old doc site as @staylor mentions above. A simple rundown of the features without all the caveats. We can save those for the detailed docs on the nav bar.

  • Remove the ambiguity between the react and non-react versions of emotion. We should have a dedicated doc to the non react version linked on the sidebar.

  • #1049 should be merged and the docs should show this as the recommended way to set up the css prop with the manual pragma being the fallback.

    • This will require more explanation for certain cases where it could cause some confusion.
  • Any docs referencing previous versions of emotion should be moved to the migration guide (e.g. https://emotion.sh/docs/ssr)

  • Next.js, Gatsby, and Puppeteer sections from the SSR docs should be their own pages with links directly from the sidebar. This should be done even if, for example, the Next.js docs just say, "It just works".

  • Package links in the right hand nav need to be culled to only show relevant packages for emotion 10.

This list is obviously not complete and it would be very helpful to point out specific pain points in this issue that are actionable so we can get them addressed. Also, if you see some documentation that is confusing please feel free to open a PR with better wording or general edits. Any changes made to the documentation markdown files is automatically reflected on the site so there is little friction to getting any changes live.

I feel like we can all work together to improve these docs. I truely appreciate you calling us out and hope both you and others can help point out specific issues in the docs so they can be addressed.

#1049 should be merged and the docs should show this as the recommended way to set up the css prop with the manual pragma being the fallback.

I kind of disagree with making the preset the recommended way to use the css prop. The pragma works everywhere whereas a babel preset can't be added in certain places(like create-react-app) and maybe i'm wrong but I think the default should work everywhere.

Maybe we should have a dedicated create-react-app page? Its probably the most popular (for better or worse) setup and it would be nice for those users to have a single point of reference. What do you think?

Yeah, maybe that would be good, I still kind of think the idea of having adding configuration being the default isn't great though but if other people really like it then I won't prevent it from changing.

One thing I have been looking for is clearer documentation around the use of pseudo classes. I've beed doing the upgrade to version 10 and received an error about :first-child being unsafe for SSR. I'm looking for docs on why that would be the case so I know what things to stay away from when writing out my styles.

@jhoffmcd SSR renders style elements as part of the component (so u end up with MANY style elements when SSRing, but that's not a perf issue anyhow). By doing so only SSR just works - it has a caveat though that first child is a style tag and this makes this pseudo selector "unsafe". I agree that it would be good to at least turn this warning off as not everyone is doing SSR.

Idea - not sure if possible, but maybe it would be possible to rewrite :first-child to make it just work? Something like this http://jsfiddle.net/3v50ynkx/ , cc @mitchellhamilton

I'm also not a big fan of the new docs/approach. It's probably not a right issue to complain, but I fully agree with @jaredLunde.

I've been using emotion for over a year in multiple projects. And I'm a big fan of the library. Because of simplicity of css returning a class name, that I can pass to className, mix using cx, and have a nice server-side rendering.

After 40 minutes of reading docs, it seems, that the way to keep this workflow is to use old emotion package (https://emotion.sh/docs/emotion). But it refers on the new version, doesn't have Global, and it's not possible to understand the underlining simplicity from a new user perspective.

How is v10 simpler than v9?

v9:
screenshot 2018-12-05 at 18 03 51

  • css returns the class name, that passed to className. Simple.

v10:
screenshot 2018-12-05 at 18 04 23

  • What is css property?
  • Why should I redefined the React's default pragma?

Defining /** @jsx jsx */ in every file (usually hundreds) seems like a bad default.

Hmm. Add me to the list of people who love emotion 9 and hate emotion 10.
It's not an evolution, it's a totally different approach that over-complicates something that was simple and beautiful.
I don't want to put a css property in my div and confuse my IDE.
I don't want to use a babel plugin.
I don't want to use a JSX pragma.
This is terribly disappointing.

@dperetti old APIs (styled etc) are usable in emotion@10 as is without any problems, you basically have to make near to 0 changes when upgrading

A few things that should be documented:

  1. How long will the old-style APIs be supported?
  2. Will there be issues if you're using a UI library that's on Emotion 9, but your app has moved onto Emotion 10, or vice versa (library on 10, app on 9).
  3. It'd be nice to have a roadmap of upcoming features.
  4. For babel-plugin-emotion, It's been stated that you should use macros intead if you're on create-react-app, but maybe mention that it's possible to use react-app-rewired with customize-cra to add Babel plugins. I've done this successfully with CRA & Emotion 9's Babel plugin.

Another suggestion is to help those of us out that are still on v9 docs.

  • Currently, any links from emotion v9 docs to GH currently points to master. (links from here, here, and here for example and just the main "Github" link at the top). They really should be pointed to the last tag for v9 perhaps.
  • Can we do a simple header color change for v10 docs for differentiation? Just so v9 people know where they are at when they read the docs? Or when they're linked from an outside source like StackOverflow?
  • Can the v9 docs have a switcher back to v10 for those that are in a transition phase?

For the core team, I get that tightening up v10 docs is your main priority but a lot of us won't/can't move off of v9 for the moment for a variety of reasons. Still, I can imagine a good chunk is still on v9 and reference the docs daily so I think that supporting v9 users in this transition phase is definitely something to prioritize as well.

I'm working through this upgrade now on a decently large Gatsby site. I'm stumbling through trying to figure out which packages I do or don't need for which features and it's quite unproductive and frustrating.

  • Do I still need emotion if I have @emotion/core? What about emotion-server? react-emotion? babel-plugin-emotion? I also have gatsby-plugin-emotion which declares @emotion/babel-preset-css-prop.
  • What suite of imports, obnoxious pragma statements, babel plugins, and linter overrides do I need to be able to use the v10-style css prop (which I've been using in Emotion 9 anyways) and not have to declare a linter-breaking pragma at the top of every file? Can I still use eslint-plugin-emotion codemods to help port over the existing codebase?
  • What do I do to keep import * as React from "react" for clarity and to keep from having to go back and add it when I use React.createRef, React.createContext, React.Component, React.PureComponent or React.Fragment?
  • Can I still use React.createElement(someElement, props)? What if props contains { css: css`color: hotPink;` }? Will that break?
  1. I believe if you are using Gatsby, you should only need these packages:
gatsby-plugin-emotion 
@emotion/core 
@emotion/styled
  1. I have seen people build in the pragma in a webpack workflow but I can't remember where the documentation is. eslint-plugin-emotion will take care of it for the most part.

Im not sure about your other questions though. I would be interested to set up a quick test and see what happens when you use non-jsx methods of rendering components.

@jhoffmcd Thanks for the response.

  1. I think you're correct here.
  2. I'm not sure if it's something Gatsby is doing, but it appears using gatsby-plugin-emotion negates the need for the pragma.

I've also had to disable eslint-plugin-emotion rules because they're not compatible with the Gatsby package. For example, this code produces a linter error saying “The css prop can only be used if jsx from @emotion/core is imported and it is set as the jsx pragma”:

import * as React from "react"
import { css } from "@emotion/core"

const demo = () => (
  <div
    css={css`
      color: hotPink;
    `}
  >
    Hi!
  </div>
)

In reality, this works fine when using gatsby-plugin-emotion.

I just spent the better part of yesterday migrating several libs from 9 -> 10 and have some notes that answer some of these questions.

emotion vs @emotion/core

  • If you utilize react-emotion, SSR or think you may at some point, definitely use @emotion/core
  • BUT if your existing code relies heavily on the concept of css returning class names, you're gonna have a bad time. It's a pain and a slog determining when to use the ClassNames component vs. just refactoring things. It may be better for you to continue using emotion and gradually ween yourself off.
  • You should NOT use these packages together IMO. It's causes confusion that only gets worse when you think in SSR terms, because you'd still have to use renderStylesToString. This is a pain if you're like me and utilized injectGlobal in a lazy loaded fashion. Global doesn't allow for this lazy-loaded style of global insertion because it will render a <style> tag anywhere Global is used and will remove that tag when Global is unmounted.
  • If you do use the libs together, it will not drastically increase the size of your app, because they share internals.
  • Not to jump on anyone but the idea that you have to make zero changes when upgrading is completely false. It's a whole new way of thinking and I had to make drastic changes. It wasn't trivial because it's not like you can just do a big find/replace. I had to go through libs individually and search for nuance. You're not dumb if you're struggling. It's a LOT of work to migrate.

jsx pragma usage

  • This pragma works by wrapping React.createElement and inserting Emotion logic to retrieve/insert the class name. It also inserts a <style> tag when it needs to. If the render phase is taking place in node (SSR), it wraps your component and <style> tag in a React.Fragment. If your css prop is a function, it will also retrieve a theme with ThemeContext.Consumer
  • If you used something like React.createElement(someElement, props) and have css in those props, yes, it will break. You'd have to import {jsx} from '@emotion/core and jsx(someElement, props) instead.
  • It's easy to forget to add // @jsx jsx to the top of your files. Way too easy. Magic the process away with @emotion/babel-preset-css-prop if you can
  • Using the jsx pragma means you no longer need emotion-server. I've found this to be a big win for SSR perf. 👍🏽

Which babel plugin/preset should I use?

I know @emotion/babel-preset-css-prop was added to remove confusion, but in the process it made selecting the right plugin/preset confusing. However, having taken that confusion upon myself:

  • Use @emotion/babel-preset-css-prop if you're using @emotion/core as it will add the jsx pragma for you.
  • Use babel-plugin-emotion if you're using emotion since you do not require the jsx pragma
  • Use @emotion/css/macro only if you've got access to macros but no ability to add plugins. It is equally annoying to remember to write import css from '@emotion/css/macro' as it is to write
// @jsx jsx
import {jsx, css} from '@emotion/core'`

and you also lose out on some of the optimizations you get from non-macro plugins handling the css prop

Will there be issues if you're using a UI library that's on Emotion 9, but your app has moved onto Emotion 10, or vice versa (library on 10, app on 9)?

Yes. Particularly if either lib relied on the babel-plugin-emotion plugin as far as I can tell.

Is it possible to get rid of jsx import?

Only through using emotion instead of @emotion/core or magicking it away with @emotion/babel-preset-css-prop

What about react-emotion?

Use @emotion/styled

What does it look like to migrate a library?

I got diffs

I hope this information is useful (and correct). I won't be offended if anyone corrects potential errors here or has some disagreements. Like I said earlier in this post, the migration is NOT trivial. You will almost certainly encounter bugs along the way. So don't feel bad, ya'll.

react-create-app + /styled/macro + @emotion/core + React SSR don't seem to be working well together https://spectrum.chat/emotion?thread=eebe92ed-0863-4713-863f-0e61a9c30014

True;

  • with or without the extra babel plugin

Non-styled emotion works.

@dperetti old APIs (styled etc) are usable in emotion@10 as is without any problems, you basically have to make near to 0 changes when upgrading

@Andarist it looks like people loved emotion for its simplicity of using css, not because of its styled counterpart.

I really dislike how this "evolution" changed the way we work with emotion. I tried it in sandbox and it looks like the package itself have become fatty and has dependency to react. Why would I need such dependency in project that is not using react? The only thing I'd like to use is css that generates class name.

If you are not using react then you can just install latest emotion (when working with react it's preferred to work with @emotion/core package) and you should be ready to go - it works in nearly the same way as emotion@9

@kkwiatkowski I suggest taking a look at these docs which are linked directly from the introduction of the site.

https://emotion.sh/docs/emotion

@Andarist Can you explain your comment about SSR performance?

SSR renders style elements as part of the component (so u end up with MANY style elements when SSRing, but that's not a perf issue anyhow).

My understanding is that including all your css in your html generally does have a performance cost - specifically your html file size can increase dramatically and you can lose a lot of caching benefits. If this does apply to the new SSR API a note on performance tradeoffs in the documentation would be helpful.

#1059 (comment)

Ty @jaredLunde .. Jan 2020, the gaps in the 10 docs are still painfully there and your comment cleared up a ton of problems for us.

Closing since this issue is pretty stale. Please open a new issue if you find any gaps in the current docs for v11.