Skip to content

Support for importing functions from tailwind plugins #5121

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

Merged
merged 14 commits into from
Apr 18, 2025

Conversation

itsmeadarsh2008
Copy link
Contributor

@itsmeadarsh2008 itsmeadarsh2008 commented Apr 12, 2025

All Submissions:

  • Have you followed the guidelines stated in CONTRIBUTING.md file?
  • Have you checked to ensure there aren't any other open Pull Requests for the desired changed?

Type of change

Please delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

New Feature Submission:

  • Does your submission pass the tests?
  • Have you linted your code locally prior to submission?

Changes To Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully run tests with your changes locally?

🧩 Example Python Data Input

Here’s how you’d pass the data for plugins like heroui() and themeVariants(...):

plugins = [
    "@tailwindcss/forms",  # simple require
    {
        "name": "@heroui/theme",
        "import": {"name": "heroui", "from": "@heroui/theme"},
        "call": "heroui"
    },
    {
        "name": "tailwindcss-theme-variants",
        "import": {"name": "themeVariants", "from": "tailwindcss-theme-variants"},
        "call": "themeVariants",
        "args": {
            "themes": {
                "light": { "selector": ".light-theme" },
                "dark": { "selector": ".dark-theme" }
            }
        }
    }
]

🧠 Why This Is Better

  • Ensures proper require() or const { fn } = require('...') imports.
  • Maintains clarity and control over plugin execution.
  • Compatible with plugins that expose multiple exports or need function calls.
  • Generates valid, modern Tailwind config files.

@itsmeadarsh2008
Copy link
Contributor Author

itsmeadarsh2008 commented Apr 13, 2025

@adhami3310 Do we need any tests? I have fixed the tailwind plugins installation too.

You can see styles working with HeroUI
image

Copy link

codspeed-hq bot commented Apr 13, 2025

CodSpeed Performance Report

Merging #5121 will not alter performance

Comparing itsmeadarsh2008:patch-1 (dd3c7e1) with main (642233b)

Summary

✅ 12 untouched benchmarks

@itsmeadarsh2008
Copy link
Contributor Author

@adhami3310 It should work now.

@adhami3310
Copy link
Member

looks good! we should have a test for it and otherwise we can merge it in

@itsmeadarsh2008
Copy link
Contributor Author

@adhami3310 I have added 2 test cases and rewrote format_full_name function to handle dict types.

@adhami3310
Copy link
Member

rewrote format_full_name function to handle dict types.

why? i'm not sure i can get the advantage here

@itsmeadarsh2008
Copy link
Contributor Author

itsmeadarsh2008 commented Apr 16, 2025

rewrote format_full_name function to handle dict types.

why? i'm not sure i can get the advantage here

@adhami3310 The test cases were failing because the function format_full_name was taking str type for formatting, and I modified the function to handle with dict types, i.e. when something like {"name": "foo"} is passed, it would refer to the name key of the dictionary. This is for formatting package names from strings as well as dictionaries. Also, I rewrote the structure of the function to improve performance while formatting.

@itsmeadarsh2008
Copy link
Contributor Author

itsmeadarsh2008 commented Apr 16, 2025

@adhami3310, why are integration tests failing? I have run it locally, it is running perfectly fine. Most of them are passed, except for the reflex web and Redis (I used to run the same pytest command in CONTRIBUTING.md), which I see here. I don't know what to do next.

@adhami3310
Copy link
Member

reflex web does something like

{
  plugins: ["@tailwindcss/typography", "tailwindcss-radix"],
  darkMode: "class",
  theme: {
    extend: {
      colors: {
        gray: {
          1: "var(--gray-1)",
          2: "var(--gray-2)",
          3: "var(--gray-3)",
          4: "var(--gray-4)",
          5: "var(--gray-5)",
          6: "var(--gray-6)",
          7: "var(--gray-7)",
          8: "var(--gray-8)",
          9: "var(--gray-9)",
          10: "var(--gray-10)",
          11: "var(--gray-11)",
          12: "var(--gray-12)",
        }
      },
    },
  },
}

@itsmeadarsh2008
Copy link
Contributor Author

itsmeadarsh2008 commented Apr 17, 2025

@adhami3310 I have added a quickfix to jinja template. I think it should work (hopefully). If succeed we can merge it.

I have written the jinja template, it works perfectly (when I used reflex-web's tailwind config) but remains generates an unformatted tailwind config in .web/ I think that's shouldn't create a noise about readability issues (not minified)

@itsmeadarsh2008
Copy link
Contributor Author

@adhami3310 I think issue is resolved now; pre-commit was the only failing check which I have fixed now. You can merge right in.

if library_fullname.startswith("@") and "/" not in library_fullname:
# Check for a second @ symbol
second_at_index = library_fullname.find("@", 1)
if second_at_index != -1:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems this code effectively does the same thing, why is it being changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TLDR: The updated diff parses packages faster than previous one.

The updated implementation in the diff is faster and more robust because it adds various optimizations and fast paths to handle specific cases. Here's why:

  1. Fast Path for URLs:

    • The line if library_fullname.startswith("https://"): return library_fullname is executed early if the input is a URL, avoiding unnecessary processing.
  2. Fast Path for Non-String Inputs:

    • The updated version includes a check for non-string inputs using not isinstance(library_fullname, str). If the input isn't a string, it quickly converts it to a string and returns it, saving unnecessary computations.
  3. Fast Path for Packages Without '@':

    • The line if "@" not in library_fullname: return library_fullname ensures that for package names without a version (e.g., "foo"), the function skips further processing and directly returns the input.
  4. Special Case Handling:

    • The new implementation handles edge cases like @library@version (no slash but starts with @) and scoped packages (@scope/package@version) more efficiently with targeted checks and substring operations.
  5. Early Returns:

    • The updated implementation introduces multiple early return paths, reducing the need for deeper logic or unnecessary processing.

In contrast, the old implementation processes all inputs uniformly, even if they don't contain a version specifier or don't require parsing. The new implementation is faster because it avoids unnecessary string operations and adds targeted checks for common scenarios.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not how Python works. A singular operation is more likely to be faster than a multitude of operations that do the same thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's not how Python works. A singular operation is more likely to be faster than a multitude of operations that do the same thing.

Yup. I was thinking the same thing while replying. I felt strange when Claude 3.7 Sonnet (Github Copilot) replied with this, when I cross checked.

@itsmeadarsh2008
Copy link
Contributor Author

@adhami3310 I went back to original with dict support.

@itsmeadarsh2008
Copy link
Contributor Author

@adhami3310 The checks are failing because of webpack errors.

@benedikt-bartscher
Copy link
Contributor

@adhami3310 The checks are failing because of webpack errors.

#5148
radix-ui/primitives#3485

@adhami3310 adhami3310 merged commit d75ea9a into reflex-dev:main Apr 18, 2025
42 checks passed
@itsmeadarsh2008
Copy link
Contributor Author

itsmeadarsh2008 commented Apr 19, 2025

thanks! Are you going to ship before tailwind v4 or along with tailwind v4?

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.

3 participants