Need help with tailwind-ppx?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

dylanirlbeck
152 Stars 16 Forks MIT License 285 Commits 19 Opened issues

Description

A Reason/OCaml Pre-Processor eXtension (PPX) that validates your Tailwind classes at compile-time.

Services available

!
?

Need anything else?

Contributors list

Note: As of 08/16/2021,

tailwind-ppx
is now in archive-mode. I have been out of the Reason/ReScript community for some time now, but if anyone wants to take over as owner please let me know. Thank you to all involved for making this project successful.


tailwind-ppx

Actions Status NPM Version All Contributors

A Reason/OCaml Pre-Processor eXtension (PPX) that validates your Tailwind classes at compile-time.

Table of Contents

Features

Current

  • Checks for invalid class names (and suggestions for valid ones!)
  • Checks for duplicate class names
  • Always in-sync with your
    tailwind.css
    file (just make sure to re-build!)
  • Automatic purging of unused class names (with PurgeCSS and
    tailwind-ppx
    's custom extractor function)
  • Ships with an integration script that converts all your existing
    className="..."
    to
    className=[%tw "..."]

Upcoming

  • Better integration with PostCSS
  • Checks for redundant class names (like having both
    flex-row
    and
    flex-col
    )
  • Checks for class name dependencies (like having
    flex-row
    without
    flex
    )

If you have ideas for new features, please open an issue!

Usage

tailwind_ppx
implements a ppx (
%tw
) that validates your Tailwind CSS classes at compile time.

For example, for the following (condensed)

tailwind.css
file:
.flex {
  display: flex;
}

.flex-row { flex-direction: row; }

tailwind-ppx
will provide validation for your desired class names. See these examples:
// Example 1
 // This is ok!

// Example 2 // ERROR: Class name not found: flex-ro. Did you mean flex-row?

// Example 3 // ERROR: Duplicate class name: flex

Finally,

tailwind-ppx
requires your generated
tailwind.css
file to exist somewhere in the project hierarchy. Though not required, it's recommended that you configure the path to your
tailwind.css
file (relative to your project root).

Getting ready for production

As outlined in the Tailwind docs, when preparing for production you'll want to make sure that the only CSS from Tailwind that ends up in your bundle is CSS that you actually use in your code.

First, take a second to read the section on setting up Purgecss from the Tailwind docs. In order to help with the process outlined in the docs, this package ships with a default extractor function that'll take care of ensuring that any CSS from Tailwind that you aren't using with this PPX can be purged from your production CSS bundle. You enable it by slightly modifying the official example of how to set up your

postcss.config.js
:
// postcss.config.js
const purgecss = require("@fullhuman/postcss-purgecss")({
  // Specify the paths to all ReasonML code where you're using this PPX.
  content: ["./src/**/*.re"],

// Include the extractor from this package defaultExtractor: require("@dylanirlbeck/tailwind-ppx").extractor });

module.exports = { plugins: [ require("tailwindcss"), require("autoprefixer"), ...(process.env.NODE_ENV === "production" ? [purgecss] : []) ] };

Doing this will ensure that you only ship CSS from Tailwind to production that you're actually using with this PPX.

Moving or changing your
tailwind.css
file

If your

tailwind.css
file changes (or you move it) you'll need to rebuild your project - for example,
bsb -clean-world
and
bsb -make-world
if in BuckleScript. At this time,
tailwind-ppx
does not automatically watch for changes, though this is on the roadmap.

Alternatively, you can add the following rules to you bsconfig.json to re-trigger builds

{
  "sources": [
    {
      "dir": "src",
      "subdirs": true,
      "generators": [
        {
          "name": "gen-tailwind",
          "edge": ["tailwind.css", ":", "styles.css"]
        }
      ]
    }
  ],
  "generators": [
    {
      "name": "gen-tailwind",
      "command": "tailwindcss build $in -o $out"
    }
  ]
}

If you have a custom tailwind config file, you'll need to pass it to the tailwindcss command:

{
  "name": "gen-tailwind",
  "command": "tailwindcss build $in -o $out -c ../../tailwind.config.js"
}

You might have to specify the path to

tailwind.css
.

Autocompletion (Neovim only)

If you're a Neovim user, you can download the

coc-tailwindcss
extension to get class name autocompletion while using

tailwind-ppx
- just make sure to define a
tailwind.config.js
file. See the example below!

Ignore
.tailwind_ppx_cache
in your version control

tailwind-ppx
will generate a
.tailwind_ppx_cache
folder in your project root to optimize the validation performance. If you're using a version control system, you don't need to check it in.

Configuration

-path

By default,

tailwind-ppx
looks for your
tailwind.css
file in the root directory. If
tailwind.css
lives elsewhere (or the name of your generated CSS file is different), you'll need to specify the file path in your
bsconfig.json
.
"ppx-flags": [
  ["tailwind-ppx", "-path ../path/to/tailwind.css",]
],

Installation

The most likely use case for

tailwind-ppx
is inside ReasonReact projects (using BuckleScript). To get started, we recommend cloning our demo project.

With
yarn
or
npm
on Bucklescript projects (recommended)

Install the PPX with

yarn
or
npm
yarn add --dev @dylanirlbeck/tailwind-ppx
# Or
npm install --dev @dylanirlbeck/tailwind-ppx

And add the PPX in your

bsconfig.json
file:
{
  "ppx-flags": ["tailwind-ppx"]
}

Integration script

The

@dylanirlbeck/tailwind-ppx
NPM package ships with an executable that, when run in a BuckleScript project, turns all instances of
className="..."
into
className=[%tw "..."]
. The script is designed to make it easy to immediately introduce
tailwind-ppx
into an existing codebase.

You can use this script by running the following command from the root of your project (just make sure you've installed the NPM package).

yarn use-tailwind-ppx
# Or
npx use-tailwind-ppx

Note that you'll need both a

bsconfig.json
to exist in the project hierarchy and compiled project with
bsb -make-world
(so the
lib/
directory exists in the project root) for the script to work properly.

FAQ

  • How can I conditionally add classes?

This feature is out of scope for

tailwind-ppx
; instead, we recommend you use
re-classnames
in combination with
tailwind-ppx
. See the example below:
  module SomeComponent = {
    [@react.component]
    let make = (~someBool) => {
      let className =
        Cn.(
          [%tw "text-blue-500"]->on(someBool)
          + [%tw "text-gray-500"]->on(!someBool)
        );
      
; }; };
  • How can I use custom CSS classes?

tailwind-ppx
directly parses your generated
tailwind.css
file, which means that all CSS classes will be validated by the PPX, including custom class names defined in your base
index.css/styles.css
file. In short, if the class is in your
tailwind.css
file, it will be validated correctly by the ppx.

Example:

   // ERROR: Class name not found: customLayou. Did you mean customLayout?

Developing

After cloning the repository, you should run

esy
to install the project dependencies. After that, you should be good to start developing!

Relevant commands

  • esy build
    -> Builds the project
  • esy format
    -> Formats the entire project with
    ocamlformat
    and
    refmt
  • esy watch
    -> Watches for changes to Reason/OCaml files in the entire project, including in the
    /test
    directory
  • esy test_native
    -> Runs the native tests (in
    test/native
    )
  • cd test/bucklescript && yarn test
    -> Runs the BuckleScript tests (in
    test/bucklescript
    )

Note that if you pull requests are not formatted properly, or the

esy.lock
is out-of-date, GitHub actions will automatically format your code by pushing up a new commit.

Releasing (for maintainers)

  1. Bump the version of the ppx in
    esy.json
    on
    master
    (we use semantic versioning)
  2. Create and push a new tag
$ git checkout master
$ git tag vx.y.z
$ git push origin vx.y.z
  1. Create detailed release notes for the new version, following the
    Added/Changed/Fixed/Removed
    format. Note that the new version of the PPX will automatically be pushed to NPM and a release will be created on GitHub.
  2. Make sure that for any merged pull requests/closed issues were noticed by the
    all-contributors
    bot -- see this PR for an example of adding a new contributor who's PR was merged.

Contributors ✨

Thanks goes to these wonderful people:


Dylan Irlbeck

💻 📖

Corentin Leruth

💻 🤔 🚧

Gabriel Nordeborn

💻 🤔

Brad Dunn

💻 🐛

Thomas Coopman

🐛 📖

Manas

📖

Peter Piekarczyk

🤔

Patrick Kilgore

📖

ahzm

💻 📖 🤔

Joseph Price

💻

Vladimir Danchenkov

📖

Jonas Zeitler

💻

Pete Shaw

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

Other

Examples

These projects are using

tailwind-ppx
throughout the code base:

Related Projects

The following amazing projects provided a lot of inspiration; I recommend you check them out!

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.