Skip to content

Conversation

thecrypticace
Copy link
Contributor

This PR builds on #127 to add support for sorting custom attributes, functions, and tagged template literals.

To do this we've added two new options to the plugin, tailwindAttributes and tailwindFunctions, which together enable sorting of classes in custom attributes, tagged template literals, and functions that take class lists as arguments.

Sorting classes in custom attributes

When using libraries that offer abstractions over class or className, or when building your own components that take multiple lists of classes as props, you may want to sort classes in custom attributes. To do this you can specify a list of additional attributes in the tailwindAttributes option in your Prettier configuration file.

For example, you can enable sorting of tw attributes like this:

// prettier.config.js
module.exports = {
  tailwindAttributes: ["tw"],
};
// Example.jsx
// An example of a component that takes a `tw` prop that functions like `clsx`
function MyButton({ isHovering, children }) {
  return (
    <StyledButton
      tw={{
        "rounded py-2 px-4 text-base bg-blue-500 text-white": true,
        "bg-blue-700 text-gray-100": isHovering,
      }}
    >
      {children}
    </StyledButton>
  );
}

Or, if you have a component that takes class lists for different parts of the component, you can enable sorting of those attributes like this:

// prettier.config.js
module.exports = {
  tailwindAttributes: ["iconClasses", "textClasses"],
};
// Example.jsx
function LikeButton({ isHovering, children }) {
  return (
    <Kit.Button
      icon="heart"
      className="rounded border border-gray-400 bg-white text-gray-800 shadow hover:bg-gray-100"
      iconClasses="w-5 h-5 mr-2 fill-current text-gray-500"
      textClasses="text-lg font-semibold"
    >
      {children}
    </Kit.Button>
  );
}

Sorting classes in tagged template literals

This plugin also enables sorting of classes using tagged template literals. To enable this you specify a list of tag names in the tailwindFunctions option in your Prettier configuration file.

// prettier.config.js
module.exports = {
  tailwindFunctions: ["tw"],
};

Tagged template literals are especially useful in React Native where libraries often expose tags as a way to build stylesheets and style components using classes like we do in the browser. Now, with the above config, we can now sort classes in tagged template literals tagged with tw, like this:

import tw from "twrnc";

function Button({ isHovering, children }) {
  let styles = tw`rounded py-2 px-4 text-base bg-blue-500 text-white hover:bg-blue-700`

  return <View style={styles}>{children}</View>;
}

Sorting classes in function calls

The third place where this plugin enables sorting of classes is in function calls. This is useful when you have a function that takes a list of classes as an argument. For example, the very popular clsx package provides a powerful abstraction to generating a class string built from arrays, objects, and strings. To enable this you add these functions to the tailwindFunctions option in your Prettier configuration file.

// prettier.config.js
module.exports = {
  tailwindFunctions: ["clsx"],
};

This, in turn, enables sorting of classes in function calls like this, even when not embedded directly inside the className attribute:

import clsx from "clsx";

function Button({ isHovering, children }) {
  let classes = clsx(
    "rounded py-2 px-4 text-base bg-blue-500 text-white",
    isHovering && "bg-blue-700 text-gray-100"
  );

  return <button className={classes}>{children}</button>;
}

Closes #133
Closes #127
Closes #126
Closes #121

@nderscore
Copy link
Contributor

Thanks for all your work building on top of my initial idea! ❤️ I like the direction you guys took it - especially how the custom attributes are more generic now and not limited to only React/JSX props 👍

@reinink reinink changed the title Enable sorting of custom attributes, functions, and tagged template literals Allow sorting of custom attributes, functions, and tagged template literals May 9, 2023
@thecrypticace thecrypticace merged commit 6ba6faa into main May 9, 2023
@thecrypticace thecrypticace deleted the feat/customizations branch May 9, 2023 19:33
bronisMateusz pushed a commit to bronisMateusz/prettier-plugin-tailwindcss-drupal that referenced this pull request Apr 16, 2025
…terals (tailwindlabs#155)

* Add opt-in customization features

* Update fixtures

* wip

* wip

* wip

* wip

* wip

* Move parsers/printers/options to bottom of the file

* Make fixture formatting async

* Run fixture tests in parallel

* wip

* remove concurrency

It works when only running the fixtures but not the other tests. Not sure why.

* wip

* Tweak prettier config

* Simplify fixture

* Fix CS

* Update readme

* Merge defaults instead of replacing them

* move fixture

* Add Vue fixture

* Update changelog

* Update options docs in readme

* Tweak readme

* Show sorted classes in readme

* Tweak changelog

---------

Co-authored-by: _nderscore <[email protected]>
Co-authored-by: Jonathan Reinink <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The plugin does not order classes that are specified in a variable outside the className prop

3 participants