Tabs
A set of layered sections of content—known as tab panels—that are displayed one at a time.
Usage
Example
Account
Update your account details.
Password
Change your password here. After saving, you'll be logged out.
Tabs(default_value: "account", class: 'w-96') do TabsList do TabsTrigger(value: "account") { "Account" } TabsTrigger(value: "password") { "Password" } end TabsContent(value: "account") do div(class: "rounded-lg border p-6 space-y-4 bg-background text-foreground") do div(class: "space-y-0") do Text(size: "4", weight: "semibold") { "Account" } Text(size: "2", class: "text-muted-foreground") { "Update your account details." } end end end TabsContent(value: "password") do div(class: "rounded-lg border p-6 space-y-4 bg-background text-foreground") do div do Text(size: "4", weight: "semibold") { "Password" } Text(size: "2", class: "text-muted-foreground") { "Change your password here. After saving, you'll be logged out." } end end end end
Full width
Joel Drapper
Creator of Phlex Components. Ruby on Rails developer.
Tabs(default_value: "overview", class: 'w-96') do TabsList(class: 'w-full grid grid-cols-2') do TabsTrigger(value: "overview") do book_icon span(class: 'ml-2') { "Overview" } end TabsTrigger(value: "repositories") do repo_icon span(class: 'ml-2') { "Repositories" } end end TabsContent(value: "overview") do div(class: "rounded-lg border p-6 bg-background text-foreground flex justify-between space-x-4") do Avatar do AvatarImage(src: "https://avatars.githubusercontent.com/u/246692?v=4", alt: "joeldrapper") AvatarFallback { "JD" } end div(class: "space-y-4") do div do Text(size: "4", weight: "semibold") { "Joel Drapper" } Text(size: "2", class: "text-muted-foreground") { "Creator of Phlex Components. Ruby on Rails developer." } end Link(href: "https://github.com/joeldrapper", variant: :outline, size: :sm) do github_icon span(class: 'ml-2') { "View profile" } end end end end TabsContent(value: "repositories") do div(class: "rounded-lg border p-6 space-y-4 bg-background text-foreground") do repo = repositories.first Link(href: repo.github_url, variant: :link, class: "pl-0") { repo.name } Badge { repo.version } end end end
Change default value
Account
Update your account details.
Password
Change your password here. After saving, you'll be logged out.
Tabs(default: "password", class: 'w-96') do TabsList do TabsTrigger(value: "account") { "Account" } TabsTrigger(value: "password") { "Password" } end TabsContent(value: "account") do div(class: "rounded-lg border p-6 space-y-4 bg-background text-foreground") do div(class: "space-y-0") do Text(size: "4", weight: "semibold") { "Account" } Text(size: "2", class: "text-muted-foreground") { "Update your account details." } end end end TabsContent(value: "password") do div(class: "rounded-lg border p-6 space-y-4 bg-background text-foreground") do div do Text(size: "4", weight: "semibold") { "Password" } Text(size: "2", class: "text-muted-foreground") { "Change your password here. After saving, you'll be logged out." } end end end end
Installation
Using RubyUI CLI
Run the install command
rails g ruby_ui:component Tabs
Manual installation
1
Add RubyUI::Tabs
to app/components/ruby_ui/tabs.rb
# frozen_string_literal: true module RubyUI class Tabs < Base def initialize(default: nil, **attrs) @default = default super(**attrs) end def view_template(&) div(**attrs, &) end private def default_attrs { data: { controller: "ruby-ui--tabs", ruby_ui__tabs_active_value: @default } } end end end
2
Add RubyUI::TabsContent
to app/components/ruby_ui/tabs/tabs_content.rb
# frozen_string_literal: true module RubyUI class TabsContent < Base def initialize(value:, **attrs) @value = value super(**attrs) end def view_template(&) div(**attrs, &) end private def default_attrs { data: { ruby_ui__tabs_target: :content, value: @value }, class: "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 hidden" } end end end
3
Add RubyUI::TabsList
to app/components/ruby_ui/tabs/tabs_list.rb
# frozen_string_literal: true module RubyUI class TabsList < Base def view_template(&) div(**attrs, &) end private def default_attrs { class: "inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground" } end end end
4
Add RubyUI::TabsTrigger
to app/components/ruby_ui/tabs/tabs_trigger.rb
# frozen_string_literal: true module RubyUI class TabsTrigger < Base def initialize(value:, **attrs) @value = value super(**attrs) end def view_template(&) button(**attrs, &) end private def default_attrs { type: :button, data: { ruby_ui__tabs_target: "trigger", action: "click->ruby-ui--tabs#show", value: @value }, class: "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow" } end end end
5
Add tabs_controller.js
to app/javascript/controllers/ruby_ui/tabs_controller.js
import { Controller } from "@hotwired/stimulus"; // Connects to data-controller="ruby-ui--tabs" export default class extends Controller { static targets = ["trigger", "content"]; static values = { active: String }; connect() { if (!this.hasActiveValue && this.triggerTargets.length > 0) { this.activeValue = this.triggerTargets[0].dataset.value; } } show(e) { this.activeValue = e.currentTarget.dataset.value; } activeValueChanged(currentValue, previousValue) { if (currentValue == "" || currentValue == previousValue) return; this.contentTargets.forEach((el) => { el.classList.add("hidden"); }); this.triggerTargets.forEach((el) => { el.dataset.state = "inactive"; }); this.activeContentTarget() && this.activeContentTarget().classList.remove("hidden"); this.activeTriggerTarget().dataset.state = "active"; } activeTriggerTarget() { return this.triggerTargets.find( (el) => el.dataset.value == this.activeValue, ); } activeContentTarget() { return this.contentTargets.find( (el) => el.dataset.value == this.activeValue, ); } }
6
Update the Stimulus controllers manifest file
Importmap!
rake stimulus:manifest:update
Components
Component | Built using | Source |
---|---|---|
Tabs | Phlex | |
TabsContent | Phlex | |
TabsList | Phlex | |
TabsTrigger | Phlex | |
TabsController | Stimulus JS |