Blocks

Tabs

Organises content into distinct panels, showing one at a time via a tab strip.

Installation

bin/rails g shadcnrb:component tabs

Usage

Each t.tab is one trigger + panel pair — the tab strip is assembled from them, and the pairing is structural, no value: ids to match up. The first tab starts active unless one passes active: true.

Manage your account details and preferences.

Change your password and security settings.

Choose what notifications you receive.

<%= sui.tabs do |t| %>
  <%= t.tab "Account" do %>
    <p class="text-sm text-muted-foreground pt-2">Manage your account details and preferences.</p>
  <% end %>
  <%= t.tab "Password" do %>
    <p class="text-sm text-muted-foreground pt-2">Change your password and security settings.</p>
  <% end %>
  <%= t.tab "Notifications" do %>
    <p class="text-sm text-muted-foreground pt-2">Choose what notifications you receive.</p>
  <% end %>
<% end %>

With richer content

Tab content can hold any markup — forms, cards, lists, etc.

Total revenue

$45,231.89

+20.1% from last month

Recent sign-ins

Chrome · macOS · 2 minutes ago

Safari · iOS · 1 hour ago

<%= sui.tabs do |t| %>
  <%= t.tab "Overview" do %>
    <div class="pt-2 space-y-1">
      <p class="text-sm font-medium">Total revenue</p>
      <p class="text-2xl font-bold">$45,231.89</p>
      <p class="text-xs text-muted-foreground">+20.1% from last month</p>
    </div>
  <% end %>
  <%= t.tab "Activity" do %>
    <div class="pt-2 space-y-1">
      <p class="text-sm font-medium">Recent sign-ins</p>
      <p class="text-xs text-muted-foreground">Chrome · macOS · 2 minutes ago</p>
      <p class="text-xs text-muted-foreground">Safari · iOS · 1 hour ago</p>
    </div>
  <% end %>
<% end %>

API

MethodArgsDefaultDescription
sui.tabsvariant:, orientation:, list:, content:, **opts:default / :horizontalRoot container. Mounts the shadcnrb--tabs--component controller, assembles the tab strip (role="tablist") and panels from the block's t.tab calls. list: / content: are option hashes for the strip and every panel.
t.tab(name)active:, **opts, &blockfalseOne trigger + panel pair: name is the tab button, the block is its panel. Hidden panels remain in the DOM. **opts land on the tab button.