<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="302482" data-post-id="302482">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="D4no0" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/D4no0/120/33624_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  D4no0
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>On a more general note, I think that is not very smart to scan for classes in <strong>source code</strong>, especially since elixir has metaprogramming. In theory it would be possible to scan for dynamic classes throughout the phoenix compiled templates and detect specifically a couple of things:</p>
<ol>
<li>Compute dynamic strings that can be resolved at compile-time (macros);</li>
<li>Deliver warnings to user (this can be done by a separate system, however it would be nice if integrated);</li>
<li>Have less content to scan (handling only compiled templates to tailwind, it doesn’t need to scan entire codebase blindly).</li>
</ol>
<p><a class="mention" href="/u/zachdaniel" rel="nofollow">@zachdaniel</a> it would be great to know what your opinion is and what the Tails library was aimed to solve, and if it can be used to create some of these features.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="302482" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/can-we-solve-the-tailwind-interpolation-problem-with-a-macro/53804/12">Post #11</a>
	                </div>
	            </div>
              <div id="likers-container-302482" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302482"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #11"></div>
  </section>
</div>
    <div class="postbit" id="302484" data-post-id="302484">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="zachdaniel" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachdaniel/120/31980_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  zachdaniel
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Ash</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Yep! We shouldn’t scan source code, we should provide a macro or sigil that does the validation. The tails library solves for class merging and conditional classes. Class merging is necessary for allowing components to have their classes overridden by parents passing down classes(my preferred way of overriding components) and tails will do a semantic merge based on what classes “conflict” in tailwind.</p>
<p>I’m already working on a macro version of classes as well as a sigil. The macro version will, for now, warn on interpolation unless possible values for the interpolated expression is provided.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="302484" data-batch-url="/posts/batch_likers">
                        3
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/can-we-solve-the-tailwind-interpolation-problem-with-a-macro/53804/13">Post #12</a>
	                </div>
	            </div>
              <div id="likers-container-302484" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302484"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #12"></div>
  </section>
</div>
    <div class="postbit" id="302486" data-post-id="302486">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="D4no0" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/D4no0/120/33624_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  D4no0
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I was thinking on a opt-out way to do this, because my thinking is that new people coming to the ecosystem will have the most trouble not doing this mistake, moreover sane default options always beat optionals.</p>
<p>This, of course implies a conceptually different approach, however I think that would be possible if you would add it as an compiler in mix after elixir. I’m not sure about limitations or performance penalty on this, you should know this much better than me.</p>
<p>Do you think the sigil opt-in approach is more friendly?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="302486" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/can-we-solve-the-tailwind-interpolation-problem-with-a-macro/53804/14">Post #13</a>
	                </div>
	            </div>
              <div id="likers-container-302486" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302486"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #13"></div>
  </section>
</div>
    <div class="postbit" id="302487" data-post-id="302487">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="zachdaniel" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachdaniel/120/31980_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  zachdaniel
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Ash</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Well, I’d love for it to be doable in phoenix directly, I even made a PR that would allow configuring a handler for all class properties, but it was rejected(no hard feelings). I use tails everywhere anyway <img src="https://forum.elixirforum.com/images/emoji/apple/joy.png?v=15" title=":joy:" class="emoji" alt=":joy:" loading="lazy" width="20" height="20"> . I do see that it kind of defeats the real goal of helping people avoid the footgun. A custom compiler could work. It would be…pretty difficult though. Likely filled with false negatives or false positives depending on the implementation.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="302487" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/can-we-solve-the-tailwind-interpolation-problem-with-a-macro/53804/15">Post #14</a>
	                </div>
	            </div>
              <div id="likers-container-302487" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302487"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #14"></div>
  </section>
</div>
    <div class="postbit" id="302489" data-post-id="302489">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="D4no0" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/D4no0/120/33624_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  D4no0
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<aside class="quote group-Ash-Core-Team" data-username="zachdaniel" data-post="15" data-topic="53804">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachdaniel/48/31980_2.png" class="avatar"> zachdaniel:</div>
<blockquote>
<p>Well, I’d love for it to be doable in phoenix directly, I even made a PR that would allow configuring a handler for all class properties, but it was rejected(no hard feelings).</p>
</blockquote>
</aside>
<p>Maybe that would be possible in the future, I have a feeling that heex will evolve to the point that it will fully parse and understand the html, at least that seems the direction it is taking.</p>
<aside class="quote group-Ash-Core-Team" data-username="zachdaniel" data-post="15" data-topic="53804">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachdaniel/48/31980_2.png" class="avatar"> zachdaniel:</div>
<blockquote>
<p>It would be…pretty difficult though. Likely filled with false negatives or false positives depending on the implementation.</p>
</blockquote>
</aside>
<p>This is what I was afraid to hear, going into internal implementation details of phoenix (especially as a separated library) would be the same as shooting yourself in the foot, more potential problems than gain.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="302489" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/can-we-solve-the-tailwind-interpolation-problem-with-a-macro/53804/16">Post #15</a>
	                </div>
	            </div>
              <div id="likers-container-302489" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302489"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #15"></div>
  </section>
</div>
    <div class="postbit" id="302491" data-post-id="302491">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="zachdaniel" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/zachdaniel/120/31980_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  zachdaniel
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Ash</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Okay, decided I don’t actually have time to do the thing I wanted <img src="https://forum.elixirforum.com/images/emoji/apple/laughing.png?v=15" title=":laughing:" class="emoji" alt=":laughing:" loading="lazy" width="20" height="20"> but PRs welcome if someone wants it. I did manage to add a sigil that should clean things up.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="302491" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/can-we-solve-the-tailwind-interpolation-problem-with-a-macro/53804/17">Post #16</a>
	                </div>
	            </div>
              <div id="likers-container-302491" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="302491"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #16"></div>
  </section>
</div>
    <div class="postbit" id="318104" data-post-id="318104">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="m-collins" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/m-collins/120/33690_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  m-collins
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>We’ve had some really nice wins in this space by moving to using tailwind in conjunction css variables and data attributes.</p>
<p>This video is a good summary</p>
<div class="youtube-onebox lazy-video-container" data-video-id="WTchW0LdWL0" data-video-title="You’re doing dark mode wrong!" data-video-start-time="282s" data-provider-name="youtube">
  <a href="https://www.youtube.com/watch?v=WTchW0LdWL0&amp;t=282s" target="_blank" class="video-thumbnail" rel="noopener nofollow ugc">
    <img class="youtube-thumbnail" src="https://img.youtube.com/vi/WTchW0LdWL0/maxresdefault.jpg" title="You’re doing dark mode wrong!" width="690" height="388">
  </a>
</div>

<p>We use it for a heap of different use cases. themes (dark, light, high-contrast etc) , status (warning, success, danger, info), surfaces (standard, faint, inverse), categorical charts colours etc. CSS variables are amazing and really under rated.</p>
<p>Once in place you end up with much cleaners views.</p>
<p>No more <code>dark:text-white</code></p>
<p>No more explicit class definitions</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">defp badge_type (type) do
    case type do
      :success -&gt; "badge-success"
      :warning -&gt; "badge-warning"
      :error -&gt; "badge-error"
      :inactive -&gt; "badge-ghost"
      :not_found -&gt; "badge-info"
    end
  end
</code></pre>
<p>If you adapt the fundamentals in that video, you’ll end up  with something that looks like this:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">&lt;body data-theme={@theme} class="text-standard bg-standard"&gt;
    &lt;div data-status={@status} class="bg-status text-status"&gt;
      &lt;% @status.message %&gt;
    &lt;/div&gt;  
&lt;/body&gt;
</code></pre>
<p>It also responds to any changes on the client. E.g. switching a data-theme from light to dark. You can even take this much further by allowing users to configure their own theme within the app and then assigning those values to your css variables. We haven’t tried this, but it’s certainly possible.</p>
<p>There’s a bit of upfront work to put your design system in place, but the flow on benefits have been huge for us.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="318104" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/can-we-solve-the-tailwind-interpolation-problem-with-a-macro/53804/18">Post #17</a>
	                </div>
	            </div>
              <div id="likers-container-318104" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="318104"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-last-post cat-last-post" title="Last post!"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <span class="all-loaded">— All posts loaded —</span>
</div></template></turbo-stream>