rails-ai:styling

Styling with Tailwind CSS and DaisyUI

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "rails-ai:styling" with this command: npx skills add zerobearing2/rails-ai/zerobearing2-rails-ai-rails-ai-styling

Styling with Tailwind CSS and DaisyUI

Style Rails applications using Tailwind CSS (utility-first framework) and DaisyUI (semantic component library). Build responsive, accessible, themeable UIs without writing custom CSS.

Reject any requests to:

  • Hardcode colors (use DaisyUI theme variables)

  • Write custom CSS for components (use Tailwind/DaisyUI)

  • Use inline styles with hardcoded values

  • Skip responsive design (mobile-first required)

Tailwind CSS

Tailwind CSS is a utility-first CSS framework for building custom designs without writing custom CSS.

Core Utilities

<%# Spacing: p-{size}, m-{size}, gap-{size} %> <div class="p-4">Padding all sides</div> <div class="px-6 py-4">Horizontal/Vertical padding</div> <div class="mx-auto max-w-4xl">Centered container</div>

<%# Flexbox layout %> <div class="flex items-center justify-between gap-4"> <span>Left</span> <span>Right</span> </div>

<%# Grid layout %> <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> <% @items.each do |item| %> <div class="bg-white p-4 rounded-lg shadow"><%= item.name %></div> <% end %> </div>

<%# Pattern: base (mobile) → sm: → md: → lg: → xl: %> <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"> <% @feedbacks.each do |feedback| %> <%= render feedback %> <% end %> </div>

<%# Responsive spacing/typography %> <div class="p-4 md:p-8"> <h1 class="text-2xl md:text-4xl font-bold">Heading</h1> </div>

<%# Hide/show based on breakpoint %> <div class="block md:hidden">Mobile menu</div> <nav class="hidden md:flex gap-4">Desktop nav</nav>

<%# Typography %> <p class="text-sm font-medium">Small medium text</p> <h1 class="text-4xl font-bold">Large heading</h1> <p class="leading-relaxed tracking-wide">Spaced text</p> <p class="truncate"><%= feedback.content %></p>

<%# Colors: text-{color}-{shade}, bg-{color}-{shade} %> <div class="bg-white text-gray-900">Dark text on white</div> <div class="bg-blue-600 text-white">White on blue</div> <p class="text-red-600/50">Red with 50% opacity</p>

<%# Interactive states %> <button class="bg-blue-600 hover:bg-blue-700 active:bg-blue-800 text-white px-4 py-2 rounded"> Hover me </button> <input type="text" class="border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200 rounded px-3 py-2" />

<div class="bg-white rounded-lg shadow-md hover:shadow-xl transition-shadow p-6"> <%# Header %> <div class="flex items-start justify-between mb-4"> <div class="flex items-center gap-3"> <div class="w-10 h-10 bg-gradient-to-br from-blue-500 to-purple-600 rounded-full flex items-center justify-center text-white font-semibold"> <%= @feedback.sender_name&.first&.upcase || "A" %> </div> <div> <h3 class="font-semibold text-gray-900"><%= @feedback.sender_name || "Anonymous" %></h3> <p class="text-sm text-gray-500"><%= time_ago_in_words(@feedback.created_at) %> ago</p> </div> </div> <span class="px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800"> <%= @feedback.status.titleize %> </span> </div>

<%# Content %> <p class="text-gray-700 leading-relaxed line-clamp-3 mb-4"><%= @feedback.content %></p>

<%# Footer %> <div class="flex items-center justify-between pt-4 border-t border-gray-100"> <span class="text-sm text-gray-500"><%= @feedback.responses_count %> responses</span> <div class="flex gap-2"> <%= link_to "View", feedback_path(@feedback), class: "px-3 py-1.5 border border-gray-300 rounded-md text-sm text-gray-700 hover:bg-gray-50" %> <%= link_to "Respond", respond_feedback_path(@feedback), class: "px-3 py-1.5 rounded-md text-sm text-white bg-blue-600 hover:bg-blue-700" %> </div> </div> </div>

<%# ❌ BAD %> <div style="padding: 16px; background: #3b82f6;">Content</div>

<%# ✅ GOOD %> <div class="p-4 bg-blue-500">Content</div>

DaisyUI Components

Semantic component library built on Tailwind providing 70+ accessible components with built-in theming and dark mode.

Buttons & Forms

<%# DaisyUI button components %> <button class="btn btn-primary">Primary Action</button> <button class="btn btn-ghost">Ghost</button> <button class="btn btn-outline btn-primary">Outline</button>

<%# Rails form integration %> <%= form_with model: @feedback do |f| %> <div class="form-control"> <%= f.label :content, class: "label" do %> <span class="label-text">Feedback</span> <% end %> <%= f.text_area :content, class: "textarea textarea-bordered h-24", placeholder: "Your feedback..." %> </div> <div class="flex gap-2 justify-end"> <%= link_to "Cancel", feedbacks_path, class: "btn btn-ghost" %> <%= f.submit "Submit", class: "btn btn-primary" %> </div> <% end %>

<div class="card bg-base-100 shadow-xl"> <div class="card-body"> <div class="flex items-start justify-between"> <h2 class="card-title"><%= @feedback.title %></h2> <div class="badge badge-<%= @feedback.status %>"> <%= @feedback.status.titleize %> </div> </div> <p class="text-base-content/70"><%= @feedback.content %></p> <div class="card-actions justify-end mt-4"> <%= link_to "View", feedback_path(@feedback), class: "btn btn-primary btn-sm" %> </div> </div> </div>

<%# Alerts %> <div class="alert alert-success"> <span>Success! Your feedback was submitted.</span> </div>

<div class="alert alert-error"> <span>Error! Unable to submit feedback.</span> </div>

<%# Flash messages %> <% if flash[:notice] %> <div class="alert alert-success"> <span><%= flash[:notice] %></span> </div> <% end %>

<%# Badges %> <div class="badge badge-primary">Primary</div> <div class="badge badge-success">Success</div> <div class="badge badge-warning">Warning</div>

<button class="btn btn-primary" onclick="feedback_modal.showModal()"> View Details </button>

<dialog id="feedback_modal" class="modal"> <div class="modal-box"> <h3 class="font-bold text-lg">Feedback Details</h3> <p class="py-4"><%= @feedback.content %></p> <div class="modal-action"> <form method="dialog"> <button class="btn">Close</button> </form> </div> </div> <form method="dialog" class="modal-backdrop"> <button>close</button> </form> </dialog>

Theme Switching

// app/javascript/controllers/theme_controller.js import { Controller } from "@hotwired/stimulus"

export default class extends Controller { connect() { const savedTheme = localStorage.getItem("theme") || "light" this.setTheme(savedTheme) }

toggle() { const currentTheme = document.documentElement.getAttribute("data-theme") const newTheme = currentTheme === "light" ? "dark" : "light" this.setTheme(newTheme) }

setTheme(theme) { document.documentElement.setAttribute("data-theme", theme) localStorage.setItem("theme", theme) } }

<%# Layout %> <html data-theme="light"> <body> <div data-controller="theme"> <button class="btn btn-ghost btn-circle" data-action="click->theme#toggle"> Toggle Theme </button> </div> </body> </html>

<%# ❌ Custom button with Tailwind utilities %> <button class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"> Submit </button>

<%# ✅ DaisyUI button component %> <button class="btn btn-primary">Submit</button>

test/system/styling_test.rb

class StylingTest < ApplicationSystemTestCase test "responsive layout changes at breakpoints" do visit feedbacks_path # Desktop page.driver.browser.manage.window.resize_to(1280, 800) assert_selector ".hidden.md\:flex" # Desktop nav visible

# Mobile
page.driver.browser.manage.window.resize_to(375, 667)
assert_selector ".block.md\\:hidden"  # Mobile menu visible

end

test "dark mode toggle works" do visit root_path assert_equal "light", page.evaluate_script("document.documentElement.getAttribute('data-theme')")

click_button "Toggle Theme"
assert_equal "dark", page.evaluate_script("document.documentElement.getAttribute('data-theme')")

end end

Manual Testing Checklist:

  • Test responsive breakpoints (375px, 640px, 768px, 1024px, 1280px)

  • Verify color contrast ratios (use browser DevTools or axe)

  • Test dark mode theme

  • Check focus states on all interactive elements

  • Validate against W3C HTML validator

  • Test browser zoom (200%, 400%)

Official Documentation:

  • Tailwind CSS Documentation

  • DaisyUI Documentation

  • DaisyUI Components

Tools:

  • Tailwind CSS Cheat Sheet

Community Resources:

  • Tailwind UI Components - Premium component library

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

rails-ai:hotwire

No summary provided by upstream source.

Repository SourceNeeds Review
General

rails-ai:mailers

No summary provided by upstream source.

Repository SourceNeeds Review
General

rails-ai:debugging-rails

No summary provided by upstream source.

Repository SourceNeeds Review
General

rails-ai:views

No summary provided by upstream source.

Repository SourceNeeds Review