Coder Social home page Coder Social logo

ben-rogerson / twin.macro Goto Github PK

View Code? Open in Web Editor NEW
7.8K 32.0 184.0 5.51 MB

๐Ÿฆนโ€โ™‚๏ธ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components, solid-styled-components, stitches and goober) at build time.

License: MIT License

JavaScript 5.27% TypeScript 94.73%
tailwind tailwindcss css-in-js babel-macro tailwind-css styling-css-in-js emotionjs emotion twin babel

twin.macro's People

Contributors

abhijithvijayan avatar albohlabs avatar alessbell avatar anark avatar ben-rogerson avatar chrisebert avatar crisis2010 avatar dcwither avatar denvash avatar dependabot[bot] avatar dfee avatar eduardobautista avatar fknop avatar fvanwijk avatar gerhardsletten avatar gillkyle avatar haidarezio avatar itsmapleleaf avatar jackmcpickle avatar jonleopard avatar klittlepage avatar klzns avatar lightyen avatar macksi avatar minzojian avatar mohammadsiyou avatar onurgvnc avatar rbutera avatar soilspoon avatar theonesean avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

twin.macro's Issues

Gatsby caching issue

Hey!

I'm using twin.macro within a Gatsby site.

My setup is basically the same as in the readme.

I've created a custom tailwind.config.js and changed a few colors.

However, the new colors are only picked up after I manually delete the node_modules/.cache folder.

I've got no experience in using Babel macros but shouldn't the cache be cleared -- at least -- when I restart my dev server?

Or how is changing the tailwind config supposed to work?

Thank you for your amazing work!

Is there a way to compose tailwind.config.js file?

Hey,
First of all thank you very much work the great work you're doing with this plugin!

I just wanted to ask if there is a way to compose tailwind.config.js file from partials.

Let's say I have 3 partial configuration files

const screens = {
  sm: "640px",
  md: "768px",
  lg: "1024px",
  xl: "1280px",
} as const

export default screens
const borderRadius = {
  none: "0",
  sm: "0.125rem",
  default: "0.25rem",
  md: "0.375rem",
  lg: "0.5rem",
  full: "9999px",
} as const

export default borderRadius
const fontSize = {
  xs: "0.75rem",
  sm: "0.875rem",
  base: "1rem",
  lg: "1.125rem",
  xl: "1.25rem",
  "2xl": "1.5rem",
  "3xl": "1.875rem",
  "4xl": "2.25rem",
  "5xl": "3rem",
  "6xl": "4rem",
  "7xl": "5rem",
} as const

export default fontSize

And I would like to be able to compose final configuartion file using something like this inside my tailwind.config.js

const fontSize = require("./src/utils/tailwind-theme")

module.exports = {
  theme: {

    fontSize,

    extend: {
    },
  },
  plugins: [require("tailwindcss-elevation")(["responsive"])],
}

Unfortunately every time I try to require a file I get the following error.

Screenshot from 2020-04-20 18-47-03

Is there a way to solve this issue?

"inset" config option overwrites default classes

With empty config, I can write:

tw.div`absolute right-0`

But adding

inset: {
      "0": 0,
      "auto": "auto"
}

To the config, which is the default Tailwind config, right-0 doesn't resolve to a class.

Allow curly brackets to be used with the tw prop

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',
    },
}

Q: Why is emotion necessary with CRA?

The top of the readme there is the following simple way which is absolutely amazing at a first sight.

import tw from 'twin.macro'

const default () => <input tw="border hover:border-black" />

Furthermore, there is also this sentence which would give me the impression that without conditionals I can use macro only.

For features like conditional styling and vanilla css, Twin works with styling libraries like ๐Ÿ‘ฉโ€๐ŸŽค emotion or ๐Ÿ’… styled-components

Unfortunately, when I try that in a clean CRA project, the output I get is like this and that's where the magical feeling is kinda lost.

<input css="[object Object]" />

To make that work I have to include this ceremony in each file that needs some styling.

/** @jsx jsx */
import { jsx } from '@emotion/core'
import tw from 'twin.macro'

Is there some better way I am simply not seeing?

twin.macro: Invalid or unexpected token

Hey Ben,

thank you for your work. I was really looking forward to get tailwind working with emotion :)

My code was working quiet ok with tailwind.macro, I moved on to twin.macro and now end up with:

header.js: twin.macro: Invalid or unexpected token Learn more: https://www.npmjs.com/package/twin.macro

As soon I import the macro this error happens, I dont have to actually call it.

Unfortunately the error message does not tell me a lot about what and where sth went wrong :(

Related PR with my migration commit: hashbite/gatsby-mdx-suite#28

Any ideas?

Thanks again,
Benedikt

Is it possible to use to render on node-ts?

Hi! Rather than an issue, I'm raising a question.

I'm experimenting with different ways to build my emails that are sent from an express server. I was using only nodemailer, then I started to look for templating languages, then I thought on using react, as I already have some experience with it.

I managed to send emails with it (using sort of this solution), which is almost perfect, except to styling which is a mess to use inline styles.

I would really really love to use this with twin macro, inlining on "style" props with tailwind classes would be so awesome, perfect for email handling (the really only downside would be that I myself would care if some property isn't really compatible with mail).

I've spent my day trying to understand better babel/babel-macro/ts/node-ts stuff but I'm starting to think it isn't really compatible, and I'd like to know if anyone knows for sure it is or isn't...

or if you have some advice to get this workflow I'm trying to get.

Sending email from server is a known huge pain. It would be a breeze for people used to frontend developing to achive this workflow which is familiar, I guess.

thanks!

Payload size implications

Hi there,

I really like the idea of twin.macro. I'm curious there if the ramifications to payload size have been considered at all. The nice thing about tailwind and other utility css frameworks is that you only have to pay the penalty of a utility class once, no matter how many times you use it. With twin.macro, it seems that the utility class is actually inlined everywhere it's used, which not only increases its size, but it also increases the number of css rules added to the dom.

I could see a macro adding the classes used directly and including the appropriate stylesheet, still obviating purgecss. That'd obviously not play nearly as well with Emotion, which is the whole point...

Anyway, just curious what thoughts have been had about this. Thanks!

Theme is not defined

Hi,

As an old user of tailwind.macro, first off let me say I love twin.macro. Thanks for the amazing work on behalf of the community.

I have used Twin successfully on a fresh project and its worked brilliantly. However, I am having issues porting an older/large site from tailwind.macro to twin.macro.

After fixing all the old class names, I get the following on every file during 'Gatsby Develop'.

ERROR #98123  WEBPACK
Generating development JavaScript bundle failed
/xxxx/src/components/faqs/faq.js: twin.macro: theme is not defined Learn more: https://www.npmjs.com/package/twin.macro

I have tried everthing:

  • removed cache and public
  • reinstalled node modules
  • etc

To confirm, i have updated all files to call:
import tw from "twin.macro"
And in package.json I have the following (which works fine in my other smaller project)

"babelMacros": {
    "styledComponents": {
      "pure": true
    },
    "twin": {
      "config": "./tailwind.config.js",
      "styled": "styled-components",
      "format": "auto",
      "hasSuggestions": true,
      "debug": false
    }
  }

Any ideas at first glance?

Thanks,
A.

CRA Typescript error when using tw prop on html elements

Hi guys

Just started experimenting with twin.macro and after having followed all instructions for CRA/Emotion, I'm getting this error when trying to convert my first className to tw:

Type '{ children: Element; tw: string; }' is not assignable to type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'.
  Property 'tw' does not exist on type 'DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>'

I'm using CRA with the typescript template.

Is there anything else I need to adjust?

Cheers

Add installation for Next.js

Hi Ben!

Amazing work!

Could you please add installation for Next.js? Here's an example setup for next+tailwind+emotion setup on Next's Github page.

As an aside; in the create-react-app + emotion installation, I saw the following -

// In your App.js or index.js entry
// (tailwindcss is pre-installed with twin.macro)

What is tailwindcss here? Is it a .css file which contains the following?

@import "tailwindcss/base";
@import "tailwindcss/components";
@import "tailwindcss/utilities";

One last question; If I have installed Next.js + tailwindcss as shown on tailwindcss' Github repo, then how would I go about installing twin.macro?

Placeholder utility not working as expected

Just came across this yesterday, placeholder utility (ex. placeholder-red-500) does not work as expected. They instead apply the color property on the input element directly instead of the ::placeholder pseudoelement.

Here's a codesandbox .

(I think it's because how they are defined here ?)

placeholder: { prop: 'color', config: 'placeholderColor' },

I think they would need to be handled as a special case (like how you've done with :before and :after). I tried to find how one would do that but couldn't.

For now to get around this for other people who see this (that are using a css-in-jss solution), you have to apply styles using the ::placeholder pseudoelement manually

const Input = styled.input`
 ${tw`p-4`}
 ::placeholder { 
    ${tw`text-red-500`} 
}
`;

Comparison with tailwindcssinjs ?

Hello,

Thank you for this great lib, I'm using it in a project of mine, it's been great.

I'm usually more of a backend developer, so please excuse me if the answer to my question seems obvious.
I was looking at https://github.com/aniftyco/awesome-tailwindcss and saw :

@tailwindcssinjs/macro - Babel macro that transforms Tailwind CSS classes into objects for CSS-in-JS libraries.

Which, to me, sounded similar to what twin.macro is doing.
So, out of curiosity, I checked out the repo https://github.com/Arthie/tailwindcssinjs, and saw this commit : Arthie/xwind@7fa2d7e which basically just bump the tailwind version, whereas for twin.macro, quite a lot of work is going on to make it happen here #45

So I guess my question is what are the differences in these projects design that cause the 2 paths of upgrade ?
Would a comparison of the projects makes sense to help people pick the lib most suited to their needs ?
Would it make sense to mention twin.macro in https://github.com/aniftyco/awesome-tailwindcss so that more people get to know about it ?

Thank you !

Typescript support for extended Styled Components

Hi,
I've been using the macro to extend components and have recently started also using Typescript and I'm getting errors from the tsc when using extended components:

So, this works in regular JSX:

const PinkButton = tw(Button)`bg-pink`;

but when it becomes TSX then I get this error:

Argument of type 'FunctionComponent<Props>' is not assignable to parameter of type 'TemplateStringsArray'.

The workaround for this is to import styled and call it like this:

const PinkButton = styled(Button)`${tw`bg-pink`}`;

Which is great for now but everywhere else I'm using tw.div etc and would like to be able to consistently use tw instead of having to import styled when extending components.

#24 fixed other issues but there's still this case.

[Feature] Support for nested group rules within styled-components

I would like to use nesting of styled-components rules to apply group related styles; however, they get applied to the parent instead of the item they are nested within. I realize this may be a large ask, but I figured I would throw it out there. I've created an example repo here: https://codesandbox.io/s/priceless-voice-31441?file=/src/App.js

const NestedHeading = styled.h1`
  ${tw`text-4xl font-bold leading-loose text-blue-500`}

  > span {
    ${tw`transition group-hover:text-blue-900`}
  }
`;

export default function App() {
  return (
    <div className="App">
      <NestedHeading className="group">
        Nested rules via <span>styled-components</span>
      </NestedHeading>
   </div>
  );
}

support custom breakpoints

Thanks for making this module! I've been hoping to use the newer releases of Tailwind with Emotion.

I'm trying to use my custom @screen breakpoints with the macro, but can only seem to get the default breakpoints to work.

I'm using the approach mentioned by @llaski on this thread, by calling the _utils.stringifyScreen function. I recognize that this may not be intended as a public function, but it does work for the default breakpoints. Is there a way to have it recognize my custom breakpoints defined under my Tailwind config?

border-t/r/b/l doesn't automatically apply border style

tw.div`border-b border-black`

Should render a div width

border-bottom-width: 1px;
border-bottom-style: solid;
border-colour: #000000;

But what I get is

border-bottom-width: 1px;
border-colour: #000000;

If, instead, I write:

tw.div`border-b border-solid border-black`

I get

border-bottom-width: 1px;
border-style: solid;
border-colour: #000000;

Which renders a div with 2px border around, and 1px bottom!


I don't understand how to write an example with babel macros in CodePen. I'd happily fork one if one exists.

TypeScript CSSObject as String error

tl;dr

If using twin.macro inside a Styled Components template literal you get typescript errors.

Basic Example

const Submit = styled(SubmitButton)<submitButtonProps>`
  ${tw`w-full`}
`

then you get errors like these

Argument of type 'CSSObject' is not assignable to parameter of type 'Interpolation<any>'.
  Type 'CSSObject' is not assignable to type 'string'.

Complex Example

A more complex example:

const Container = styled.div`
  ${tw`flex flex-col max-w-sm w-full`}
  & > form {
    ${tw`w-full`}
  }
`

gives you the error

No overload matches this call.
  Overload 1 of 3, '(first: TemplateStringsArray | CSSObject | InterpolationFunction<ThemedStyledProps<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style" | ... 254 more ... | "css"> & { ...; }, any>>, ...rest: Interpolation<...>[]): StyledComponent<...>', gave the following error.
    Argument of type 'CSSObject' is not assignable to parameter of type 'Interpolation<ThemedStyledProps<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style" | "title" | "slot" | ... 252 more ... | "css"> & { ...; }, any>>'.
      Type 'CSSObject' is not assignable to type 'string'.
  Overload 2 of 3, '(first: TemplateStringsArray | CSSObject | InterpolationFunction<ThemedStyledProps<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style" | ... 254 more ... | "css"> & { ...; } & object, any>>, ...rest: Interpolation<...>[]): StyledComponent<...>', gave the following error.
    Argument of type 'CSSObject' is not assignable to parameter of type 'Interpolation<ThemedStyledProps<Pick<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "style" | "title" | "slot" | ... 252 more ... | "css"> & { ...; } & object, any>>'.
      Type 'CSSObject' is not assignable to type 'string'.

Please Change TemplateFn values type

After 1.0.0 release.

It works like this โฌ‡๏ธ

export type TemplateFn<R> = (
  strings: TemplateStringsArray,
  ...values: string[]
) => R

image

npm bump please

Hey Ben, Thanks for all your work on this lately. Really love it. Would you mind doing a version bump on npm? I was patching that container commit into it, but I'm having problems with the production build step. ๐Ÿ˜…

`Cannot read property 'name' of undefined` when passing {...props} to a component

Hi!

I'm sorry if this has been documented somewhere. I couldn't find anything regarding to this at least. First, I love tailwind and I love twin.macro! โค๏ธ I love your work.

The issue is that everytime I create a component like this...

import React from 'react';
import tw from 'twin.macro';
import { css } from 'styled-components/macro';

const Example = ({...props}) => (
  <div tw="inline-block" {...props} />
);

...this error happens:

TypeError: /Users/nico/Dev/tailbook/src/Responsive/index.js: twin.macro: Cannot read property 'name' of undefined Learn more: https://www.npmjs.com/package/twin.macro
    at /Users/nico/Dev/tailbook/node_modules/twin.macro/macro.js:2521:68
    at Array.filter (<anonymous>)
    at JSXAttribute (/Users/nico/Dev/tailbook/node_modules/twin.macro/macro.js:2521:27)
    at NodePath._call (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/path/context.js:55:20)
    at NodePath.call (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/path/context.js:42:17)
    at NodePath.visit (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/path/context.js:90:31)
    at TraversalContext.visitQueue (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/context.js:112:16)
    at TraversalContext.visitMultiple (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/context.js:79:17)
    at TraversalContext.visit (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/context.js:138:19)
    at Function.traverse.node (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/index.js:84:17)
    at NodePath.visit (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/path/context.js:97:18)
    at TraversalContext.visitQueue (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/context.js:112:16)
    at TraversalContext.visitSingle (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/context.js:84:19)
    at TraversalContext.visit (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/context.js:140:19)
    at Function.traverse.node (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/index.js:84:17)
    at NodePath.visit (/Users/nico/Dev/tailbook/node_modules/@babel/traverse/lib/path/context.js:97:18)

What I found out is:

  • When I remove {...props}, it works.
  • When I use css={tw``inline-block``}, it works.
  • It doesn't matter if props are actually passed to the component or not
  • The order doesn't matter either ({...props} before or after tw="")

This does ALSO happen with the codesandbox example you linked in your README.

With styled-components:
Screenshot 2020-04-07 at 11 09 06

With emotion:
Screenshot 2020-04-07 at 11 11 27

You can reproduce this by changing the Logo component like this:

const Logo = ({ ...props }) => (
  <a
    // Use the tw prop to add Tailwind styles directly on jsx elements
    tw="w-32 m-10 p-5 block opacity-50 hover:opacity-100"
    href="https://github.com/ben-rogerson/twin.macro"
    target="_blank"
    rel="noopener noreferrer"
    {...props}
  >
    <TwinSvg />
  </a>
)

So I feel like this is not specific to my setup but more of a general issue. Is this intended behaviour?

position/inset not detected

hi @ben-rogerson , and thanks for your plugin.

trying to migrate vom tailwind-canary.macro to twin.macro. everything works except one thing.

  1. positions not working for me
import tw from "twin.macro";

const Base = styled.div`
    ${tw`top-0 hidden md:flex flex-row mb-4 md:sticky z-50`}
`

results in

top-0 was not found

in my config im not using inset

Transforms only work if applied after classes like rotate, translate

tw.`rotate-90 transform` works as expected
however, tw.`transform rotate-90` doesn't work.

Seems anything set by transform isn't overridden later, so since transform already sets --transform-rotate: 0, rotate-90 is not applied. Same goes for all scale,skew, translate classes.
Also using rotate-90! does nothing.
It all only works if the order is reversed. TailwindCSS makes all rules set by these secondary utils (rotate, skew, etc) as !important so they override.

Thank you for the amazing library btw ๐Ÿ˜„

Plugin style merge issues: Rules appear to be getting overwritten by 2nd class not merged into rules from 1st class

Demo of a problem I am seeing.

I created a plugin for sidebar styling it is incomplete but I was seeing something that surprised me.
I am not certain this is a bug, but it's not doing what I expected, though possibly my expectations may be faulty.

Styles from two classes appear to be getting over written for a given style rule path "> *" rather than merged, so the 2nd classes styles for that path are replace the rules from the first class styles.

https://codesandbox.io/s/cra-tailwind-emotion-starter-demo-possible-style-not-merging-bug-twinmacro-tf4vk

I found if i use the rule .with-sidebar__rightAlternate the styles merge but its kind of cheating by adding > *:first-child so it doesn't match the rule > * used in .with-sidebar.

The plugin creating the styles.

function sidebarPlugin({ addUtilities }) {
  addUtilities({
    [`.with-sidebar > *`]: {
      display: 'flex',
      flexWrap: 'wrap'
    }
  })
  addUtilities({
    [`.with-sidebar__right > *`]: {
      flexDirection: 'row-reverse'
    }
  })
  addUtilities({
    [`.with-sidebar > * > *`]: {
      flexGrow: 1
    }
  })
  // last-child is always not-sidebar
  addUtilities({
    [`.with-sidebar > * > *:last-child`]: {
      flexBasis: 0,
      flexGrow: 999,
      minWidth: `calc(50%)`
    }

  addUtilities({
    [`.with-sidebar__rightAlternate > *:first-child`]: {
      flexDirection: 'row-reverse'
    }
  })
  })
}

Styles rules from different classes not merging.

twwith-sidebar with-sidebar__right styles
This shows style "> *" has lost the flex and wrap settings from with-sidebar. Which ever class name is last overwrites the first, it does not merge.

{
  "> *": {
    "flex-direction": "row-reverse"
  },
  "> * > *": {
    "flex-grow": "1"
  },
  "> * > *:last-child": {
    "flex-basis": "0",
    "flex-grow": "999",
    "min-width": "calc(50%)"
  }
}

twwith-sidebar__right with-sidebar styles
This shows style "> *" has lost the styles from with-sidebar__right. Which ever class name is last overwrites the first, it does not merge.

{
  "> *": {
    "display": "flex",
    "flex-wrap": "wrap"
  },
  "> * > *": {
    "flex-grow": "1"
  },
  "> * > *:last-child": {
    "flex-basis": "0",
    "flex-grow": "999",
    "min-width": "calc(50%)"
  }
}

twwith-sidebar styles

{
  "> *": {
    "display": "flex",
    "flex-wrap": "wrap"
  },
  "> * > *": {
    "flex-grow": "1"
  },
  "> * > *:last-child": {
    "flex-basis": "0",
    "flex-grow": "999",
    "min-width": "calc(50%)"
  }
}

twwith-sidebar__right styles

{
  "> *": {
    "flex-direction": "row-reverse"
  }
}

Is there a way to use variables for colour names with emotionjs + twin?

I have an array which contains key-value pairs as follows -

const colourTypeMapping = [
  { type: "normal", color: "bg-orange-700" },
    .
    .
    .
]

Now, I want to create a <div> </div> which has some base styles but it uses the bg-color from the above colourTypeMapping array.

For instance,

const StyledDiv = (props) => {
    const {objType} = props
    // search for the type in `colourTypeMapping` and save in the variable `col` below
    const objFound = colourTypeMapping.find(obj => obj.type === objType)
    const col = objFound.color

    return (
    )
}

How do I complete the above component?

Improve debugging tw prop styling

When tw prop is used, on the output we get for example class="App___StyledDiv-sc-1r3ydil-0 ksfoHe". In a bigger tree, it's impossible to identify elements like that. I am aware that's a tradeoff of not naming components.

export default function App() {
  return (
    <div tw="max-w-md mx-auto flex p-6 bg-gray-100 mt-10 rounded-lg shadow-xl" />
  )
}

Unfortunately, React Devtools is not helping here either.

image

It would be really useful if we could see TW styles along with the resulting CSS styles.

What comes into my mind is in DEV mode to basically include data-tw="..." prop with an original value that wouldn't be transformed.

<div class="App___StyledDiv-sc-1r3ydil-0 ksfoHe" data-tw="max-w-md mx-auto flex p-6 bg-gray-100 mt-10 rounded-lg shadow-xl" />

I assume that React Devtools can't be improved here, that would require something from SC/Emotion.

Trying out plugin addUtilities noticed a few errors output in console

I created an example sandbox forked from one I stumbled on that you created.
https://codesandbox.io/s/cra-tailwind-emotion-starter-4wkeh

My fork adds a plugin to tailwind.config.js then replaces the styling in App.tsx with the new "stack" class that the plugin implements.
When loading I see 4 errors reported in the console when you load it.
Everything appears to work correctly, just the errors come out and I thought they may indicate a problem internally somewhere.

I am pretty sure I have the styles correct so maybe twin.macro has converted them to real styles before it reaches emotion somewhere ?

So far liking twin.macro, interesting stuff.

This is what my tailwind.config.sj file looks like with the plugin added.
The plugin adds stack classes as created and documented by https://every-layout.dev/layouts/stack/

// In CRA, this config file must be inside the src
// so it can be imported by the theme provider

const stackPlugin = ({ addUtilities, theme }) => {
  const spacing = theme('spacing', {})
  const stackCommon = {
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'flex-start'
  }
  const my_0 = {
    marginTop: 0,
    marginBottom: 0
  }
  const defaultSpacing = spacing['6']
  addStackComponent('.stack', defaultSpacing)
  addRecursiveStackComponent('.rstack', defaultSpacing)
  Object.entries(spacing).forEach(([k, v]) => {
    addStackChildren(`.stack-${k}`, v)
    addStackChildren(`.rstack-${k}`, v, '')
  })

  function addStackComponent(baseName, marginTop) {
    addUtilities({ [baseName]: stackCommon })
    addStackChildren(baseName, marginTop)
  }

  function addRecursiveStackComponent(baseName, marginTop) {
    addUtilities({ [baseName]: stackCommon })
    addStackChildren(baseName, marginTop, '')
  }

  function addStackChildren(baseName, marginTop, child = '>') {
    addUtilities({ [`${baseName} ${child} *`]: my_0 })
    addUtilities({ [`${baseName} ${child} * + *`]: { marginTop } })
  }
}

module.exports = {
  theme: {
    extend: {}
  },
  plugins: [stackPlugin]
}

This is the updated App in App.js

const App = () => (
  <Theme>
    <div
      css={[
        tw`h-screen flex flex-col items-center justify-center`,
        // Combine regular css and Tailwind styles within backticks
        css`
          * {
            ${tw`mt-6`}
          }
          background: linear-gradient(#db00ff, #0047ff);
        `
      ]}
    >
      <div tw="stack">
        <Button isPrimary>Submit</Button>
        <Button isSecondary>Cancel</Button>
        <Button isSmall>Close</Button>
      </div>
      <Logo />
    </div>
  </Theme>
)

These are the errors I see in console.
image

Position class disappear when container applied

Hello, the position class seems cannot place together with container.

Without container:

const WebNav = tw.nav`relative flex justify-between items-center mx-auto`

The position class is applied:
1

With container:

const WebNav = tw.nav`relative container flex justify-between items-center mx-auto`

The position class disappear:
2

Falsy values in tailwind config trigger class not found

Hello there,

First of all, thanks for this library. Even though it's still young, it is showing promising things and I'm eager to see future releases !

I'm posting due to a weird issue I'm encountering on my GatsbyJS project.
I have setup a project as stated in the docs, and am using Twin with Emotion.

I've customized the "inset" section of my Tailwind theme as is :
inset: { '0': 0, auto: 'auto', 'icon-offset': '19px', }

From time to time, I don't know why it doesn't always occur, I'm getting this error message and my bundle no longer builds :

Generating development JavaScript bundle failed
<hidden location>/frontend/src/mixins/Forms.ts:

โœ• inset-y-0 was not found
Did you mean inset-y-0?

File: src/mixins/Forms.ts

I've tried restarting the dev server, clearing the .cache folder inside node_modules, nothing helps. I can sometimes get rid of the error by removing all inset classes from the incriminated file and let livereloading do its job.

Any ideas why this happens ?
Let me know if I can help you with anything by providing you any specific details.

CRA + Twin.Macro Component UI Monorepo

To start off, I wanna say thank you @ben-rogerson for building this! I was in the process doing just that for tailwindcss 2.0 support but then came across this, so thank you.

Im in the process of setting up a monorepo with a CRA app + components ui library and I end up getting the following error when building the CRA:

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

Im assuming this is from default CRA babel config, but it works when removing tw from the styled-component macro from the component library. I set up the following repro for reference: https://github.com/skene/cra-twin.macro-monorepo

I have a feeling im being stupid and missing something obvious.

String interpolation inside tw macro doesn't work

Hi!

I have a problem with string interpolation in tw macro.
For example I need to customize border color, so I'm trying to do it like this:

export const PrimaryButton = styled(Button)`
  ${({ color }) => tw`hover:border-${color ?? 'blue'}`};
`;

But I get the following error:
โœ• Class โ€œhover:border-โ€ shouldnโ€™t have a trailing dash.

It also doesn't work without variables:

export const PrimaryButton = styled(Button)`
  ${({ color }) => tw`hover:border-${'blue'}`};
`;

autocomplete

I'm considering twin for a Gatsby project, however I really miss the tailwind intellisense. Any idea on how I can have a similar experience? I've tried the typescript-plugin-tw-template package, but it doesn't seems to work.

Support for 'group' and 'group-hover'

Hi,

Love twin.macro - amazing work!

We have noticed a small issue when trying to use 'group' and 'group-hover' tailwind utilities.

We get the following error message:

ERROR #98123  WEBPACK
Generating development JavaScript bundle failed
/xxxxx/Appssubmenu.js:
โœ• group was not found

We tested the above with the following code (taken from tailwind docs)

<div css={tw`group`}>
  <p css={tw`group-hover:text-white`}>Create a new project from a variety of starting templates.</p>
</div>

Have you or anyone else come across this?

Thanks,
Adrian

add eslint, configurations, and add to precommit hook

Please Note: I am willing to personally contribute this if @ben-rogerson approves.

Motivation

twin.macro is gaining some traction and contributions are coming in from the community.

I think it would be wise to now enforce some code quality and increase stability through the addition of static code testing as a pre

Steps to Solve

To achieve this I think that we should:

  • remove pretty-quick
  • Install prettier as a dev dependency (behaves well with eslint -- see proposal below)
  • install eslint as a dev dependency
  • install relevant plugins (see proposal below)
  • install lint-staged as a dev dependency
  • add lint-staged to the husky git pre-commit hook
  • add eslint and prettier to the lint-staged configuration

Proposed Configuration

The following configurations I would propose we use are adopted from a project that I am currently using twin.macro in.

eslint

Plugins Used

It uses the following plugins:

  • @typescript/eslint
  • unicorn
  • xo
  • chai-friendly
  • jest
  • import
  • prettier

Configuration File

// .eslintrc.js

module.exports = {
  settings: {
    version: 'detect',
  },
  extends: [
    'eslint:recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:unicorn/recommended',
    'xo/browser',
    'xo/esnext',
    'xo-typescript/space',
    'xo-react/space',
    'plugin:chai-friendly/recommended',
    'plugin:jest/recommended',
    'plugin:import/errors',
    'plugin:import/warnings',
    'plugin:import/typescript',
    'prettier/@typescript-eslint',
    'prettier',
    'prettier/babel',
    'prettier/react',
    'prettier/unicorn',
  ],
  plugins: ['chai-friendly', 'jest', 'import'],
  rules: {
    '@typescript-eslint/semi': 0,
    '@typescript-eslint/restrict-template-expressions': 0,
    '@typescript-eslint/default-param-last': 0,
    'react/prop-types': 0,
    'jest/prefer-expect-assertions': 0,
    'capitalized-comments': 0,
    'comma-dangle': 0,
    'import/extensions': [
      'error',
      {
        svg: 'allow',
      },
    ],
    'import/no-unassigned-import': [
      'error',
      {
        allow: ['**/*.css'],
      },
    ],
  },
  overrides: [
    {
      files: ['**/*.ts', '**/*.js'],
      rules: {
        'jest/no-try-expect': 0,
      },
    },
    {
      files: ['**/*.js', '**/*.jsx'],
      rules: {
        '@typescript-eslint/explicit-function-return-type': 0,
        '@typescript-eslint/space-before-function-paren': 0,
        '@typescript-eslint/no-unsafe-call': 0,
        '@typescript-eslint/no-unsafe-member-access': 0,
        '@typescript-eslint/prefer-readonly-parameter-types': 0,
      },
    },
  ],
}

Husky / Lint-Staged

// package.json
{
"husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "*.{js,ts,jsx,tsx}": [
      "eslint --cache --fix",
      "jest --findRelatedTests"
    ],
    "*.{js,ts,jsx,tsx,json,md}": [
      "prettier --write"
    ]
  }
}

Prettier

// .prettierrc
{
  "endOfLine": "lf",
  "semi": false,
  "singleQuote": true,
  "bracketSpacing": false,
  "tabWidth": 2,
  "jsxBracketSameLine": false,
  "trailingComma": "es5",
  "useTabs": false
}

Show all not found classes at once

I change my tailwind config classes every now and then (maybe more than I should ๐Ÿ˜…), and the not-found errors help a ton already, but it'd be even nicer if the plugin could print all of the invalid class errors at once, instead of me having to go through the rhythm of saving and waiting for the next one.

Changelog needed

It's not that easy to see what was changed between different releases.
I think that CHANGELOG.md would be a great addition to this project.

Thanks for your work!

How might I get twin.macro styles inline in dom markup?

Thanks for this project.
I was pleasantly surprised to find this project to get tailwindcss into css in js space (after finding tailwind.macro and reading a lot of other stuff to get to twin.macro).

I have several years of React development experience but very little with css in js.
I was trying this out to get a feel for emotion css in js and nextjs.
I mocked up the small notification example from the tailwindcss documentation here https://tailwindcss.com/docs/utility-first as per this screen shot from that documentation.

image

The below works fine but I think there are benefits if I could get the styling definition inline with the markup without creating those intermediate styled components.

Possibly there are other ways to approach this problem without getting the inline behaviour I am asking about. If so I happy to hear about alternatives.
(Updated the example code with better named helpers).

const NotifyOuter = tw.div`max-w-sm mx-auto flex p-6 bg-white rounded-lg shadow-xl`
const LeftLogo = tw.div`flex-shrink-0`
const Logo = tw.img`h-12 w-12`
const RightCaption = tw.div`ml-6 pt-1`
const CaptionHeading = tw.h1`text-xl text-gray-900 leading-tight` // a11y dont use H4 here confusing.
const CaptionBody = tw.p`text-base text-gray-600 leading-normal`

const NotificationExample = () => (
  <NotifyOuter>
    <LeftLogo>
      <Logo src="/chit-chat-logo.svg" alt="ChitChat Logo" />
    </LeftLogo>
    <RightCaption>
      <CaptionHeading>ChitChat</CaptionHeading>
      <CaptionBody>You have a new message! You have a new message! You have a new message! You have a new message!</CaptionBody>
    </RightCaption>
  </NotifyOuter>
)

Issues pre-bundling twin components with Rollup and importing them

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

Is there a way to get Tailwind UI to work with this?

Apologies if this is rudimentary information, I'm new to the world of Tailwind CSS. Would it be correct to assume issue #7 is somewhat connected to having the ability to use @tailwindcss/ui (if it is considered a plugin)?

TailwindUI is an official product, a set of components built using TailwindCSS. In order to currently use it, there is a small adjustment that is needed on the PurgeCSS regex case (inside postcss.config.js) when setting up for TailwindUI. I am not sure if this is something Twin.macro would help with or if that'll be more for emotion to deal with.

I'm trying to use this Next.js + Tailwind + Emotion example, and want it for SSR reasons, but I can't currently seem to figure out what I need to connect TailwindUI to this system. Any input on the topic would be really welcome. Thank you for the great alternative to tailwind.macro!

Using props to add tailwind classes

I'm trying to use props to add in some tailwind classes so that a component can pass down a particular colour and it gets picked up by tailwind and applied.

So I'm doing something like this <MyComponent customColor="red" /> and then, using Emotion, I have something like this

const MyComponent = styled.div([
     ({ customColor }) => tw`bg-${customColor}-500`,
     tw`border`,
     css`...`,
])

But I get an error

โœ• Class โ€œbg-โ€ shouldnโ€™t have a trailing dash.

Any ideas what I'm doing wrong?

Vue + Emotion + Tailwind Starter: babel-preset-css-prop alternative required

I've put together a sandbox demo for using twin.macro in Vue and need some help.

I want to use a css function so I can write css alongside tw classes in a styled block.
I've got it working using @emotion/babel-preset-css-prop however there's a dependency chain that requires react to be installed ๐Ÿ˜ฑ

๐Ÿ”ฅ Vue + Emotion + Tailwind Starter

Looking for a little help on how I can remove this React dependency and still use the css function.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.