Twin.macro: Allow curly brackets to be used with the tw prop

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

Hi there,

Loving the library, but hitting a weird snag that I've never seen before and searching around wasn't giving me much information.

Versions:

"twin.macro": "^1.0.0-alpha.10",
"webpack": "^4.43.0",
"typescript": "^3.8.3",
"styled-components": "^5.1.0",

Given this code:

<p tw={'font-medium'}>Testing</p>

I'm getting the following error:

ERROR in ./src/components/screens/LoginScreen.tsx
Module build failed (from ./node_modules/babel-loader/lib/index.js):
TypeError: /Users/dane/Sites/provider-v2/src/components/screens/LoginScreen.tsx: twin.macro: Cannot read property 'match' of undefined Learn more: https://www.npmjs.com/package/twin.macro
    at getStyles (/Users/dane/Sites/provider-v2/node_modules/twin.macro/macro.js:2375:26)
    at JSXAttribute (/Users/dane/Sites/provider-v2/node_modules/twin.macro/macro.js:2600:20)
    at NodePath._call (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/path/context.js:55:20)
    at NodePath.call (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/path/context.js:42:17)
    at NodePath.visit (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/path/context.js:90:31)
    at TraversalContext.visitQueue (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/context.js:112:16)
    at TraversalContext.visitMultiple (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/context.js:79:17)
    at TraversalContext.visit (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/context.js:138:19)
    at Function.traverse.node (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/index.js:84:17)
    at NodePath.visit (/Users/dane/Sites/provider-v2/node_modules/@babel/traverse/lib/path/context.js:97:18)
 @ ./src/components/App.tsx 13:0-48 24:15-26
 @ ./src/index.tsx
 @ multi react-hot-loader/patch ./src/index.tsx

However, doing <p tw="font-medium">Testing</p> works fine. Is this by design, or do I have some weird thing going on with my project compilation steps? Ideally it would work with the braces since that is how our eslint rules are defined.

This is my webpack module rules:

rules: [
            {
                test: /\.ts(x?)$/,
                exclude: /node_modules/,
                use: [
                    {
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: process.env.NODE_ENV !== 'production',
                            presets: [
                                '@babel/typescript',
                                '@babel/env',
                                '@babel/react',
                            ],
                            plugins: [
                                'babel-plugin-macros',
                                'styled-components',
                                'react-hot-loader/babel',
                                '@babel/transform-runtime',
                                '@babel/plugin-transform-react-jsx',
                                '@babel/proposal-class-properties',
                                '@babel/proposal-object-rest-spread',
                                '@babel/proposal-optional-chaining',
                                '@babel/proposal-nullish-coalescing-operator',
                                '@babel/syntax-dynamic-import',
                            ],
                        },
                    },
                ],
            },
            {
                test: /\.css$/i,
                use: ['style-loader', 'css-loader'],
            },
            {
                enforce: "pre",
                test: /\.js$/,
                loader: "source-map-loader"
            }
        ]

And my babel-plugin-macros.config.js:

module.exports = {
    twin: {
        styled: 'styled-components',
        config: './tailwind.config.js',
    },
}
feature request

Most helpful comment

IMO we should keep it as is until the time that we are able to use variables, which I think would probably require us to solve string interpolation (#17) first.

In the interim, we should update the documentation and the error output to better communicate to users that the tw prop expects a plain string of Tailwind class names and that it does not support an expression contained in curly brackets.

All 6 comments

Hey there Dane
You're right it's weird - it's because it's a Babel macro and you get to choose how it can be used.
If Twin supported the curly braces then I think the "Why can't I pass a variable in there?" question will come up more often.

My knowledge of macros is basically none, but I think I follow you.

So in this case its just a known limitation of it? If thats the case no worries, I've been working around it by doing a slightly more verbose call using the css macro for styled-components.

css={[ tw`class` ]}

Yeah, the tw prop has some pretty strict usage at the moment.
I'll update this issue into a feature request. Perhaps there are a few people that would like this changed?

Great you found a workaround, sorry it's not the best it could be.
I'll make sure I fix up that 'match' of undefinederror.

IMO we should keep it as is until the time that we are able to use variables, which I think would probably require us to solve string interpolation (#17) first.

In the interim, we should update the documentation and the error output to better communicate to users that the tw prop expects a plain string of Tailwind class names and that it does not support an expression contained in curly brackets.

In the interim, we should update the documentation and the error output to better communicate to users that the tw prop expects a plain string of Tailwind class names and that it does not support an expression contained in curly brackets.

There's now an error display for unintended usage in v1.0.0 馃帀

Hey @DaneEveritt, curly brackets are now available in 1.3.0.

<div tw={'flex flex-col justify-center h-full space-y-6'}>
Was this page helpful?
0 / 5 - 0 ratings