Theme-ui: EmotionContext version mismatch can break `styled.div(css({...`

Created on 23 Nov 2020  Â·  15Comments  Â·  Source: system-ui/theme-ui

Describe the bug

The theme references in the import { css } from 'theme-ui' function don't work on version v0.5.0-alpha.0

It still works in the theme styles, variants, and sx prop.

To Reproduce

  1. Upgrade Theme UI to v0.5.0-alpha.0
  2. Upgrade Emotion to v11
  3. Rename the emotion package names in you codebase
  4. Use the css function from theme-ui in an emotion component
export const StyledHeader = styled.div(
  css({
    // doesn't work
    color: 'primary',
    bg: 'background',
    zIndex: 'nav',
    maxWidth: 'sidebar',
    borderRadius: 'small',

    // works
    px: 4,
  })
)

This code outputs

.StyledHeader {
  color: primary;
  background-color: background;
  z-index: nav;
  max-width: sidebar;
  border-radius: small;
  padding-left: 32px;
  padding-right: 32px;
}

Expected behavior
Should output something like

.StyledHeader {
  color: var(--theme-ui-colors-primary, #000000);
  background-color: var(--theme-ui-colors-background, #ffffff);
  z-index: 10;
  max-width: 350px;
  border-radius: 4px;
  padding-left: 32px;
  padding-right: 32px;
}

Screenshots
Shot_0 2

bug

Most helpful comment

I assumed it's just keyframes, Global, and styled? I might have missed something.

I think you are right atm, not sure 100%, but who knows in he future. In any case I usually prefer transparent vs ease-of-use in the case of developers as users, assuming they can handle a few more steps.
Maybe a good candidate for your polls :)

All 15 comments

Thanks for the issue, @fcisio! I really appreciate you taking the time instead of writing "fools, the most important feature of Theme UI doesn't work" :D

Repro: https://codesandbox.io/s/gracious-water-dt2k5?file=/src/App.tsx

I'm not sure if this is also what happened for you, but inside my CodeSandbox, there's a context version mismatch.
Could you send me your lockfile?

yarn.lockfile

Didn't have issues with the content version. But the version of Theme UI in the sandbox is "0.3.4" might be related?

I changed it by accident a minute ago, sorry. Take a look now.

So the problem is, that we have @emotion/react in dependencies, not in peerDependencies. And Theme UI and @emotion/styled import Emotion context from different versions, we have a mismatch.

I think this is the longest living bug/problem we have.

After removing @emotion/react from sandbox's deps, it works fine, but I'm getting TS errors on import of @emotion/react :/
https://codesandbox.io/s/condescending-wilson-rpnnv?file=/src/App.tsx

I tested in the sandbox, and there doesn't seem to be any problem. It might be an issue on my end 🤔

Okay, you don't have the same mismatch in your yarn.lock, but you have two @emotion/styled

image

Good catch, thanks!
It was a me issue in the end 😅

I guess we can close the issue now!

No! 😲 We can't close it. This is a problem! I have this problem every now and then, and there's a dozen issues and discussion from the same cause.

Okay, I don't have a quick solution for this problem.
Right now, Theme UI is a bit of a leaky abstraction. We depend on Emotion, and we install it for ours users, but we don't reexport equivalents of full Emotion's Public API. So users also depend on Emotion. That's how we end up with multiple context mismatches.

We could either:

  1. Entirely hide our dependency on Emotion. Want styled components? Use @theme-ui/styled*. Need global styles? import { Global } from 'theme-ui'.
  2. Be entirely transparent. Make Emotion a peerDependency, so the user entirely controls the version they depend on.
  3. Ignore it? We did ignore it for quite some time, I think.
  4. __ _A better solution to solve the problem?_ __

cc @lachlanjc @atanasster @dcastil
what do you think?


I believe we have a similar problem with dependency on some mdx packages.

Thanks for investigating, makes sense although I never had the issue myself.

I would support option 2. - peerDependency, since it would be very hard to re-export everything (and difficult to maintain)

since it would be very hard to re-export everything (and difficult to maintain)

I assumed it's just keyframes, Global, and styled? I might have missed something.

I never had issues with emotion deps but I get the issue. I solved it by importing stuff from emotion despite it not being referenced in my own dependencies which is probably the worst of all solutions. 🙈

I don't have a good answer on this. I see tradeoffs in all cases which aren't so nice.

  1. Might make the bundle size bigger and creates the need to write arbitrary documentation for Emotion features.
  2. Makes Theme UI harder to use for beginners. Also, that might bring the interdependencies between Emotion and Theme UI to the surface, because you could use our theme within Emotion.

I'm leaning towards 2, but dunno…

I assumed it's just keyframes, Global, and styled? I might have missed something.

I think you are right atm, not sure 100%, but who knows in he future. In any case I usually prefer transparent vs ease-of-use in the case of developers as users, assuming they can handle a few more steps.
Maybe a good candidate for your polls :)

Ignoring it isn't so bad. People usually believe it's their fault, because they didn't "install properly", but I think it's a design flaw on our part. It's too easy to break in userland.

Another idea:

We're importing @emotion/react package.json to pass their version as __EMOTION_VERSION__ through context.
We could print a huge warning that something went wrong if the version we import doesn't match (by semver) the version we depend on. Then, after we've shown a "disclaimer", the responsibility is on the user.

I'm not a huge fan of this solution, but it might be practical.

Was this page helpful?
0 / 5 - 0 ratings