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

Build in specificity-based sorting mechanism #2

Open
brandonmcconnell opened this issue Apr 6, 2024 · 1 comment
Open

Build in specificity-based sorting mechanism #2

brandonmcconnell opened this issue Apr 6, 2024 · 1 comment

Comments

@brandonmcconnell
Copy link
Owner

brandonmcconnell commented Apr 6, 2024

Currently, the priority of conflicting signal-triggered styles relies solely on the order in which they are processed and appear in the output stylesheet. This lack of proper prioritization results in variable results when working with conflicting styles and makes using them for the same style unreliable.

It's an edge case, and even Tailwind CSS core doesn't support built-in prioritization beyond the ! symbol for importance, but they don't need to for this case because Tailwind CSS leverages the built-in specificity algorithm for style prioritization.

Tailwind CSS does, however, deal with something similar with their media query sorting internally. A similar convention could work here. I see a couple of options here:

  1. A more straightforward solution could be to order the signals based on the number of variants used to trigger them. In the example below, the container query for each signal would be ordered based on the specificity of the condition used when declaring it.

    <input type="checkbox" class="peer" /> 👈🏼 check/uncheck here
    <div class="signal/vader hover:signal/obiwan peer-checked:signal/yoda peer-checked:hover:signal/macewindu">
      <div class="signal/macewindu:!bg-purple signal/obiwan:bg-blue signal/vader:bg-red signal/yoda:bg-green">or hover here</div>
    </div>

    One issue with this approach that is core to the principle of Signals for Tailwind CSS is that signals must be trigger-able in multiple ways and places, so it might be unclear which usage is the most specific in certain instances. Even with that approach, certain signals might require different specificities in different places.

    This option would be the closest to how a natural CSS solution would work, similar to how group works, and this should maintain a 1:1 complementary relationship to that as much as possible.

    One last missing step that may ultimately solve this issue is to create a new media query not only per name but also per declaration, allowing each declaration to be uniquely sorted based on its specificity.

  2. Another option could be to use the modifier syntax as a manual prioritization system instead, so someone could use any of these:

    • signal:vader (specificity defaults to 0)
    • hover:signal/1:obiwan
    • peer-checked:signal/2:yoda
    • peer-checked:hover:signal/3:macewindu

    With this solution, I would expose signals as BOTH a variant and a utility, but both would have the same functionality of setting up the signal. Then, to consume a signal, you would use a different accompanying utility, perhaps effect as suggested by @AlexVipond in change variant name to effect, update documentation for clarity and readability #1. This would solve the issue, but I don't love this solution to the problem and how it places the full burden of manual specification into the hands of the users. (I might still rename the variant to effect though to better align with the prior art behind signals in JS)

  3. I could ideate on some way to leverage CSS custom property inheritance here, but that idea is half-developed, and I don't think it would apply here since I'm working primarily with container queries and not variable values.

  4. Lastly, I do nothing and suggest that users implement an approach for handling conflicting utility classes, such as tailwind-merge (or similar)

Action items

For now, with this all at front of mind, I think the ideal solution would be Option 1, specifically the idea to set up a new container query per usage/unique selector sorted based on that selector's specificity.

  • Investigate this to ensure the idea is sound
  • Implement and test it
    • consider alternatives for determining specificity based on the number of variants. Some may be more or less naturally specific than others. Case in point, :where zeroes out the specificity of a given selector, and that should be reflected here as well. Maybe I can get the final selector back from Tailwind's engine and use a 3rd party lib to determine specificity.
  • Deploy the fix as a patch
@AlexVipond
Copy link

I noticed this, and yeah it's a tricky problem.

Variant chaining is the built-in adequate solution IMO. signal:bg-blue-100 signal:signal/one:bg-blue-200 signal:signal/one:signal/two:bg-blue-300 would override background color as expected. This is how people currently use group-hover:group-focus, and it's intuitive once you understand that CSS class usage order doesn't correlate with cascade order.

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

No branches or pull requests

2 participants