Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow sorting of custom attributes, functions, and tagged template literals #155

Merged
merged 25 commits into from May 9, 2023

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
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