Theme-ui: Using babel plugin instead of pragma

Created on 26 Jul 2019  ·  22Comments  ·  Source: system-ui/theme-ui

The documentation states:
"To change the underlying create element function, you can either add an option to the Babel plugin or you can set a pragma comment at the beginning of a module."

Is that referring to @styled-system/babel-plugin?

Most helpful comment

@AndrewPrifer there's an open PR that introduces a theme-ui babel preset. Until this gets published if you want to avoid having to add a jsx pragma to every file you can add the following to your .babelrc.

{
  "plugins": [
    [
      "@emotion/babel-plugin-jsx-pragmatic",
      {
        "module": "theme-ui",
        "import": "jsx",
        "export": "jsx"
      }
    ],
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "jsx",
        "pragmaFrag": "React.Fragment"
      }
    ]
  ]
}

All 22 comments

No, this is referring to how JSX works generally with @babel/plugin-transform-react-jsx – the recommended way to use Theme UI is with the pragma comment /** @jsx jsx */

Thanks. I know it's not as performant but is it still possible to use a babel plugin instead of the pragma?

Yes, it's still possible, the pragma comment and Babel plugin option both replace React.createElement with the custom function – one works per file and the other works globally in a project

Hey @jxnblk what's the babel plugin option to get the sx prop working? Couldn't find it in the docs.

@jxnblk I'm using theme-ui with next. If I don't include the pragma at the beginning of the file, sx props are ignored. Any idea what to include in my babelrc file to get it working?

You can use the Babel plugin linked above, it includes docs for setting project-wide jsx pragma: https://babeljs.io/docs/en/babel-plugin-transform-react-jsx

@jxnblk gotcha. So something like this?

{
  "presets": ["next/babel"],
  "plugins": [
    ["@babel/plugin-transform-react-jsx", {
      "pragma": "jsx",
      "pragmaFrag": "React.Fragment"
    }]
  ]
}

This above doesn't seem to work :/

@jxnblk any chance you could provide an example on how to use theme-ui without using the pragma? Either in the docs or in a codesandbox?

Not a big deal, but ideally I don't have to put this at the beginning of each component file:

/** @jsx jsx */
import { jsx } from 'theme-ui'

Any reason this issue is closed? Does it mean you have a strong preference for the pragma design vs the global Babel plugin? Is that worth writting one? Would you accept it?
I'm asking this because Xstyled has made the choice and provides a Babel plugin. @adamsoffer maybe you can take a look at their implementation, that should be fairly easy to adapt it to ThemeUI?

I built an entire website with ThemeUI and JSX pragma, it's fine this way but it happened to me a couple of times to not understand why my styles were not working and figure out I forgot the pragma.
Also it's less intuitive for noobs ("_wtf is this comment at the top?_") and that's not something you have to understand to style a component.

I also don't understand this preference. Why wouldn't users want to use design tokens and sx for all their components? If anything, I think that's the rarer case. Plus you can also do all sorts of other nice things with a babel plugin, just look at emotion.

@AndrewPrifer there's an open PR that introduces a theme-ui babel preset. Until this gets published if you want to avoid having to add a jsx pragma to every file you can add the following to your .babelrc.

{
  "plugins": [
    [
      "@emotion/babel-plugin-jsx-pragmatic",
      {
        "module": "theme-ui",
        "import": "jsx",
        "export": "jsx"
      }
    ],
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "jsx",
        "pragmaFrag": "React.Fragment"
      }
    ]
  ]
}

@adamsoffer nice!

I get this when running the above babel plugins with CRA 4 and Craco

Module parse failed: Identifier 'jsx' has already been declared (18:9)
File was processed with these loaders:
 * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
| import { Input } from '../components/inputs/Input';
| import { Button } from '../components/buttons/Button';
> import { jsx } from "theme-ui";
| export const Login = () => {
|   _s();

has anyone gotten it to work with react 17?

@Ericnr CRA4 introduces a new Babel config that allows you to stop having to import React from 'react' in every file. I strongly think it's in connection to that.

I have a hunch if you rename jsx in the above Babel plugins and in the import to something else, it'll work.

@Ericnr we don't support the new automatic jsx runtime yet. @dcastil is working on it 🙏

In the meantime, you can change automatic to classic in your babel options with "runtime": "classic" or a pragma comment @jsxRuntime classic

https://babeljs.io/docs/en/babel-plugin-transform-react-jsx#:~:text=React%20Automatic%20Runtime,to%20will%20be%20imported%20automatically.

yea I did try it with classic runtime but still get the same error. I'll wait for the fix, thx!

@Ericnr, okay let me try one last thing.

Are you're using "@emotion/babel-plugin-jsx-pragmatic" from the post above?
If so, do you also have some lines importing { jsx } from 'theme-ui'?
Is the problem fixed if you remove those lines?

oh I had to remove DISABLE_NEW_JSX_TRANSFORM=true I had on cause I was trying many different things. I dont get that error anymore but now TS complains about the sx prop Property 'sx' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'. How can I tell TS that babel is importing theme-ui's jsx?

@Ericnr I guess that's because you don't explicitly import anything from theme-ui that could extend JSX.IntrinsicElements so you have to do it manually. I'd just take a look at theme-ui's code and copy the type they're using. Should look sth like

declare global {
  namespace JSX {
    interface IntrinsicElements {
      // ...
    }
  }
}

@AndrewPrifer that does it, thanks

This actually stopped working for me. TS compains Property 'sx' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>' for me as well. @Ericnr how did you end up solving this?

Sorry @adamsoffer, we forgot to document this.

Here's what happened and how to solve the problem (tldr: declare module 'react' and augment Attributes instead of global.JSX): https://github.com/system-ui/theme-ui/issues/1335#issuecomment-749543430

Was this page helpful?
0 / 5 - 0 ratings