Tailwindcss: [Proposal] Open the compiler's API to allow creating compilers to other languages

Created on 26 May 2019  路  1Comment  路  Source: tailwindlabs/tailwindcss

Use Case:

I'm using React in conjunction with styled-components. Styled components don't allow extending global classes, so it's an entire adventure to use them with tailwind.

Existing Solution's Issues:

There's a babel macro that you can find here https://github.com/bradlc/tailwind.macro. It works, however, it doesn't support plugins (I had to re-implement .container myself) and has issues. After looking at its source I found that the creator basically wrote his own compiler that replicates tailwind's compiler, thus he's not planning to support all the features. It's also possible that one day he'll be behind tailwind's releases, which happens a lot with libraries like that.

My proposal:

I propose opening tailwind's complier's API to allow creating custom compilers. I don't mean just calling the compiler from code, but allowing developers to get _nodes_ that they can put into code themselves.

Here's how I would imagine it:

import { compile } from 'tailwindcss-compiler'
import { twNodeToStyled } from './parser'

compile({ configPath: 'tailwind.config.js' })
  .then(nodes =>
    twNodesToStyled(nodes, { output: 'styled-tailwind.js' })
  )

Thus a Tailwind node could look something like this:

{
  className: 'bg-blue-300',
  variants: ['sm', 'md', 'lg', 'hover', 'focus'],
  css: {
    rule: 'background-color',
    value: '#90cdf4'
  }
}

Plus the nodes object should include variant values such as:

{
  variant: 'sm',
  mediaQuery: 'min-width: 640px'
}

Then using that node I could generate the following object compatible with styled-components:

{
  bgBlue400: css`background-color: #90cdf4;`,
  sm: {
    bgBlue400: css`
      @media(min-width: 640px) {
        background-color: #90cdf4;
      }
    `
  },
  md: {
    bgBlue400: css`
      @media(min-width: 768px) {
        background-color: #90cdf4;
      }
    `
  },
  hover: {
    bgBlue400: css`
      :hover {
        background-color: #90cdf4;
      }
    `
  },
  focus: {
    bgBlue400: css`
      :focus {
        background-color: #90cdf4;
      }
    `
  }
}

Then I can use it in styled-components with syntax similar to native tailwind syntax, but JS compatible:

const Component = styled.div`
  ${bgBlue400}
  ${focus.bgBlue400}
`

Conclusion:

Opening the tailwind compiler's API this way will open the possibility for many other plugins and custom compilers, which will eliminate the need for hacky ways of using tailwind in modern web apps :)

It's totally possible that I missed something while coming up with this, so feel free to add or amend anything.

Most helpful comment

We actually don't have any sort of intermediate representation of the CSS Tailwind generates, it's simply a PostCSS plugin so the nodes we manipulate are PostCSS nodes.

You could absolutely write a PostCSS plugin that receives the nodes as processed by Tailwind and does whatever you want with them, including generating a different object for use in other ways 馃憤

I'm not really sure what we can do on the Tailwind side to make this easier or anything without some dramatic reimplementation of the code, since there really is no "compiler" or anything, we just walk a PostCSS tree and mutate it.

If you actually read the source and have some specific ideas on changes that would let you do things you can't currently do I'm open to hearing them 馃憤 These two blog posts are a pretty good introduction to understanding how Tailwind works:

https://dev.to/mariowhowrites/parsing-open-source-tailwind-css-39j7
https://dev.to/mariowhowrites/parsing-open-source-tailwind-css-part-2-2kga

In the mean time I'm going to close this specific issue with no plans to change anything because there's a bit of a mismatch between what you're asking for and how Tailwind works, so there's nothing I can realistically do to satisfy this request.

>All comments

We actually don't have any sort of intermediate representation of the CSS Tailwind generates, it's simply a PostCSS plugin so the nodes we manipulate are PostCSS nodes.

You could absolutely write a PostCSS plugin that receives the nodes as processed by Tailwind and does whatever you want with them, including generating a different object for use in other ways 馃憤

I'm not really sure what we can do on the Tailwind side to make this easier or anything without some dramatic reimplementation of the code, since there really is no "compiler" or anything, we just walk a PostCSS tree and mutate it.

If you actually read the source and have some specific ideas on changes that would let you do things you can't currently do I'm open to hearing them 馃憤 These two blog posts are a pretty good introduction to understanding how Tailwind works:

https://dev.to/mariowhowrites/parsing-open-source-tailwind-css-39j7
https://dev.to/mariowhowrites/parsing-open-source-tailwind-css-part-2-2kga

In the mean time I'm going to close this specific issue with no plans to change anything because there's a bit of a mismatch between what you're asking for and how Tailwind works, so there's nothing I can realistically do to satisfy this request.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jvanbaarsen picture jvanbaarsen  路  3Comments

nternetinspired picture nternetinspired  路  3Comments

smbdelse picture smbdelse  路  3Comments

jbardnz picture jbardnz  路  3Comments

dbpolito picture dbpolito  路  3Comments