I’m working with LiveView.JS for the first time. It’s one of the features that’s brought me back to LiveView on the frontend, and I feel like it was a critical piece that was missing for the community in earlier versions of the websocket-based paradigm.
By default, Phoenix comes installed with TailwindCSS. In Tailwind, transitions often occur via CSS classes. Take the following example:
<!-- When a menu is 'opened', it should receive the "block" class. When 'closed', it should receive the "hidden" class -->
<div id="mobile-menu" class="block sm:hidden">...</div>
<div id="desktop-menu" class="hidden sm:block">...</div>
This is a very common occurrence in Tailwind - transitions are almost exclusively driven via class addition and subtraction. When I went to try and apply this pattern with LiveView.JS, I was surprised to not see an obvious way to approach this.
The challenge with JS.toggle() is that the display property is directly applied via the style=display:
attribute, where tailwind classes are invalid. This causes problems in the reactive example above, because the mobile menu could be toggled to be in the open state (style= display:block
), and if the window is resized, this style will override the existing reactive behavior defined in tailwind (sm:hidden
), causing both menus to be shown at once!
Of course, you could avoid this by using the JS.addClass
and JS.removeClass
functions, but that requires you to know the current state of the element to determine which function to call… meaning we’d need to keep state on the server, exactly what we are trying to avoid for something like a menu’s visibility!
I looked over the other functions available in LiveView.JS, but none seem to handle what I imagine must be an incredibly common use-case.
So, please help me out LiveView devs - am I missing something obvious? All I want is the ability to toggle two sets of arbitrary tailwind classes and let the state be contained entirely on the client via JavaScript. If I can do that, Tailwind will take care of everything else.
Thanks for your suggestions!