Tabs
A set of layered sections of content, known as tab panels, that are displayed one at a time.
Account
Make changes to your account here. Click save when you're done.
Password
Change your password here. After saving, you'll be logged out.
<%= render Shadcn::TabsComponent.new(default_value: "tab1", class_name: "w-[400px]") do |tabs| %>
<% tabs.with_list do |list| %>
<% list.with_trigger(value: "tab1") { "Tab 1" } %>
<% list.with_trigger(value: "tab2") { "Tab 2" } %>
<% list.with_trigger(value: "tab3") { "Tab 3" } %>
<% end %>
<% tabs.with_panel(value: "tab1") do %>
<div class="p-4">Content for Tab 1</div>
<% end %>
<% tabs.with_panel(value: "tab2") do %>
<div class="p-4">Content for Tab 2</div>
<% end %>
<% tabs.with_panel(value: "tab3") do %>
<div class="p-4">Content for Tab 3</div>
<% end %>
<% end %>
Installation
Add the component to your project:
rails generate shadcn:add tabs
Usage
<%= render Shadcn::TabsComponent.new(default_value: "tab1", class_name: "w-[400px]") do |tabs| %>
<% tabs.with_list do |list| %>
<% list.with_trigger(value: "tab1") { "Tab 1" } %>
<% list.with_trigger(value: "tab2") { "Tab 2" } %>
<% list.with_trigger(value: "tab3") { "Tab 3" } %>
<% end %>
<% tabs.with_panel(value: "tab1") do %>
<div class="p-4">Content for Tab 1</div>
<% end %>
<% tabs.with_panel(value: "tab2") do %>
<div class="p-4">Content for Tab 2</div>
<% end %>
<% tabs.with_panel(value: "tab3") do %>
<div class="p-4">Content for Tab 3</div>
<% end %>
<% end %>
Examples
Basic
<%= render Shadcn::TabsComponent.new(default_value: "tab1", class_name: "w-[400px]") do |tabs| %>
<% tabs.with_list do |list| %>
<% list.with_trigger(value: "tab1") { "Tab 1" } %>
<% list.with_trigger(value: "tab2") { "Tab 2" } %>
<% list.with_trigger(value: "tab3") { "Tab 3" } %>
<% end %>
<% tabs.with_panel(value: "tab1") do %>
<div class="p-4">Content for Tab 1</div>
<% end %>
<% tabs.with_panel(value: "tab2") do %>
<div class="p-4">Content for Tab 2</div>
<% end %>
<% tabs.with_panel(value: "tab3") do %>
<div class="p-4">Content for Tab 3</div>
<% end %>
<% end %>
URL Sync
Sync the active tab with the URL using the url_param option.
This is useful for shareable links and browser back/forward navigation.
Disabled Tab
<%= render Shadcn::TabsComponent.new(default_value: "active", class_name: "w-[400px]") do |tabs| %>
<% tabs.with_list do |list| %>
<% list.with_trigger(value: "active") { "Active" } %>
<% list.with_trigger(value: "disabled", disabled: true) { "Disabled" } %>
<% list.with_trigger(value: "another") { "Another" } %>
<% end %>
<% tabs.with_panel(value: "active") do %>
<div class="p-4">Active tab content</div>
<% end %>
<% tabs.with_panel(value: "disabled") do %>
<div class="p-4">Disabled tab content</div>
<% end %>
<% tabs.with_panel(value: "another") do %>
<div class="p-4">Another tab content</div>
<% end %>
<% end %>
With Cards
Account
Make changes to your account here.
Password
Change your password here.
<%= render Shadcn::TabsComponent.new(default_value: "tab1", class_name: "w-[400px]") do |tabs| %>
<% tabs.with_list do |list| %>
<% list.with_trigger(value: "tab1") { "Tab 1" } %>
<% list.with_trigger(value: "tab2") { "Tab 2" } %>
<% list.with_trigger(value: "tab3") { "Tab 3" } %>
<% end %>
<% tabs.with_panel(value: "tab1") do %>
<div class="p-4">Content for Tab 1</div>
<% end %>
<% tabs.with_panel(value: "tab2") do %>
<div class="p-4">Content for Tab 2</div>
<% end %>
<% tabs.with_panel(value: "tab3") do %>
<div class="p-4">Content for Tab 3</div>
<% end %>
<% end %>
API Reference
TabsComponent
| Prop | Type | Default | Description |
|---|---|---|---|
| default_value |
String
|
nil
|
The value of the initially active tab |
| orientation |
Symbol
|
:horizontal
|
Tab orientation (:horizontal or :vertical) |
| url_param |
String
|
nil
|
Query parameter name to sync active tab with URL |
Slots
| Slot | Description |
|---|---|
| with_list | Container for tab triggers (yields TabsListComponent) |
| with_panel(value:) | Tab panel content, matched by value to trigger |
TabsListComponent Slots
| Slot | Props | Description |
|---|---|---|
| with_trigger | value:, disabled: |
Tab trigger button |
Stimulus Controller
This component requires JavaScript. The Stimulus controller shadcn--tabs provides interactivity.
Manages tab switching, keyboard navigation, and URL synchronization.
Installation
Add to your config/importmap.rb:
pin "shadcn", to: "index.esm.js"
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn"
const application = Application.start()
registerShadcnControllers(application)
Install the package:
npm install shadcn-rails-stimulus
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn-rails-stimulus"
const application = Application.start()
registerShadcnControllers(application)
Install the package:
yarn add shadcn-rails-stimulus
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn-rails-stimulus"
const application = Application.start()
registerShadcnControllers(application)
Install the package:
npm install shadcn-rails-stimulus
Then in your app/javascript/controllers/index.js:
import { Application } from "@hotwired/stimulus"
import { registerShadcnControllers } from "shadcn-rails-stimulus"
const application = Application.start()
registerShadcnControllers(application)
Or import just this controller:
import TabsController from "shadcn-rails-stimulus/controllers/tabs_controller"
application.register("shadcn--tabs", TabsController)
Targets
| Name | Description |
|---|---|
| trigger | Tab trigger buttons |
| content | Tab content panels |
Values
| Name | Type | Default | Description |
|---|---|---|---|
| value | String |
""
|
Currently active tab value |
| defaultValue | String |
""
|
Initial tab value |
| urlParam | String |
null
|
URL parameter name for syncing |
Actions
| Action | Description |
|---|---|
| selectTab | Switches to a specific tab (triggered by click) |
TypeScript
Type definitions are included. Import types as needed:
import type { TabsController } from "shadcn-rails-stimulus"
Accessibility
- Uses
role="tablist",role="tab", androle="tabpanel" - Sets
aria-selectedon active tab - Links tabs to panels via
aria-controlsandaria-labelledby - Keyboard navigation: Arrow Left/Arrow Right to navigate between tabs
- Home/End to jump to first/last tab
On This Page