tal3nce's avatar

Tailwind not compiling dynamic classes from Blade components

So, here's the thing. I have some dynamic Blade components that should accept color as a prop or fallback to default. The problem is that Blade recognizes this and compiles HTML correctly, however, Tailwind is not picking this up and is not compiling these classes so I don't see the end result.

Important: this is not a "global" Tailwind issue or my browser cache et cetera, I checked those multiple times. Other than this, Tailwind works correctly, I use NPM watch during developments, it's all good. So the problem is when some of these classes are only coming from my dynamic components, so if I e.g. want a pink button, I will not see border-pink-600 compiled in my public/css/app.css, but if I provide red as color, I will see it because I use e.g. border-red-600, text-red-600 etc. in other places, so it gets compiled based on those.

Component:

@props(['route', 'color' => 'teal'])

<a href="{{ $route }}"
    {{ $attributes
         ->merge(['class' => 'px-2 py-1 border rounded-md
                             border-'.$color.'-600 text-'.$color.'-600
                             hover:bg-'.$color.'-600 hover:text-gray-100'
                     ]) }}
>{{ $slot }}</a>

Adding the component in my markup:

<x-button-link route="{{ route('posts.edit', ['post' => $post]) }}"
                           color="amber" class="ml-2 text-sm">Edit</x-button-link>

So my final output looks like this:

<a href="http://localhost:8080/posts/81865188-dolores-libero-ut-ipsa-repudiandae/edit" class="px-2 py-1 border rounded-md
                             border-amber-600 text-amber-600
                             hover:bg-amber-600 hover:text-gray-100 ml-2 text-sm">Edit</a>

However, I don't see my button as "amber" colored, it's grayish. Basically, classes such as border-amber-600, text-amber-600 etc. are not ending up in /public/css/app.css.

There is a very annoying workaround to this and that is to manually add these classes anywhere in my Blade, let it compile to app.css so I can see the results, however, if I only use these classes in my Blade components, the next time it compiles, it will re-compile public/css/app.css without it.

Is this a known issue and expected behavior (e.g. Tailwind does compiling before blade does, so it still sees e.g. border-$color-200) or is this a bug fix material? Alternatively, am I doing something wrong? Thanks in advance!

0 likes
8 replies
tal3nce's avatar

@Snapey thanks a lot! I can't believe I couldn't find this in the docs. Thanks for the quick and complete anawer, all the best!

da3monhunt3r's avatar

@Snapey Thats a lot of safe listing if we are making components like we do in vue/react. Creating a blade file and adding the classes there sounds the same too :S

robsontenorio's avatar

Do you mind to elaborate how safelist solves this issue ? Because you don’t known with class it will be used. It can be many.

Snapey's avatar

@robsontenorio tailwind only includes classes it can detect from scanning the source file. It does not do static analysis of what your code might do. So its never going to detect class names that are computationally created.

Safelisting says, I don't care what is found in the code, I will assume you ALWAYS want classes defining that are in the safelist. If its many permutations then I'm afraid you have to list every permutation.

aalaap's avatar

Instead of having a separate safe list file, I've been co-locating the possible class names under unused stacks via @push directives within my components, like this:

/resources/views/components/button.blade.php:

@push('tailwindcss-safelist')
<div class="btn btn-neutral btn-primary btn-warning"></div>
@endpush

<button {{ $attributes->merge([
    'class' => 'btn' . (empty($variant) ? '' : ' btn-' . $variant)
    ]) }}>
    {{ $slot }}
</button>

This way, every time I use a new class on the button component, I can add it right here, instead of having to remember adding it to another file altogether.

Since there's no tailwindcss-safelist @stack defined in my layouts, Blade skips the rendering of that div, but Tailwind CSS processes it.

Please or to participate in this conversation.