Rails ViewComponent tabs not rendering content

1 week ago 20
ARTICLE AD BOX

I'm building a tabs component using ViewComponent and Stimulus, but the tab content (partials) are not rendering. I believe it's related to the active tab state.

Component Structure

tabs_component.rb:

class Dashboard::TabsComponent < ViewComponent::Base class Tab < ViewComponent::Base attr_reader :title, :active, :block def initialize(title:, active: false, &block) @title = title @active = active @block = block end def active? @active end def content(view_context) view_context.capture(&@block) if @block end end renders_many :tabs, Tab def active_tab_index tabs.index(&:active?) || 0 end end

tabs_component.html.erb:

<div class="w-full" data-controller="tabs"> <!-- Tab headers --> <div> <nav class="flex space-x-8" aria-label="Tabs"> <% tabs.each_with_index do |tab, index| %> <button class="px-4 py-2 text-gray-600 hover:text-blue-600 focus:outline-none <%= 'border-b-2 border-blue-500 text-blue-600' if index == active_tab_index %>" data-tab-index="<%= index %>" data-action="click->tabs#switch" data-tabs-target="button" > <%= tab.title %> </button> <% end %> </nav> </div> <!-- Tab panels --> <div class="mt-6"> <% tabs.each_with_index do |tab, index| %> <div class="<%= 'hidden' unless index == active_tab_index %>" data-tab-index="<%= index %>" data-tabs-target="panel" > <%= tab.content(self) %> </div> <% end %> </div> </div>

tabs_controller.js:

import { Controller } from "@hotwired/stimulus" export default class extends Controller { static targets = ["button", "panel"] connect() { console.log("Tabs Controller Connected") } switch(event) { event.preventDefault(); const index = event.currentTarget.dataset.tabIndex; // Remove active classes this.buttonTargets.forEach(btn => btn.classList.remove("border-b-2", "border-blue-500", "text-blue-600")) this.panelTargets.forEach(panel => panel.classList.add("hidden")) // Add active classes this.buttonTargets[index].classList.add("border-b-2", "border-blue-500", "text-blue-600") this.panelTargets[index].classList.remove("hidden") } }

Usage

settings/show.html.erb:

<div class="container mx-auto pt-12 px-6"> <%= render Dashboard::TabsComponent.new do |component| %> <% component.with_tab(title: "General") do %> General <% end %> <% component.with_tab(title: "Appearance") do %> <%= render "settings/appearance" %> <% end %> <% component.with_tab(title: "Appointments") do %> <%= render "settings/appointments" %> <% end %> <% end %> </div>

Problem

The tab buttons render correctly, but none of the tab content (including the partials) is showing up. The panels appear to all be hidden.

What I've Tried

Verified the partials exist and render correctly when used outside the component Checked browser console - Stimulus controller connects successfully Inspected the DOM - panels have the hidden class applied

What am I missing? Why isn't the first tab showing by default?

Environment

Rails 7.x ViewComponent Stimulus Tailwind CSS
Read Entire Article