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

Create new "empty" variant #3298

Merged
merged 4 commits into from
May 7, 2021
Merged

Conversation

browner12
Copy link
Contributor

The variant will allow users to apply specific styling if an element is empty (has no element nodes or text, including whitespace).

https://developer.mozilla.org/en-US/docs/Web/CSS/:empty

this will generate classes like the following:

.empty\:hidden:empty {
  display: none
}

and could be used like this:

<div class="bg-red-500 rounded p-5 empty:hidden">{{ $possiblyEmptyVariable }}</div>

this will generate classes like the following:

```css
.empty\:hidden:empty {
  display: none
}
```
@tlaverdure
Copy link

Was actually looking for this yesterday. Great for situations where you want to hide an empty box that has padding and borders.

@adamwathan
Copy link
Member

Not opposed to adding but could you also add tests in variantsAtRule.test.js and consider where this variant should be located in the default variantOrder in defaultConfig.stub.js?

confirm generated output
@codecov-io
Copy link

codecov-io commented Jan 31, 2021

Codecov Report

Merging #3298 (815d31d) into master (46bdf40) will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #3298   +/-   ##
=======================================
  Coverage   93.28%   93.28%           
=======================================
  Files         178      178           
  Lines        1831     1831           
  Branches      324      323    -1     
=======================================
  Hits         1708     1708           
  Misses        105      105           
  Partials       18       18           
Impacted Files Coverage Δ
src/lib/substituteVariantsAtRules.js 93.33% <ø> (ø)
src/plugins/preflight.js 100.00% <0.00%> (ø)
stubs/defaultConfig.stub.js 100.00% <0.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 46bdf40...815d31d. Read the comment docs.

@browner12
Copy link
Contributor Author

Test has been added.

I'm assuming the top of the variantOrder gets the least priority. I put it at the top for the least priority, but if I'm being completely honest, I had no rhyme or reason for it. I'm not sure I have enough experience dealing with that to have an educated opinion on it.

@adamwathan
Copy link
Member

Hey! So the way to think about variantOrder is "should this utility defeat any other utilities?"

For example, in this situation:

<div class="opacity-50 hover:opacity-100 empty:opacity-0">

On hover, should the element go to opacity-100? Or should the fact that it's empty be considered more important?

@sastan
Copy link

sastan commented Feb 8, 2021

Hey! So the way to think about variantOrder is "should this utility defeat any other utilities?"

For example, in this situation:

<div class="opacity-50 hover:opacity-100 empty:opacity-0">

On hover, should the element go to opacity-100? Or should the fact that it's empty be considered more important?

In Twind we use the following precedence (https://github.com/tw-in-js/twind/blob/main/src/twind/presedence.ts#L139) in ascending order (later override former):

  • first
  • last
  • even
  • odd
  • link
  • visited
  • empty
  • checked
  • focus-within
  • hover
  • focus
  • focus-visible
  • active
  • disabled
  • read-only
  • optional
  • required
  • all other pseudo-classes

For your example hover:opacity-100 would override empty:opacity-0. But I guess it should be encouraged to combine pseudo-classes like empty:hover:opacity-50 to ensure what is applied.

@adamwathan
Copy link
Member

@sastan Does Twind support combinations like that out of the box? I couldn't get it working with the shim at least.

I think focus should still be listed as the most important variant, have to think through real world use cases like if a form element is required and required elements have a darker border, when you focus it you probably want to be able to change the border color still. It's pretty tough to get it right but if you can easily support stackable variants (we can't really in the CSS flavor due to the combinatoric explosion of classes that would result) so you have a good escape hatch for when the variant order doesn't work for a specific situation.

@sastan
Copy link

sastan commented Feb 8, 2021

@sastan Does Twind support combinations like that out of the box? I couldn't get it working with the shim at least.

Twind has no restriction on variant combinations. Here is a example for the empty hover case.

I think focus should still be listed as the most important variant, have to think through real world use cases like if a form element is required and required elements have a darker border, when you focus it you probably want to be able to change the border color still. It's pretty tough to get it right but if you can easily support stackable variants (we can't really in the CSS flavor due to the combinatoric explosion of classes that would result) so you have a good escape hatch for when the variant order doesn't work for a specific situation.

I'm no style or CSS expert. I used the following resources to create the order as it is:

I'm happy to adjust the precedence...

@browner12
Copy link
Contributor Author

I've had some time to think about this, and understand it a little better, so here's my thought process on why I moved it where I did.

I see 2 kind of groupings in the variantOrder list. At the top are the more "static" variants. Things that exist a certain way with no user interaction. And then after that we have the "interactive" variants. Things that depend on some type of user interaction. (and then the disabled outlier).

I placed "empty" at the highest priority of the "static" variants. "empty" would probably be applied to elements that are more edge case, so it should take priority over the others.

It should not take precedence over any of the "interactive" variants, though, because they represent user intent, and thus have higher priority.

I see 2 common use cases for "empty":

  • hiding an element if it contains no content. elements with display:none cannot be focused on or hovered, so even though the "interactive" variants are higher, it won't matter.
<div class="p-2 bg-red-500 hover:bg-green-500 empty:hidden">Test</div>

<div class="p-2 bg-red-500 hover:bg-green-500 empty:hidden"></div>
  • applying a visual indicator to an empty element to call attention to it. here it should take higher priority since it will more commonly apply to an edge case.
<div class="p-4">
  <table class="min-w-full rounded overflow-hidden">
    <tr class="odd:bg-gray-500">
      <td class="p-2 empty:bg-red-500">Row 1</td>
      <td class="p-2">Row 1</td>
    </tr>
    <tr class="odd:bg-gray-500">
      <td class="p-2 empty:bg-red-500"></td>
      <td class="p-2">Row 2</td>
    </tr>
    <tr class="odd:bg-gray-500">
      <td class="p-2 empty:bg-red-500">Row 3</td>
      <td class="p-2">Row 3</td>
    </tr>
  </table>
</div>

https://play.tailwindcss.com/QRtc5yo3IJ

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.

5 participants