Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Itacomp is a [View Component](https://viewcomponent.org/) and [Helper](https://a
* [AlertComponent](app/components/itacomp/alert_component.rb)
* [AvatorComponent](app/components/itacomp/avator_component.rb)
* [NotificationComponent](app/components/itacomp/notification_component.rb)
* [TabComponent](app/components/itacomp/tab_component.rb)
* [TurboFrameComponent](app/components/itacomp/turbo_frame_component.rb)

## Installation
Expand Down
65 changes: 65 additions & 0 deletions app/components/itacomp/tab_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

module Itacomp
# make a strcture for [tab component](https://italia.github.io/bootstrap-italia/docs/componenti/tab/)
# ==== Example
# With no params return an empty tab container
# <%= render Itacomp::TabComponent.new %>
# <ul class="nav nav-tabs" role="tablist"></ul>
# With options on container
# <%= render Itacomp::TabComponent.new(class: 'top-tab', data: {enabled: true}) %>
# <ul class="nav nav-tabs top-tab" role="tablist" data-enabled="true"></ul>
# with some entries
# <%= render Itacomp::TabComponent.new([["Home", root_path], active: true, ["Books", books_path]]) %>
# <ul class="nav nav-tabs" role="tablist">
# <li class="nav-item"><a class="nav-link active" role="tab" href="/">Home</a></li>
# <li class="nav-item"><a class="nav-link" role="tab" href="/books">Books</a></li>
# </ul>
class TabComponent < ViewComponent::Base
# Initialize tab component
#
# ==== options
# * <tt>entries</tt> array of tabs, read "entries structure"
# * <tt>**opts</tt> each key is delegated as ul tag options
# * <tt>yield</tt> Alternative tabs content
#
# ==== Entries structure
# Entries is an Array of tab option. A tab is structured with
# * <tt>text</tt>, default nil, html link content (you can include icon too)
# * <tt>url</tt>, default nil, destination link url
# * <tt>**opts</tt> each key is delegated as link_to options
def initialize(entries = [], **opts)
opts[:class] = [ "nav nav-tabs", opts[:class] ]
opts[:role] = "tablist"
@opts = opts
@entries = entries
end

# Return html for a tab.
# The container tag li have class "nav-item"
# The link have class "nav-link", other class are append after this.
# The link have role "tab"
#
# ==== Options
# * <tt>text</tt>, default nil, html link content (you can include icon too)
# * <tt>url</tt>, default nil, Destination link utl
# * <tt>**opts</tt> each key is delegated as link_to options
#
# ==== Example
# tab('test', root_path, class: 'mytab')
# <li class="nav-item"><a class="nav-link mytab" role="tab" href="/">test</a></li>
def tab(text = nil, url = nil, **opts)
opts[:class] = [ "nav-link", opts[:class] ]
opts[:role] = "tab"
tag.li(link_to(text, url, **opts), class: "nav-item")
end

# From entried return an array of tab
#
# === Options
# * <tt>entries</tt>, default @entries, array of tab
def tabs(entries = @entries)
safe_join(entries.map { |e| tab(e[0], e[1], **e[2]) })
end
end
end
3 changes: 3 additions & 0 deletions app/components/itacomp/tab_component/tab_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= tag.ul **@opts do %>
<%= content? ? content : tabs %>
<% end %>
21 changes: 21 additions & 0 deletions test/components/itacomp/tab_component_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# frozen_string_literal: true

require "test_helper"

class Itacomp::TabComponentTest < ViewComponent::TestCase
test "empty tabs" do
render_inline Itacomp::TabComponent.new()
assert_selector "ul.nav.nav-tabs[role='tablist']", text: nil
end

test "can add options to ul selector" do
render_inline Itacomp::TabComponent.new(id: "uno", class: "due", data: { value: "tre" })
assert_selector "ul#uno.nav.nav-tabs.due[role='tablist'][data-value='tre']", text: nil
end

test "can add content as array" do
render_inline Itacomp::TabComponent.new([ [ "uno", "/due", { active: true } ], [ "tre", "/quattro" ] ])
assert_selector "ul.nav.nav-tabs[role='tablist'] li.nav-item a.nav-link[active='true'][href='/due']", text: "uno"
assert_selector "ul.nav.nav-tabs[role='tablist'] li.nav-item a.nav-link[href='/quattro']", text: "tre"
end
end
9 changes: 9 additions & 0 deletions test/components/previews/itacomp/tab_component_preview.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

module Itacomp
class TabComponentPreview < ViewComponent::Preview
def default
render(TabComponent.new(entries: "entries"))
end
end
end