unocss / unocss

The instant on-demand atomic CSS engine.

Home Page:https://unocss.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature request: partially transformed variant groups

UltraCakeBakery opened this issue · comments

With the current implementation of variant groups, the following html...

<div hover:(text-red-500 text-xl)></div>

...would be transformed to

<div hover:text-red-500 hover:text-xl></div>

This is very neat for smaller html markups and easy to read. However...

Problem

When you start adding more variant groups to the example above, your final HTML markup can grow huge. This in combination with a generous for loop can lead to giant html documents, which can take quite long to parse. Also, when reading the transformed HTML it may become harder to recognize what code you are looking at since all variants groups have been transformed and no () are to be found anywhere.

Proposed solution

An extra option could be added to the transformer called partialTransformation or something like that. When enabled the transformer only replaces all the spaces inside variant groups with a separator, which could be _ by default, and add additional matchers for the group-variant to the individual utility styles.

Example:

Input:

<div hover:(text-red-500 text-xl)></div>

Output

<div hover:(text-red-500_text-xl)></div>

<style>
[text-red-500=""]:hover,
[hover\:\(text-red-500_text-xl\)=""]:hover  {
     color: red;
}

[text-xl=""]:hover,
[hover\:\(text-red-500_text-xl\)=""]:hover  {
     font-size: 4rem;
} 
</style>
Alternative solution

#948 could act as a partial alternative solution, but it doesn't allow for showing the original source code

Additional information

I tried to see if we could just simply generate a compiled styles like...

[hover\:\(text-red-500\ text-xl\)=""] {
      color: red;
      font-size: 4rem;
}

...so this issue could extend #948 instead, but that will not be possible because browsers consider hover:(text-red-500 and hover:text-xl) to be two individual attributes.

Fun idea: replace separator spaces with an alternative space that looks the same, like (U+2005) twice (found on https://jkorpela.fi/chars/spaces.html). This looks the same, but browsers don't consider it a space so they do not separate the attributes internally. This allows the selector to work without looking different https://jsfiddle.net/L18rzv2p/

I edited my issue to better reflect what I am proposing. Also fixed some typo's and added some details about configuration options. If this requires some more work or takes more time then the main contributors have available or are willing to spend on this, please flag this with "help wanted" or something like that so I can take a shot at it in the near future.

Just to clarify, with the current implementation of variant group transformer, your code snippet above should not be transformed at all since only quoted content (including js) is extracted and transformed. If I understand correctly what you're proposing here, you'll need a transformer to transformed the variant group, an extractor to extracted the transformed content, and a variant to 'expand' the extracted content to corresponding rules. However I would advise against writing variant groups outside of class names, since you already have attributify mode at your disposal and your typescript typecheck is probably going to fight you with illegal attribute names. Nevertheless I do think this is a fun a idea, I might attempt to implement it if I have time.

Just to clarify, with the current implementation of variant group transformer, your code snippet above should not be transformed at all since only quoted content (including js) is extracted and transformed. If I understand correctly what you're proposing here, you'll need a transformer to transformed the variant group, an extractor to extracted the transformed content, and a variant to 'expand' the extracted content to corresponding rules. However I would advise against writing variant groups outside of class names, since you already have attributify mode at your disposal and your typescript typecheck is probably going to fight you with illegal attribute names. Nevertheless I do think this is a fun a idea, I might attempt to implement it if I have time.

I made the mistake in my issue to use attributify. I was actually talking about classes. I do think attributify should support this for boolean attributes too though.

I closing this issue since this is such a niche feature it would not be worth it to add it to unocss. If anyone needs this, @ me. If I have time I'll put together a custom transformer.