Artur Roszczyk

October 30, 2023

Conditional styles for Turbo Native in TailwindCSS

Joe Masilotti, in his Rails World 2023 talk, shows how to create custom styles for Turbo Native Rails applications in a way that does not break cache:

# app/assets/stylesheets/native.css
.turbo-native-hidden {
  display: hidden important!
}

# app/views/layouts/application.html.erb
<head>
  <%= stylesheet_include_tag "application" %>
  <%= stylesheet_include_tag "native" if turbo_native_app? %>
</head>

This works great for simple scenarios when I must show or hide certain elements. With Tailwind, however, I would like to benefit from the full richness of all its utility classes. 

How

In config/tailwind.config.js, add the following function to the plugins section: 
 plugins: [
    # ...
    ({ addVariant }) => {
      addVariant('turbo-native', "html[data-turbo-native-app] &"),
      addVariant('non-turbo-native', "html:not([data-turbo-native-app]) &")
    },
  ]

Next, add a conditional data attribute to your layout html tag:
<!DOCTYPE html>
<html <%= 'data-turbo-native-app' if turbo_native_app? %> >
<head>

In case the helper is not available in your views, add the following line to your application controller:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  helper_method :turbo_native_app?
end

And that's it! Now, you can use these variants to display your app on iOS/Android native app differently, from simple cases like:
<div class="flex turbo-native:flex-col">
</div>

To more complex scenarios:
<div class="flex non-turbo-native:group-data-[hide]:hidden turbo-native:flex">
  <%= render 'overdue_tasks_count', overdue_tasks_count: @overdue_tasks_count %>
</div>

Enjoy! I hope this helps (me remember).

About Artur Roszczyk

Engineering manager by trade, Ruby on Rails enthusiast at heart.
Find me on Twitter – @sevos