--- name: rails-ai:styling description: Use when styling Rails views - Tailwind CSS utility-first framework and DaisyUI component library with theming --- # 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. - Styling ANY user interface in Rails - Building responsive layouts (mobile, tablet, desktop) - Implementing dark mode or multiple themes - Creating consistent UI components (buttons, cards, forms, modals) - Rapid UI iteration and prototyping - Maintaining design system consistency - **Rapid Development** - Compose UIs with pre-built utilities - **Consistency** - Design tokens enforce consistent spacing, colors, typography - **Responsive by Default** - Mobile-first breakpoints built-in - **Dark Mode** - Theme switching with DaisyUI data attributes - **No Custom CSS** - Most styling done with classes, no style tag needed - **Accessible Components** - DaisyUI components have built-in accessibility - **Small Bundle Size** - Tailwind purges unused CSS in production **This skill enforces:** - ✅ **Rule #9:** DaisyUI + Tailwind (no hardcoded colors) **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) Before completing styling work: - ✅ No hardcoded colors (use DaisyUI theme variables) - ✅ Responsive design (mobile, tablet, desktop breakpoints) - ✅ Accessibility verified (color contrast, keyboard navigation) - ✅ Theme-aware (works with light/dark modes) - ✅ Tailwind utilities used (minimal custom CSS) - ✅ DaisyUI components for complex UI - Use Tailwind utilities first, DaisyUI components for complex UI - Follow mobile-first responsive design (base → sm → md → lg → xl) - Use semantic color names from DaisyUI (primary, secondary, accent, neutral) - Avoid inline styles (`style=`) - use Tailwind classes instead - Use responsive breakpoints consistently (sm:640px, md:768px, lg:1024px, xl:1280px) - Implement dark mode with DaisyUI themes - Extract repeated utility combinations into view components (not CSS classes) - Ensure 4.5:1 color contrast ratio for text (WCAG 2.1 AA) --- ## Tailwind CSS Tailwind CSS is a utility-first CSS framework for building custom designs without writing custom CSS. ### Core Utilities Consistent spacing and layout with Tailwind utilities ```erb <%# Spacing: p-{size}, m-{size}, gap-{size} %>
Padding all sides
Horizontal/Vertical padding
Centered container
<%# Flexbox layout %>
Left Right
<%# Grid layout %>
<% @items.each do |item| %>
<%= item.name %>
<% end %>
```
Mobile-first responsive utilities (sm:640px, md:768px, lg:1024px, xl:1280px) ```erb <%# Pattern: base (mobile) → sm: → md: → lg: → xl: %>
<% @feedbacks.each do |feedback| %> <%= render feedback %> <% end %>
<%# Responsive spacing/typography %>

Heading

<%# Hide/show based on breakpoint %>
Mobile menu
```
Text styling and color utilities ```erb <%# Typography %>

Small medium text

Large heading

Spaced text

<%= feedback.content %>

<%# Colors: text-{color}-{shade}, bg-{color}-{shade} %>
Dark text on white
White on blue

Red with 50% opacity

<%# Interactive states %> ```
Complete feedback card using Tailwind utilities ```erb
<%# Header %>
<%= @feedback.sender_name&.first&.upcase || "A" %>

<%= @feedback.sender_name || "Anonymous" %>

<%= time_ago_in_words(@feedback.created_at) %> ago

<%= @feedback.status.titleize %>
<%# Content %>

<%= @feedback.content %>

<%# Footer %>
<%= @feedback.responses_count %> responses
<%= 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" %>
```
Using inline styles instead of Tailwind utilities Bypasses design system consistency and reduces maintainability ```erb <%# ❌ BAD %>
Content
```
```erb <%# ✅ GOOD %>
Content
```
--- ## DaisyUI Components Semantic component library built on Tailwind providing 70+ accessible components with built-in theming and dark mode. ### Buttons & Forms Use DaisyUI button classes for consistent interactive elements ```erb <%# DaisyUI button components %> <%# Rails form integration %> <%= form_with model: @feedback do |f| %>
<%= f.label :content, class: "label" do %> Feedback <% end %> <%= f.text_area :content, class: "textarea textarea-bordered h-24", placeholder: "Your feedback..." %>
<%= link_to "Cancel", feedbacks_path, class: "btn btn-ghost" %> <%= f.submit "Submit", class: "btn btn-primary" %>
<% end %> ```
Use card component for content containers ```erb

<%= @feedback.title %>

<%= @feedback.status.titleize %>

<%= @feedback.content %>

<%= link_to "View", feedback_path(@feedback), class: "btn btn-primary btn-sm" %>
```
Use alerts and badges for notifications and status ```erb <%# Alerts %>
Success! Your feedback was submitted.
Error! Unable to submit feedback.
<%# Flash messages %> <% if flash[:notice] %>
<%= flash[:notice] %>
<% end %> <%# Badges %>
Primary
Success
Warning
```
Use modal component for dialogs ```erb ``` ### Theme Switching Implement dark mode and theme switching ```javascript // 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) } } ``` ```erb <%# Layout %>
```
Building custom buttons with Tailwind instead of DaisyUI components Duplicates effort, loses accessibility features ```erb <%# ❌ Custom button with Tailwind utilities %> ``` ```erb <%# ✅ DaisyUI button component %> ``` --- **Visual Regression Testing:** ```ruby # 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%) --- - rails-ai:views - View structure and partials to style - rails-ai:hotwire - Interactive components that need styling - rails-ai:testing - Visual regression and accessibility testing **Official Documentation:** - [Tailwind CSS Documentation](https://tailwindcss.com/docs) - [DaisyUI Documentation](https://daisyui.com/) - [DaisyUI Components](https://daisyui.com/components/) **Tools:** - [Tailwind CSS Cheat Sheet](https://nerdcave.com/tailwind-cheat-sheet) **Community Resources:** - [Tailwind UI Components](https://tailwindui.com/) - Premium component library