Twin.macro: Issues pre-bundling twin components with Rollup and importing them

Created on 6 Apr 2020  路  16Comments  路  Source: ben-rogerson/twin.macro

Hey,

This may be a dumb question.

If i publish a package to NPM ... say button that i use this macro within and then publish. If i then import this package with the button would this still work?

for example...

import tw from "twin.macro";

const Button = () => <button tw="w-32 m-10 p-5 block opacity-50 hover:opacity-100">ddd</button>

export default Button;

nextjs site

import Button from "package";

const page = () => <Button />

export default page;

should that work or am i missing the point the macros in that it is only compile time... I use rollup for button example

feature request

Most helpful comment

Valid point, I'll see what I can put together on the topic.

All 16 comments

I am not an expert, however your specific example won't achieve styles assigned to your button as a unique named style.
You will produce something like.

<button css="[object Object]">ddd</button>

twin.macro at compile time converts tw="<classes string here>" into css={<styles object here>}

You need to supply an alternate jsx handler that understands what to do with css=""
A simple example below uses @emotion/core jsx parse and will work, it uses
@emotion to do this. (styled-components has an equivalent jsx parser).

Then @emotion will create a unique class from the styles in css prop create a unique classname and set the className for the component.

/* @jsx jsx */
import React from 'react'
import { jsx } from '@emotion/core'
import tw from "twin.macro";

const ButtonTest = () => <button tw="w-32 m-10 p-5 block opacity-50 hover:opacity-100">ddd</button>

export default ButtonTest;

If you want an even more bare boned example to get a feel for it.
Using the tw`` template literal will return a style object to the constant
buttonStyle, this can then be directly used in style of the button.
No special @jsx or other libraries required.
However this does limit you to styles that can be set via inline styles, which in this case means hover will not work.

import React from 'react'
import tw from "twin.macro";

const buttonStyle = tw`w-32 m-10 p-5 block opacity-50 hover:opacity-100`

const ButtonTest = () => <button style={buttonStyle}>ddd</button>

export default ButtonTest;

@rluiten Thanks for the reply. However, my example prob was not the best. If i have a button component that works if i export it without using tw and just use the css prop all works, published to private verdaccio. But when i rollup this file with tw included and macros added to rollup it removes the tw macro from the imports and does not overwrite the string to the correct styles. this is in a monorepo btw.

then in a nextjs app if i import button all works as expected (without tw import). Then in the next app i add tw import and to ${twwhatever} inside css of emotion all works. But not when bundling my component with tw as import

@ben-rogerson So the result of my bundled package looks like this (use typescript and rollup)
as you can see where has tw import gone?

the below is this example from docs:

import React from 'react'
import tw from 'twin.macro'
import styled from '@emotion/styled/macro'
import { css } from '@emotion/core'

const MyComponent = styled.div(({ hasDarkHover }) => [
  tw`inline-block`,
  hasDarkHover
    ? tw`hover:text-black`
    : css`
        &:hover {
          ${tw`text-white`}
        }
      `
])
export default props => <MyComponent {...props} />

rollup transformation:

using typescript "es5" - this does not work as expected... seems to not transpile correctly

import _styled from '@emotion/styled/base';
import { __assign, __makeTemplateObject } from 'tslib';
import React from 'react';
import { css } from '@emotion/core';

var MyComponent = _styled("div", {
  target: "efqezp20",
  label: "MyComponent"
})(function (_a) {
  var hasDarkHover = _a.hasDarkHover;
  return [tw(templateObject_1 || (templateObject_1 = __makeTemplateObject(["inline-block"], ["inline-block"]))), hasDarkHover ? tw(templateObject_2 || (templateObject_2 = __makeTemplateObject(["hover:text-black"], ["hover:text-black"]))) : css(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n        &:hover {\n          ", "\n        }\n      "], ["\n        &:hover {\n          ", "\n        }\n      "])), tw(templateObject_3 || (templateObject_3 = __makeTemplateObject(["text-white"], ["text-white"]))))];
}, process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlNST25seS50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBTWtCIiwiZmlsZSI6IlNST25seS50c3giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBfX2Fzc2lnbiwgX19tYWtlVGVtcGxhdGVPYmplY3QgfSBmcm9tIFwidHNsaWJcIjtcclxuLy8gQHRzLW5vY2hlY2tcclxuaW1wb3J0IFJlYWN0IGZyb20gJ3JlYWN0JztcclxuaW1wb3J0IHR3IGZyb20gXCJ0d2luLm1hY3JvXCI7XHJcbmltcG9ydCBzdHlsZWQgZnJvbSBcIkBlbW90aW9uL3N0eWxlZC9tYWNyb1wiO1xyXG5pbXBvcnQgeyBjc3MgfSBmcm9tIFwiQGVtb3Rpb24vY29yZVwiO1xyXG52YXIgTXlDb21wb25lbnQgPSBzdHlsZWQuZGl2KGZ1bmN0aW9uIChfYSkge1xyXG4gICAgdmFyIGhhc0RhcmtIb3ZlciA9IF9hLmhhc0RhcmtIb3ZlcjtcclxuICAgIHJldHVybiBbXHJcbiAgICAgICAgdHcodGVtcGxhdGVPYmplY3RfMSB8fCAodGVtcGxhdGVPYmplY3RfMSA9IF9fbWFrZVRlbXBsYXRlT2JqZWN0KFtcImlubGluZS1ibG9ja1wiXSwgW1wiaW5saW5lLWJsb2NrXCJdKSkpLFxyXG4gICAgICAgIGhhc0RhcmtIb3ZlclxyXG4gICAgICAgICAgICA/IHR3KHRlbXBsYXRlT2JqZWN0XzIgfHwgKHRlbXBsYXRlT2JqZWN0XzIgPSBfX21ha2VUZW1wbGF0ZU9iamVjdChbXCJob3Zlcjp0ZXh0LWJsYWNrXCJdLCBbXCJob3Zlcjp0ZXh0LWJsYWNrXCJdKSkpIDogY3NzKHRlbXBsYXRlT2JqZWN0XzQgfHwgKHRlbXBsYXRlT2JqZWN0XzQgPSBfX21ha2VUZW1wbGF0ZU9iamVjdChbXCJcXG4gICAgICAgICY6aG92ZXIge1xcbiAgICAgICAgICBcIiwgXCJcXG4gICAgICAgIH1cXG4gICAgICBcIl0sIFtcIlxcbiAgICAgICAgJjpob3ZlciB7XFxuICAgICAgICAgIFwiLCBcIlxcbiAgICAgICAgfVxcbiAgICAgIFwiXSkpLCB0dyh0ZW1wbGF0ZU9iamVjdF8zIHx8ICh0ZW1wbGF0ZU9iamVjdF8zID0gX19tYWtlVGVtcGxhdGVPYmplY3QoW1widGV4dC13aGl0ZVwiXSwgW1widGV4dC13aGl0ZVwiXSkpKSlcclxuICAgIF07XHJcbn0pO1xyXG5leHBvcnQgZGVmYXVsdCAoZnVuY3Rpb24gKHByb3BzKSB7IHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KE15Q29tcG9uZW50LCBfX2Fzc2lnbih7fSwgcHJvcHMpKTsgfSk7XHJcbnZhciB0ZW1wbGF0ZU9iamVjdF8xLCB0ZW1wbGF0ZU9iamVjdF8yLCB0ZW1wbGF0ZU9iamVjdF8zLCB0ZW1wbGF0ZU9iamVjdF80O1xyXG4iXX0= */");

var SROnly = (function (props) {
  return React.createElement(MyComponent, __assign({}, props));
});
var templateObject_1, templateObject_2, templateObject_3, templateObject_4;

export { SROnly };

using typescript "esnext" - this works as expected

import _styled from '@emotion/styled/base';
import React from 'react';
import { css } from '@emotion/core';

const MyComponent = _styled("div", {
  target: "efqezp20",
  label: "MyComponent"
})(({
  hasDarkHover
}) => [{
  "display": "inline-block"
}, hasDarkHover ? {
  ":hover": {
    "color": "#000"
  }
} : css`
        &:hover {
          ${{
  "color": "#fff"
}}
        }
      `], process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIlNST25seS50c3giXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBS29CIiwiZmlsZSI6IlNST25seS50c3giLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAdHMtbm9jaGVja1xyXG5pbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xyXG5pbXBvcnQgdHcgZnJvbSBcInR3aW4ubWFjcm9cIjtcclxuaW1wb3J0IHN0eWxlZCBmcm9tIFwiQGVtb3Rpb24vc3R5bGVkL21hY3JvXCI7XHJcbmltcG9ydCB7IGNzcyB9IGZyb20gXCJAZW1vdGlvbi9jb3JlXCI7XHJcbmNvbnN0IE15Q29tcG9uZW50ID0gc3R5bGVkLmRpdigoeyBoYXNEYXJrSG92ZXIgfSkgPT4gW1xyXG4gICAgdHcgYGlubGluZS1ibG9ja2AsXHJcbiAgICBoYXNEYXJrSG92ZXJcclxuICAgICAgICA/IHR3IGBob3Zlcjp0ZXh0LWJsYWNrYFxyXG4gICAgICAgIDogY3NzIGBcbiAgICAgICAgJjpob3ZlciB7XG4gICAgICAgICAgJHt0dyBgdGV4dC13aGl0ZWB9XG4gICAgICAgIH1cbiAgICAgIGBcclxuXSk7XHJcbmV4cG9ydCBkZWZhdWx0IHByb3BzID0+IFJlYWN0LmNyZWF0ZUVsZW1lbnQoTXlDb21wb25lbnQsIE9iamVjdC5hc3NpZ24oe30sIHByb3BzKSk7XHJcbiJdfQ== */");

var SROnly = (props => React.createElement(MyComponent, Object.assign({}, props)));

export { SROnly };

Twin does some tricky stuff during compilation time and actually swaps the tw import with _styled (that's why using tw.div works similarly to styled.div).

Using the typescript "es5" transformation makes Rollup do some work before babel macros run.
Have you tried using a plugin like rollup-plugin-babel?

If you're still having trouble getting this working, perhaps post a reproduction of the issue so we can look into the issue further.

hey,

its pretty much the same as https://github.com/skene/cra-twin.macro-monorepo/blob/master/packages/components/rollup.config.js

so babel runs also.

TBH for my use case exporting as as "esnext" is ok because i would ideally like the consumer of the lib to determine what to do in terms of browser support etc. So mine will already be converted using twin behind the scenes and once the package is used in some other app they can decide what to transpile it down too.

This does not address the issue though as if someone using twin in an app with using typescript to transpile to es5 it will be an issue.

Any future plans to provide a guide on packaging components with twin.macro?

I haven't heard many requests for it yet.
Would you be interested in a TS or JS guide?

TS as we went with twin.macro due to the typescript support. Right now due to the issues with rollup and other build tools we currently have code which is duped in many areas. If you have a multi client project then having a shared resource amongst the assets is vital. I came close the other day to achieving a bundle but I doubt I was in the right direction which is why I asked. I think if provided it would boost the possibility that twin.macro would be used in various UI libraries within different ecosystems.

Valid point, I'll see what I can put together on the topic.

Is this still a thing, having exactly the same issue as @derekbar90

Yeah, I haven't spent any more time with it yet.
There should be some other issues on the same topic as this affects all babel-plugin-macros.

I encounter this issue and already found solution on my side. The problem is because the codes is already transpiled by rpt2, so the babel could not pick up the "macros". Therefore if you remove rpt2 and transpile the typescript using the babel, would be work like a charm. Hope it helps

Screenshot_20201029_192950

So I presume this has something to do with this as well (without rollup).
I am trying to build a component with tsc (es5) enabled and then publish it and use it.

You'll need to precompile your components with Babel before export.
I'm working on a demo with Rollup, hang tight and I'll release it shortly.

Check out the Twin component library monorepo for a pretty sweet component library setup 馃帀

I'm closing up this issue now but feel free to reopen if there are any further issues.

Thank you @ben-rogerson !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

r6203 picture r6203  路  5Comments

owaiswiz picture owaiswiz  路  3Comments

hendrul picture hendrul  路  3Comments

lukasluecke picture lukasluecke  路  6Comments

DaneEveritt picture DaneEveritt  路  6Comments