profile
viewpoint
Frank van Wijk fvanwijk XSD @xebia Leiden http://www.frankvanwijk.nl Senior Frontend Consultant

fvanwijk/mox 60

Utility library for AngularJS/Jasmine mocks

fvanwijk/d3-area-chunked 5

Create areas that indicate where data is missing with gaps or differently styled chunks/area segments.

0xR/frontend-cli-performance-site 0

Promotional website showcasing different CLI tools and their performance

AlbertBrand/VueD3AreaChart 0

Area Chart with Vue & D3 as a web component

fvanwijk/advent-of-code 0

My solutions to Advent of Code (all years)

fvanwijk/advent-of-code-2017 0

My solutions to the Advent of Code 2017 code challenge

fvanwijk/adventofcode-2015 0

My solutions to the Advent of Code 2015 code challenge

fvanwijk/adventofcode-2016 0

My solutions to the Advent of Code 2016 code challenge

fvanwijk/angular.io 0

Website for Angular 2

issue commentben-rogerson/twin.macro

Extended colour does not change on reload (Next.js)

@ben-rogerson is this issue solved? I have nextjs + emotion + tailwndcss + twin.macro setup. After extending a tw class in tailwind.config.js, I have to restart the dev server to take effect.

package.json

{
  "name": "nextjs",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "@emotion/react": "^11.1.4",
    "@emotion/styled": "^11.0.0",
    "next": "10.0.0",
    "react": "17.0.1",
    "react-dom": "17.0.1",
    "twin.macro": "^2.0.8"
  },
  "devDependencies": {
    "@babel/core": "^7.12.10",
    "@types/node": "^14.14.20",
    "@types/react": "^17.0.0",
    "postcss": "^8.2.4",
    "tailwindcss": "^2.0.2",
    "typescript": "^4.1.3"
  }
}

twin.d.ts

// twin.d.ts
import "twin.macro";
import styledImport from "@emotion/styled";
import { css as cssImport } from "@emotion/react";

// The css prop
// https://emotion.sh/docs/typescript#css-prop
import {} from "@emotion/react/types/css-prop";

declare module "twin.macro" {
  // The styled and css imports
  const styled: typeof styledImport;
  const css: typeof cssImport;
}

// The 'as' prop on styled components
declare global {
  namespace JSX {
    interface IntrinsicAttributes<T> extends DOMAttributes<T> {
      as?: string;
    }
  }
}

.babelrc

{
  "presets": [
    [
      "next/babel",
      {
        "preset-react": {
          "runtime": "automatic",
          "importSource": "@emotion/react"
        }
      }
    ]
  ],
  "plugins": ["@emotion/babel-plugin", "babel-plugin-macros"]
}
theairbend3r

comment created time in 2 days

issue commentben-rogerson/twin.macro

framer-motion + styled-components doesn't work with prop styling

@ben-rogerson, interesting. While the reproduction uses NPM, we ran into this issue in our Yarn workspaces monorepo. And yes, we were able to work around it as well by doing this:

const MotionDiv = motion.div

// snip

<MotionDiv tw="..." />

In that case, the transpilation properly defined var MotionDiv = _framerMotion.motion.div. My uneducated guess here is that the Babel transform is probably just taking what it finds in the JSX call (i.e., <motion.div>) and putting it in the styled component (i.e., styled(motion.div)) in a way that doesn't consider ES6 -> CommonJS interop changes.

I'd be happy to dig in a bit more and help implement a fix if you could point me in the right direction, specifically where the AST fransformation is happening within the Babel macro implementation.

Thanks!

migueloller

comment created time in 2 days

issue commentben-rogerson/twin.macro

styled-components preset doesn't work with certain React elements

When testing this, I had no issues using yarn, but I experienced the described error when using npm to install the dependencies. I also had no issues with emotion so this issue seems localised to twin + styled-components + npm.

Here's the workaround I've found:

import React from 'react'
import tw from 'twin.macro'
import { Button, Logo } from './components'
import { motion } from 'framer-motion'

const Motion = tw(motion.div)``

const App = () => (
  <Motion
    as="span"
    css={[
      tw`flex flex-col items-center justify-center h-screen`,
      tw`bg-gradient-to-b from-electric to-ribbon`,
    ]}
  >
    <Motion tw="flex flex-col justify-center h-full space-y-5">
      <Button isPrimary>Submit</Button>
      <Button isSecondary>Cancel</Button>
      <Button isSmall>Close</Button>
    </Motion>
    <Logo />
  </Motion>
)

export default App

Note that you can change from a div to another element with the as prop.

I'll have to have a better dig into this before I can explain exactly what's happening.

migueloller

comment created time in 2 days

issue openedben-rogerson/twin.macro

styled-components preset doesn't work with certain React elements

We ran into this issue when attempting to use Framer Motion with twin.macro. The gist of it is that using the tw prop on an element like motion.div results in the commonjs transpilation improperly importing the bindings, which causes this error: image

Here's what some transpiled output looks like:

var _framerMotion = require("framer-motion");

// snip

var _StyledMotionDiv = (0, _styledComponents.default)(motion.div).withConfig({
  displayName: "Dialog___StyledMotionDiv",
  componentId: "sc-1ji47xs-0"
})({
  "position": "absolute",
  "top": "0px",
  "right": "0px",
  "bottom": "0px",
  "left": "0px",
  "pointerEvents": "none",
  "--tw-bg-opacity": "1",
  "backgroundColor": "rgba(0, 0, 0, var(--tw-bg-opacity))"
});

Notice that instead of _framerMotion.motion.div, the styled component is just called with motion.div and since motion isn't defined, that results in an error. The code that transpiles to this looks somewhat like this:

import { motion } from 'framer-motion'

// snip

  <motion.div tw="absolute inset-0 pointer-events-none bg-black">

This can easily be reproduced by doing the following:

Follow the instructions at https://github.com/ben-rogerson/twin.examples/tree/master/react-styled-components:

npx degit https://github.com/ben-rogerson/twin.examples/react-styled-components folder-name
cd folder-name
npm install framer-motion

And apply the following changes to src/App.js:

 import React from 'react'
 import tw from 'twin.macro'
 import { Button, Logo } from './components'
+import { motion } from 'framer-motion'
 
 const App = () => (
-  <div
+  <motion.div
     css={[
       tw`flex flex-col items-center justify-center h-screen`,
       tw`bg-gradient-to-b from-electric to-ribbon`,
     ]}
   >
-    <div tw="flex flex-col justify-center h-full space-y-5">
+    <motion.div tw="flex flex-col justify-center h-full space-y-5">
       <Button isPrimary>Submit</Button>
       <Button isSecondary>Cancel</Button>
       <Button isSmall>Close</Button>
-    </div>
+    </motion.div>
     <Logo />
-  </div>
+  </motion.div>
 )
 
 export default App

Run npm start and open the console in the browser and you'll see the error.

created time in 3 days

issue commentben-rogerson/twin.macro

twin.macro not playing nicely with Next.JS and shared components in a yarn workspaces

Thanks Frank — that thought did occur to me.

Unfortunately tweaking the order, in the built module file, doesn't help.

Here's how TextInput is being called in that built file:

function Input(props) {
  var icon = props.icon,
      rest = _objectWithoutProperties(props, ["icon"]);

  return InputWrapper(null, [icon && icon({
    size: 24
  }), TextInput(Object.assign({}, rest))]);
}

Unfortunately, TextInput seems to be returned as an object by _styled2.

PaddyMann

comment created time in 3 days

issue commentben-rogerson/twin.macro

twin.macro not playing nicely with Next.JS and shared components in a yarn workspaces

The rollup solution I've got currently works well with a simple styled component, e.g.:

import tw, {styled} from 'twin.macro';

const PageCenter = styled.div((props) => [
  tw`
    flex
    items-center
    justify-center
    h-screen
  `,
]);

export default PageCenter;

However, it doesn't seem to support something a little more complex:

import React from 'react';
import PropTypes from 'prop-types';
import tw, {styled} from 'twin.macro';

Input.propTypes = {
  icon: PropTypes.func,
};

Input.defaultProps = {
};

function Input (props) {
  const {
    icon,
  } = props;

  return <InputWrapper>
    {icon && icon({size: 24})}
    <TextInput />
  </InputWrapper>;
}

const InputWrapper = styled.div((props) => [
  tw`
    flex
    border
    w-full
    px-3
    pl-2.5
    h-11
    border-gray-300
    text-gray-700
    svg:self-center
    svg:text-gray-400
  `,
]);

const TextInput = styled.input((props) => [
  tw`
    outline-none
    w-full
    ml-2
  `,
]);

export default Input;

The error I get is:

TypeError: TextInput is not a function

In the built module, I can see TextInput is included, but it's wrapped as a styled-components object:

;

var TextInput = _styled2.input.withConfig({
  displayName: "Input__TextInput",
  componentId: "sc-15h421e-1"
})(function (props) {
  return [{
    "outline": "2px solid transparent",
    "outlineOffset": "2px",
    "width": "100%",
    "marginLeft": "0.5rem"
  }];
});

Any ideas how to resolve this?

PaddyMann

comment created time in 3 days

issue commentben-rogerson/twin.macro

twin.macro not playing nicely with Next.JS and shared components in a yarn workspaces

I've now got it working with rollup — thank you sir!

PaddyMann

comment created time in 3 days

issue commentben-rogerson/twin.macro

twin.macro not playing nicely with Next.JS and shared components in a yarn workspaces

I've just re-read your response and realize the next step is to look at the linked repo. I'll be doing that now — thanks @ben-rogerson :)

PaddyMann

comment created time in 3 days

issue commentben-rogerson/twin.macro

twin.macro not playing nicely with Next.JS and shared components in a yarn workspaces

Thanks for reviewing @ben-rogerson (and epic work on twin btw — amazing to find so much support + examples of making it work with so many other libraries!)

I'm a little unclear on what the next steps are. Is this something I can resolve at my end, or does it need to be addressed either in twin or styled-components? :)

PaddyMann

comment created time in 3 days

issue commentben-rogerson/twin.macro

Overriding existing utilities in tailwind.config.js has no effect when using with Next.js

@ben-rogerson Yes, I think that's the best solution for now...thank you for this excellent project.

amrnn90

comment created time in 4 days

issue commentben-rogerson/twin.macro

twin.macro not playing nicely with Next.JS and shared components in a yarn workspaces

Thanks for the great issue repo. I've used Rollup to create a shared component library and the trick there was to pre-compile the library before importing it into my project. I believe what's happening here is that shared-components doesn't precompile the library beforehand so when next attempts to use the component, styled hasn't been replaced with the css-in-js library import.

PaddyMann

comment created time in 4 days

issue commentben-rogerson/twin.macro

Overriding existing utilities in tailwind.config.js has no effect when using with Next.js

Ah yes, it's similar for Gatsby also but it's the .cache dir in that case. If I'm adjusting the config often enough I'll change the dev script to rimraf the dir before starting the dev server.

amrnn90

comment created time in 4 days

issue openedben-rogerson/twin.macro

twin.macro not playing nicely with Next.JS and shared components in a yarn workspaces

Our monorepo has both a create-react-app (CRA) and a Next.JS app.

I'm trying to set up a shared components library, and have got it working for the CRA app.

I've also managed to set up Next.JS to load shared components using next-transpile-modules, but I'm having issues when importing {styled} from twin.macro.

With this code... :

import tw, {styled} from 'twin.macro';

... styled is coming out as undefined.

I've recreated the issue here: https://github.com/PaddyMann/twin-yarn-workspaces-issue

created time in 4 days

issue commentben-rogerson/twin.macro

Overriding existing utilities in tailwind.config.js has no effect when using with Next.js

@drymek Yes, that's what happens with me also. I don't usually override existing utilities anyway, so I'll just remove the .next directory for now 😅

amrnn90

comment created time in 4 days

startedsnowpackjs/snowpack

started time in 4 days

issue commentben-rogerson/twin.macro

Overriding existing utilities in tailwind.config.js has no effect when using with Next.js

In my case, it is not enough to change the file or restart service. I looked for this bug for a while (I thought it was a wrong tailwind configuration) - only removing the .next directory works for me. However, I use it everywhere, so I'm not able to easy test it without twin.macro

amrnn90

comment created time in 4 days

issue commentben-rogerson/twin.macro

Cannot Get Values from Prop

Thanks for the explanation -- much appreciated.

thecodeclimber

comment created time in 4 days

issue commentben-rogerson/twin.macro

'css' is not exported from 'styled-components/macro'

FYI, I just tried this with npm install and I got the same error

'css' is not exported from 'styled-components/macro'

So I cleared away the repo, and tried again using yarn and everything seems to work.

Sounds like some caching happening there 🤷‍♂️

hendrul

comment created time in 5 days

issue closedben-rogerson/twin.macro

MacroError with webpack and typescript

Getting this error with a project that is using RMWC. I've seen people posting about the same issue with Storybook or Jest. I can't seem to suss out the solution. Any help would be appreciated.

 MacroError: The macro you imported from "undefined" is being executed outside the context of compilation with babel-plugin-macros. This indicates that you don't have the babel plugin "babel-plugin-macros" configured correctly. Please see the documentation for how to configure babel-plugin-macros properly: https://github.com/kentcdodds/babel-plugin-macros/blob/master/other/docs/user.md

I suppressed some potentially related errors about fs and module being undefined with the below in webpack.config.js.

      node: {
            fs: "empty",
             module: "empty"
        },

Here a redacted bit of my ``webpack.config.js`

const path = require("path");
const webpack = require("webpack");
const FaviconsWebpackPlugin = require('favicons-webpack-plugin')
const htmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const Ajv = require("ajv");


...


module.exports = (env, argv) => {
    
    ...

    return {
        mode: mode,
        entry: path.resolve(__dirname, "src/index.tsx"),
        output: {
            filename: "js/[name].js",
            path: path.resolve(__dirname, "dist"),
            publicPath: publicPath
        },
        devtool: isProduction ? false : "source-map",
        devServer: {
            compress: true,
            port: 3001,
            historyApiFallback: true,
            proxy: {
                "/api": {
                    target: "http://localhost:4001",
                    pathRewrite: { "^/api": "" }
                }
            }
        },
        resolve: {
            alias: {
                "@": path.resolve(__dirname, "./src")
            },
            extensions: [".ts", ".tsx", ".js", ".json"]
        },
        plugins: [
            new MiniCssExtractPlugin({
                filename: "css/[name].css",
                sourceMap: true
            }),
              new FaviconsWebpackPlugin({
                logo: './src/logo.png', 
                mode: 'webapp', 
                devMode: 'light', 
                favicons: {
                    appName: 'app',
                    appDescription: 'app description',
                    developerName: 'Me',
                    developerURL: null, 
                    background: '#ffecb3',
                    theme_color: '#FFF',
                    icons: {
                        coast: false,
                        yandex: false
                    }
                }
            }),
            new htmlWebpackPlugin({
                template: path.resolve(__dirname, "src/index.html"),
            })
        ],
        optimization: {
            splitChunks: {
                name: "vendor",
                chunks: "initial"
            }
        },
        performance: {
            maxEntrypointSize: 1000000,
            maxAssetSize: 1000000
        },
        module: {
            rules: [
                {
                    test: /\.tsx?$/,
                    loader: "ts-loader"
                },
                {
                    enforce: "pre",
                    test: /\.js$/,
                    loader: "source-map-loader",
                    exclude: [
                        // material-ui は source-map を提供してくれていないっぽいので除外
                        /node_modules\/@material/,
                        /node_modules\/@rmwc/
                    ]
                },
                {
                    test: /\.css$/,
                    sideEffects: true,
                    use: [MiniCssExtractPlugin.loader, "css-loader"]
                },
                {
                    test: /\.(?:ico|gif|png|jpg|jpeg|webp|svg)$/i,
                    loader: "file-loader",
                    options: {
                        name: "[path][name].[ext]",
                        context: "src"
                    }
                },
                {
                    test: /\.(woff|woff2|eot|ttf)$/,
                    loader: "file-loader",
                    options: {
                        limit: 8192,
                        name: "[path][name].[ext]",
                        context: "src"
                    }
                }
            ]
        },
        watch
    };
};


closed time in 5 days

b-d-m-p

issue closedben-rogerson/twin.macro

Overriding existing utilities in tailwind.config.js has no effect when using with Next.js

Hello, I'm using twin.macro with emotion and Next.js. Whenever I make a change inside tailwind.config.js that overrides an existing utility, that change is ignored and restarting the server has no effect...the only way to make it work is by deleting the .next folder.

Steps to reproduce:

  1. npx degit https://github.com/ben-rogerson/twin.examples/next-emotion folder-name
  2. yarn && yarn dev
  3. override an existing utility in tailwind.config.js (must be an existing utility, if it's a new utility things work fine), for example:
module.exports = {
  theme: {
    extend: {
      colors: {
        red: {
          100: 'black'
        }
      },
    },
  },
  plugins: [],
}
  1. apply this utility somewhere, for example <div tw="bg-red-100"></div>
  2. the created div will show the old red instead of the new black
  3. restarting the server doesn't work, you have to delete the .next folder and run the server again to make it work.

closed time in 5 days

amrnn90

issue commentben-rogerson/twin.macro

Overriding existing utilities in tailwind.config.js has no effect when using with Next.js

You've hit the babel caching issue, to fix it you'll just need to make a change in your file to force babel to recompile. This only happens in dev and never in production.

amrnn90

comment created time in 5 days

issue closedben-rogerson/twin.macro

Cannot Get Values from Prop

You can see an example of what I am trying to do here: https://codesandbox.io/s/vibrant-leaf-qj8vz

Note: this particular example is using Styled Components (I just modified your codesandbox demo). On my local computer I tried the same thing with the same results using emotion/next.js.

Here is a sample component illustrating what I am trying to do:

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

const Acme = ({ children, type }) => <div css={[tw`${type}`]}>{children}</div>

export default Acme

Here is how I would use that component: <Acme type="text-2xl">Text Goes Here</Acme>

My expectation is that I will be able to style this instance of the <Acme /> component via the tailwind css classes that I pass into the type prop. Instead, I get the following error message:

/src/components/Acme.js: twin.macro: Property value expected type of string but got null Learn more: https://www.npmjs.com/package/twin.macro

When trying to figure this out, I noticed something interesting that may be relevant. Here is a variation of the code that does work:

const Acme = ({ children, type }) => {
  const typeClass = 'text-2xl'
  const typeObj = {
    class: 'text-2xl',
  }

  return <div css={[tw`${typeClass}`]}>{children}</div>
}

export default Acme

Note that I have created a variable typeClass and set it to the same tailwind css class. Note, in particular, the following line of code:

css={[tw`${typeClass}`]}

I have replace the prop type with the variable typeClass. This works. But now, instead of using the variable typeClass let's use the object typeObj that I have created as follows:

const Acme = ({ children, type }) => {
  const typeClass = 'text-2xl'
  const typeObj = {
    class: 'text-2xl',
  }

  return <div css={[tw`${typeObj.class}`]}>{children}</div>
}

export default Acme

This does not work and produces the same error:

/src/components/Acme.js: twin.macro: Property value expected type of string but got null Learn more: https://www.npmjs.com/package/twin.macro

This is so even though typeClass === typeObj.class evaluates to true.

I don't know if this is helpful, but perhaps it can help indicate a solution. If I can get the type prop to behave like the typeClass variable then hopefully this would work.

Either way, any idea why this is not working and how to fix it?

Thanks.

closed time in 5 days

thecodeclimber

issue commentben-rogerson/twin.macro

Cannot Get Values from Prop

Great you found an answer here.

To explain why your previous code wasn't working: Twin is a babel-plugin and babel plugins don't execute the javascript you write, they let you traverse over it and customise things. Babel doesn't have the ability to go searching for the variable you've defined within tw - it can do very basic executions but only when the variable it's looking for is plainly defined.

thecodeclimber

comment created time in 5 days

issue commentben-rogerson/twin.macro

Cannot Get Values from Prop

I found the answer (meaning that a user on your discord channel answered it). Here is is. I have to rewrite both the Component and the usage of the component as follows:

// Acme.js
const Acme = ({ children, type }) => <div css={[type]}>{children}</div>

---

// App.js
import tw from "twin.macro"

<Acme type={tw`text-2xl`}>Text Goes Here</Acme>

I have tried this out and it works.

thecodeclimber

comment created time in 5 days

issue commentben-rogerson/twin.macro

'css' is not exported from 'styled-components/macro'

FYI, I just tried this with npm install and I got the same error

'css' is not exported from 'styled-components/macro'

So I cleared away the repo, and tried again using yarn and everything seems to work.

hendrul

comment created time in 5 days

issue openedben-rogerson/twin.macro

Cannot Get Values from Prop

You can see an example of what I am trying to do here: https://codesandbox.io/s/vibrant-leaf-qj8vz

Note: this particular example is using Styled Components (I just modified your codesandbox demo). On my local computer I tried the same thing with the same results using emotion/next.js.

Here is a sample component illustrating what I am trying to do:

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

const Acme = ({ children, type }) => <div css={[tw`${type}`]}>{children}</div>

export default Acme

Here is how I would use that component: <Acme type="text-2xl">It does NOT work</Acme>

My expectation is that I will be able to style this instance of the <Acme /> component via the tailwind css classes that I pass into the type prop. Instead, I get the following error message:

/src/components/Acme.js: twin.macro: Property value expected type of string but got null Learn more: https://www.npmjs.com/package/twin.macro

When trying to figure this out, I noticed something interesting that may be relevant. Here is a variation of the code that does work:

const Acme = ({ children, type }) => {
  const typeClass = 'text-2xl'
  const typeObj = {
    class: 'text-2xl',
  }

  return <div css={[tw`${typeClass}`]}>{children}</div>
}

export default Acme

Note that I have created a variable typeClass and set it to the same tailwind css class. Note, in particular, the following line of code:

css={[tw`${typeClass}`]}

I have replace the prop type with the variable typeClass. This works. But now, instead of using the variable typeClass let's use the object typeObj that I have created as follows:

const Acme = ({ children, type }) => {
  const typeClass = 'text-2xl'
  const typeObj = {
    class: 'text-2xl',
  }

  return <div css={[tw`${typeObj.class}`]}>{children}</div>
}

export default Acme

This does not work. Even though typeClass === typeObj.class evaluates to true.

I don't know if this is helpful, but perhaps it can help indicate a solution. If I can get the type prop to behave like the typeClass variable then hopefully this would work.

Either way, any idea why this is not working and how to fix it?

created time in 5 days

pull request commentben-rogerson/twin.macro

Enhance nested bracket groups

hey @lightyen, is this PR ready for review?

Yes.

lightyen

comment created time in 5 days

pull request commentben-rogerson/twin.macro

Enhance nested bracket groups

hey @lightyen, is this PR ready for review?

lightyen

comment created time in 5 days

PR opened ben-rogerson/twin.macro

Add config presets

This PR adds tailwind.config.js presets so you can extend your config with other tailwind configs:

// tailwind.config.js

+ const extraConfig = {
+   theme: {
+     colors: {
+       hotpink: "hotpink",
+     },
+   },
+ };

module.exports = {
  theme: {
+   presets: [extraConfig],
    colors: {
      black: "#000000",
      white: "#ffffff",
    },
  },
};

Closes #255

+28 -7

0 comment

3 changed files

pr created time in 5 days

create barnchben-rogerson/twin.macro

branch : feature/presets

created branch time in 5 days

more