primer_view_components 0.0.30 → 0.0.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +78 -0
- data/README.md +2 -2
- data/app/components/primer/auto_complete_component.rb +1 -1
- data/app/components/primer/auto_complete_item_component.rb +1 -1
- data/app/components/primer/avatar_stack_component.rb +1 -1
- data/app/components/primer/base_component.rb +115 -85
- data/app/components/primer/blankslate_component.html.erb +1 -1
- data/app/components/primer/blankslate_component.rb +0 -2
- data/app/components/primer/border_box_component.rb +0 -2
- data/app/components/primer/breadcrumb_component.rb +0 -1
- data/app/components/primer/button_component.rb +13 -11
- data/app/components/primer/button_group_component.rb +3 -5
- data/app/components/primer/button_marketing_component.rb +12 -12
- data/app/components/primer/component.rb +3 -0
- data/app/components/primer/details_component.rb +0 -1
- data/app/components/primer/dropdown/menu_component.rb +0 -2
- data/app/components/primer/dropdown_component.rb +1 -3
- data/app/components/primer/dropdown_menu_component.rb +1 -1
- data/app/components/primer/flash_component.html.erb +2 -2
- data/app/components/primer/flash_component.rb +10 -12
- data/app/components/primer/layout_component.rb +0 -2
- data/app/components/primer/link_component.rb +9 -9
- data/app/components/primer/menu_component.rb +2 -4
- data/app/components/primer/navigation/tab_component.html.erb +11 -0
- data/app/components/primer/navigation/tab_component.rb +126 -0
- data/app/components/primer/octicon_component.rb +5 -8
- data/app/components/primer/popover_component.rb +19 -3
- data/app/components/primer/progress_bar_component.rb +0 -1
- data/app/components/primer/spinner_component.html.erb +1 -3
- data/app/components/primer/spinner_component.rb +1 -0
- data/app/components/primer/state_component.rb +13 -13
- data/app/components/primer/subhead_component.rb +1 -3
- data/app/components/primer/tab_nav_component.html.erb +8 -10
- data/app/components/primer/tab_nav_component.rb +63 -76
- data/app/components/primer/time_ago_component.rb +2 -1
- data/app/components/primer/timeline_item_component.rb +1 -2
- data/app/components/primer/underline_nav_component.html.erb +19 -7
- data/app/components/primer/underline_nav_component.rb +114 -16
- data/app/lib/primer/classify.rb +5 -14
- data/app/lib/primer/classify/cache.rb +14 -4
- data/app/lib/primer/classify/spacing.rb +63 -0
- data/app/lib/primer/tabbed_component_helper.rb +39 -0
- data/app/lib/primer/view_helper.rb +2 -2
- data/lib/primer/view_components/version.rb +1 -1
- data/static/statuses.json +1 -1
- metadata +83 -22
- data/app/components/primer/slot.rb +0 -10
@@ -5,7 +5,6 @@ module Primer
|
|
5
5
|
#
|
6
6
|
# By default, the popover renders with absolute positioning, meaning it should usually be wrapped in an element with a relative position in order to be positioned properly. To render the popover with relative positioning, use the relative property.
|
7
7
|
class PopoverComponent < Primer::Component
|
8
|
-
include ViewComponent::SlotableV2
|
9
8
|
status :beta
|
10
9
|
|
11
10
|
CARET_DEFAULT = :top
|
@@ -54,7 +53,7 @@ module Primer
|
|
54
53
|
|
55
54
|
# This is a hack to allow the parent to set the slot's content
|
56
55
|
@body_arguments = system_arguments
|
57
|
-
block&.call
|
56
|
+
view_context.capture { block&.call }
|
58
57
|
}
|
59
58
|
|
60
59
|
# @example Default
|
@@ -83,7 +82,24 @@ module Primer
|
|
83
82
|
# Activity feed
|
84
83
|
# <% end %>
|
85
84
|
# <% component.body(caret: :left) do %>
|
86
|
-
# This is the
|
85
|
+
# This is the Popover body.
|
86
|
+
# <% end %>
|
87
|
+
# <% end %>
|
88
|
+
#
|
89
|
+
# @example With HTML body
|
90
|
+
# <%= render Primer::PopoverComponent.new do |component| %>
|
91
|
+
# <% component.heading do %>
|
92
|
+
# Activity feed
|
93
|
+
# <% end %>
|
94
|
+
# <% component.body(caret: :left) do %>
|
95
|
+
# <p> This is the Popover body.</p>
|
96
|
+
# <div>
|
97
|
+
# This is using HTML.
|
98
|
+
# <ul>
|
99
|
+
# <li>Thing #1</li>
|
100
|
+
# <li>Thing #2</li>
|
101
|
+
# </ul>
|
102
|
+
# </div>
|
87
103
|
# <% end %>
|
88
104
|
# <% end %>
|
89
105
|
#
|
@@ -1,6 +1,4 @@
|
|
1
1
|
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
|
2
2
|
<circle cx="8" cy="8" r="7" stroke="currentColor" stroke-opacity="0.25" stroke-width="2" vector-effect="non-scaling-stroke" />
|
3
|
-
<path d="M15 8a7.002 7.002 0 00-7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" vector-effect="non-scaling-stroke"
|
4
|
-
<animateTransform attributeName="transform" type="rotate" from="0 8 8" to="360 8 8" dur="1s" repeatCount="indefinite" />
|
5
|
-
</path>
|
3
|
+
<path d="M15 8a7.002 7.002 0 00-7-7" stroke="currentColor" stroke-width="2" stroke-linecap="round" vector-effect="non-scaling-stroke" />
|
6
4
|
<% end %>
|
@@ -31,6 +31,7 @@ module Primer
|
|
31
31
|
@system_arguments = system_arguments
|
32
32
|
@system_arguments[:tag] = :svg
|
33
33
|
@system_arguments[:style] ||= DEFAULT_STYLE
|
34
|
+
@system_arguments[:animation] = :rotate
|
34
35
|
@system_arguments[:width] = SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)]
|
35
36
|
@system_arguments[:height] = SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)]
|
36
37
|
@system_arguments[:viewBox] = "0 0 16 16"
|
@@ -5,21 +5,21 @@ module Primer
|
|
5
5
|
class StateComponent < Primer::Component
|
6
6
|
status :beta
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
SCHEME_DEFAULT = :default
|
9
|
+
NEW_SCHEME_MAPPINGS = {
|
10
10
|
open: "State--open",
|
11
11
|
closed: "State--closed",
|
12
12
|
merged: "State--merged"
|
13
13
|
}.freeze
|
14
14
|
|
15
|
-
|
16
|
-
|
15
|
+
DEPRECATED_SCHEME_MAPPINGS = {
|
16
|
+
SCHEME_DEFAULT => "",
|
17
17
|
:green => "State--open",
|
18
18
|
:red => "State--closed",
|
19
19
|
:purple => "State--merged"
|
20
20
|
}.freeze
|
21
|
-
|
22
|
-
|
21
|
+
SCHEME_MAPPINGS = NEW_SCHEME_MAPPINGS.merge(DEPRECATED_SCHEME_MAPPINGS)
|
22
|
+
SCHEME_OPTIONS = SCHEME_MAPPINGS.keys
|
23
23
|
|
24
24
|
SIZE_DEFAULT = :default
|
25
25
|
SIZE_MAPPINGS = {
|
@@ -34,24 +34,24 @@ module Primer
|
|
34
34
|
# @example Default
|
35
35
|
# <%= render(Primer::StateComponent.new(title: "title")) { "State" } %>
|
36
36
|
#
|
37
|
-
# @example
|
37
|
+
# @example Schemes
|
38
38
|
# <%= render(Primer::StateComponent.new(title: "title")) { "Default" } %>
|
39
|
-
# <%= render(Primer::StateComponent.new(title: "title",
|
40
|
-
# <%= render(Primer::StateComponent.new(title: "title",
|
41
|
-
# <%= render(Primer::StateComponent.new(title: "title",
|
39
|
+
# <%= render(Primer::StateComponent.new(title: "title", scheme: :open)) { "Open" } %>
|
40
|
+
# <%= render(Primer::StateComponent.new(title: "title", scheme: :closed)) { "Closed" } %>
|
41
|
+
# <%= render(Primer::StateComponent.new(title: "title", scheme: :merged)) { "Merged" } %>
|
42
42
|
#
|
43
43
|
# @example Sizes
|
44
44
|
# <%= render(Primer::StateComponent.new(title: "title")) { "Default" } %>
|
45
45
|
# <%= render(Primer::StateComponent.new(title: "title", size: :small)) { "Small" } %>
|
46
46
|
#
|
47
47
|
# @param title [String] `title` HTML attribute.
|
48
|
-
# @param
|
48
|
+
# @param scheme [Symbol] Background color. <%= one_of(Primer::StateComponent::SCHEME_OPTIONS) %>
|
49
49
|
# @param tag [Symbol] HTML tag for element. <%= one_of(Primer::StateComponent::TAG_OPTIONS) %>
|
50
50
|
# @param size [Symbol] <%= one_of(Primer::StateComponent::SIZE_OPTIONS) %>
|
51
51
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
52
52
|
def initialize(
|
53
53
|
title:,
|
54
|
-
|
54
|
+
scheme: SCHEME_DEFAULT,
|
55
55
|
tag: TAG_DEFAULT,
|
56
56
|
size: SIZE_DEFAULT,
|
57
57
|
**system_arguments
|
@@ -62,7 +62,7 @@ module Primer
|
|
62
62
|
@system_arguments[:classes] = class_names(
|
63
63
|
@system_arguments[:classes],
|
64
64
|
"State",
|
65
|
-
|
65
|
+
SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_OPTIONS, scheme, SCHEME_DEFAULT)],
|
66
66
|
SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, SIZE_DEFAULT)]
|
67
67
|
)
|
68
68
|
end
|
@@ -5,8 +5,6 @@ module Primer
|
|
5
5
|
class SubheadComponent < Primer::Component
|
6
6
|
status :beta
|
7
7
|
|
8
|
-
include ViewComponent::SlotableV2
|
9
|
-
|
10
8
|
# The heading
|
11
9
|
#
|
12
10
|
# @param danger [Boolean] Whether to style the heading as dangerous.
|
@@ -73,7 +71,7 @@ module Primer
|
|
73
71
|
# <% component.actions do %>
|
74
72
|
# <%= render(
|
75
73
|
# Primer::ButtonComponent.new(
|
76
|
-
# tag: :a, href: "http://www.google.com",
|
74
|
+
# tag: :a, href: "http://www.google.com", scheme: :danger
|
77
75
|
# )
|
78
76
|
# ) { "Action" } %>
|
79
77
|
# <% end %>
|
@@ -1,17 +1,15 @@
|
|
1
|
-
<%=
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
<%= wrapper do %>
|
2
|
+
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
|
3
|
+
<%= render Primer::BaseComponent.new(**@body_arguments) do %>
|
4
|
+
<% tabs.each do |tab| %>
|
5
|
+
<%= tab %>
|
6
|
+
<% end %>
|
5
7
|
<% end %>
|
6
|
-
|
8
|
+
<% end %>
|
7
9
|
|
8
10
|
<% if @with_panel %>
|
9
11
|
<% tabs.each do |tab| %>
|
10
|
-
|
11
|
-
<div role="tabpanel" <%= "hidden" if tab.hidden? %>>
|
12
|
-
<%= tab.panel %>
|
13
|
-
</div>
|
14
|
-
<% end %>
|
12
|
+
<%= tab.panel %>
|
15
13
|
<% end %>
|
16
14
|
<% end %>
|
17
15
|
<% end %>
|
@@ -3,106 +3,93 @@
|
|
3
3
|
module Primer
|
4
4
|
# Use TabNav to style navigation with a tab-based selected state, typically used for navigation placed at the top of the page.
|
5
5
|
class TabNavComponent < Primer::Component
|
6
|
-
include
|
6
|
+
include Primer::TabbedComponentHelper
|
7
7
|
|
8
|
-
|
9
|
-
class NoSelectedTabsError < StandardError; end
|
10
|
-
|
11
|
-
# Tabs to be rendered.
|
8
|
+
# Tabs to be rendered. For more information, refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
|
12
9
|
#
|
13
|
-
# @param title [String] Text to be rendered by the tab.
|
14
10
|
# @param selected [Boolean] Whether the tab is selected.
|
15
11
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
16
|
-
renders_many :tabs, lambda {
|
17
|
-
|
12
|
+
renders_many :tabs, lambda { |selected: false, **system_arguments|
|
13
|
+
system_arguments[:classes] = class_names(
|
14
|
+
"tabnav-tab",
|
15
|
+
system_arguments[:classes]
|
16
|
+
)
|
18
17
|
|
19
|
-
TabComponent.new(
|
18
|
+
Primer::Navigation::TabComponent.new(
|
19
|
+
selected: selected,
|
20
|
+
with_panel: @with_panel,
|
21
|
+
**system_arguments
|
22
|
+
)
|
20
23
|
}
|
21
24
|
|
22
25
|
# @example Default
|
23
|
-
# <%= render(Primer::TabNavComponent.new) do |c| %>
|
24
|
-
# <% c.tab(selected: true,
|
25
|
-
# <% c.tab(
|
26
|
-
# <% c.tab(
|
26
|
+
# <%= render(Primer::TabNavComponent.new(label: "Default")) do |c| %>
|
27
|
+
# <% c.tab(selected: true, href: "#") { "Tab 1" }%>
|
28
|
+
# <% c.tab(href: "#") { "Tab 2" } %>
|
29
|
+
# <% c.tab(href: "#") { "Tab 3" } %>
|
30
|
+
# <% end %>
|
31
|
+
#
|
32
|
+
# @example With icons and counters
|
33
|
+
# <%= render(Primer::TabNavComponent.new(label: "With icons and counters")) do |component| %>
|
34
|
+
# <% component.tab(href: "#", selected: true) do |t| %>
|
35
|
+
# <% t.icon(icon: :star) %>
|
36
|
+
# <% t.text { "Item 1" } %>
|
37
|
+
# <% end %>
|
38
|
+
# <% component.tab(href: "#") do |t| %>
|
39
|
+
# <% t.icon(icon: :star) %>
|
40
|
+
# <% t.text { "Item 2" } %>
|
41
|
+
# <% t.counter(count: 10) %>
|
42
|
+
# <% end %>
|
43
|
+
# <% component.tab(href: "#") do |t| %>
|
44
|
+
# <% t.text { "Item 3" } %>
|
45
|
+
# <% t.counter(count: 10) %>
|
46
|
+
# <% end %>
|
27
47
|
# <% end %>
|
28
48
|
#
|
29
49
|
# @example With panels
|
30
|
-
# <%= render(Primer::TabNavComponent.new(with_panel: true)) do |c| %>
|
31
|
-
# <% c.tab(selected: true
|
32
|
-
#
|
33
|
-
#
|
50
|
+
# <%= render(Primer::TabNavComponent.new(label: "With panels", with_panel: true)) do |c| %>
|
51
|
+
# <% c.tab(selected: true) do |t| %>
|
52
|
+
# <% t.text { "Tab 1" } %>
|
53
|
+
# <% t.panel do %>
|
54
|
+
# Panel 1
|
55
|
+
# <% end %>
|
56
|
+
# <% end %>
|
57
|
+
# <% c.tab do |t| %>
|
58
|
+
# <% t.text { "Tab 2" } %>
|
59
|
+
# <% t.panel do %>
|
60
|
+
# Panel 2
|
61
|
+
# <% end %>
|
62
|
+
# <% end %>
|
63
|
+
# <% c.tab do |t| %>
|
64
|
+
# <% t.text { "Tab 3" } %>
|
65
|
+
# <% t.panel do %>
|
66
|
+
# Panel 3
|
67
|
+
# <% end %>
|
68
|
+
# <% end %>
|
34
69
|
# <% end %>
|
35
70
|
#
|
36
|
-
# @param
|
71
|
+
# @param label [String] Used to set the `aria-label` on the top level `<nav>` element.
|
37
72
|
# @param with_panel [Boolean] Whether the TabNav should navigate through pages or panels.
|
38
73
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
39
|
-
def initialize(
|
40
|
-
@aria_label = aria_label
|
74
|
+
def initialize(label:, with_panel: false, **system_arguments)
|
41
75
|
@with_panel = with_panel
|
42
76
|
@system_arguments = system_arguments
|
43
|
-
@system_arguments[:tag] ||= :div
|
44
77
|
|
78
|
+
@system_arguments[:tag] ||= :div
|
45
79
|
@system_arguments[:classes] = class_names(
|
46
80
|
"tabnav",
|
47
81
|
system_arguments[:classes]
|
48
82
|
)
|
49
|
-
end
|
50
|
-
|
51
|
-
def before_render
|
52
|
-
validate_single_selected_tab
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def wrapper
|
58
|
-
@with_panel ? Primer::TabContainerComponent : Primer::BaseComponent
|
59
|
-
end
|
60
|
-
|
61
|
-
def validate_single_selected_tab
|
62
|
-
raise MultipleSelectedTabsError, "only one tab can be selected" if selected_tabs_count > 1
|
63
|
-
raise NoSelectedTabsError, "a tab must be selected" if selected_tabs_count != 1
|
64
|
-
end
|
65
|
-
|
66
|
-
def selected_tabs_count
|
67
|
-
@selected_tabs_count ||= tabs.count(&:selected)
|
68
|
-
end
|
69
|
-
|
70
|
-
# Tabs to be rendered.
|
71
|
-
class TabComponent < Primer::Component
|
72
|
-
attr_reader :selected
|
73
|
-
|
74
|
-
def initialize(title:, selected: false, **system_arguments)
|
75
|
-
@title = title
|
76
|
-
@selected = selected
|
77
|
-
@system_arguments = system_arguments
|
78
|
-
@system_arguments[:tag] ||= :a
|
79
|
-
@system_arguments[:role] = :tab
|
80
|
-
|
81
|
-
if selected
|
82
|
-
if @system_arguments[:tag] == :a
|
83
|
-
@system_arguments[:"aria-current"] = :page
|
84
|
-
else
|
85
|
-
@system_arguments[:"aria-selected"] = true
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
@system_arguments[:classes] = class_names(
|
90
|
-
"tabnav-tab",
|
91
|
-
system_arguments[:classes]
|
92
|
-
)
|
93
|
-
end
|
94
|
-
|
95
|
-
def call
|
96
|
-
render(Primer::BaseComponent.new(**@system_arguments)) { @title }
|
97
|
-
end
|
98
83
|
|
99
|
-
|
100
|
-
|
101
|
-
|
84
|
+
@body_arguments = {
|
85
|
+
tag: navigation_tag(with_panel),
|
86
|
+
classes: "tabnav-tabs",
|
87
|
+
aria: {
|
88
|
+
label: label
|
89
|
+
}
|
90
|
+
}
|
102
91
|
|
103
|
-
|
104
|
-
!@selected
|
105
|
-
end
|
92
|
+
@body_arguments[:role] = :tablist if @with_panel
|
106
93
|
end
|
107
94
|
end
|
108
95
|
end
|
@@ -3,7 +3,8 @@
|
|
3
3
|
module Primer
|
4
4
|
# Use Primer::TimeAgoComponent to display a time relative to how long ago it was. This component requires JavaScript.
|
5
5
|
class TimeAgoComponent < Primer::Component
|
6
|
-
|
6
|
+
status :beta
|
7
|
+
|
7
8
|
# @example Default
|
8
9
|
# <%= render(Primer::TimeAgoComponent.new(time: Time.at(628232400))) %>
|
9
10
|
#
|
@@ -3,7 +3,6 @@
|
|
3
3
|
module Primer
|
4
4
|
# Use `TimelineItem` to display items on a vertical timeline, connected by badge elements.
|
5
5
|
class TimelineItemComponent < Primer::Component
|
6
|
-
include ViewComponent::SlotableV2
|
7
6
|
status :beta
|
8
7
|
|
9
8
|
# Avatar to be rendered to the left of the Badge.
|
@@ -78,7 +77,7 @@ module Primer
|
|
78
77
|
|
79
78
|
def call
|
80
79
|
render(Primer::BaseComponent.new(**@system_arguments)) do
|
81
|
-
render(Primer::OcticonComponent.new(
|
80
|
+
render(Primer::OcticonComponent.new(@icon))
|
82
81
|
end
|
83
82
|
end
|
84
83
|
end
|
@@ -1,11 +1,23 @@
|
|
1
|
-
<%=
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
<%= wrapper do %>
|
2
|
+
<%= render Primer::BaseComponent.new(**@system_arguments) do %>
|
3
|
+
<% if @align == :right %>
|
4
|
+
<%= actions %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<%= render body do %>
|
8
|
+
<% tabs.each do |tab| %>
|
9
|
+
<%= tab %>
|
10
|
+
<% end %>
|
11
|
+
<% end %>
|
5
12
|
|
6
|
-
|
13
|
+
<% if @align == :left %>
|
14
|
+
<%= actions %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
7
17
|
|
8
|
-
<% if @
|
9
|
-
|
18
|
+
<% if @with_panel %>
|
19
|
+
<% tabs.each do |tab| %>
|
20
|
+
<%= tab.panel %>
|
21
|
+
<% end %>
|
10
22
|
<% end %>
|
11
23
|
<% end %>
|
@@ -5,34 +5,66 @@ module Primer
|
|
5
5
|
# underlined selected state, typically used for navigation placed at the top
|
6
6
|
# of the page.
|
7
7
|
class UnderlineNavComponent < Primer::Component
|
8
|
-
include
|
8
|
+
include Primer::TabbedComponentHelper
|
9
9
|
|
10
10
|
ALIGN_DEFAULT = :left
|
11
11
|
ALIGN_OPTIONS = [ALIGN_DEFAULT, :right].freeze
|
12
12
|
|
13
|
-
|
13
|
+
BODY_TAG_DEFAULT = :div
|
14
|
+
BODY_TAG_OPTIONS = [BODY_TAG_DEFAULT, :ul].freeze
|
15
|
+
|
16
|
+
# Use the tabs to list navigation items. For more information, refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
|
14
17
|
#
|
18
|
+
# @param selected [Boolean] Whether the tab is selected.
|
15
19
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
16
|
-
|
17
|
-
system_arguments[:classes] = class_names(
|
18
|
-
|
20
|
+
renders_many :tabs, lambda { |selected: false, **system_arguments|
|
21
|
+
system_arguments[:classes] = class_names(
|
22
|
+
"UnderlineNav-item",
|
23
|
+
system_arguments[:classes]
|
24
|
+
)
|
19
25
|
|
20
|
-
Primer::
|
26
|
+
Primer::Navigation::TabComponent.new(
|
27
|
+
list: list?,
|
28
|
+
selected: selected,
|
29
|
+
with_panel: @with_panel,
|
30
|
+
icon_classes: "UnderlineNav-octicon",
|
31
|
+
**system_arguments
|
32
|
+
)
|
21
33
|
}
|
22
34
|
|
23
|
-
#
|
35
|
+
# Use actions for a call to action.
|
24
36
|
#
|
25
37
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
26
38
|
renders_one :actions, lambda { |**system_arguments|
|
27
39
|
system_arguments[:tag] ||= :div
|
28
40
|
system_arguments[:classes] = class_names("UnderlineNav-actions", system_arguments[:classes])
|
29
|
-
|
41
|
+
|
42
|
+
Primer::BaseComponent.new(**system_arguments)
|
30
43
|
}
|
31
44
|
|
32
45
|
# @example Default
|
33
|
-
# <%= render(Primer::UnderlineNavComponent.new) do |component| %>
|
34
|
-
# <% component.
|
35
|
-
#
|
46
|
+
# <%= render(Primer::UnderlineNavComponent.new(label: "Default")) do |component| %>
|
47
|
+
# <% component.tab(href: "#", selected: true) { "Item 1" } %>
|
48
|
+
# <% component.tab(href: "#") { "Item 2" } %>
|
49
|
+
# <% component.actions do %>
|
50
|
+
# <%= render(Primer::ButtonComponent.new) { "Button!" } %>
|
51
|
+
# <% end %>
|
52
|
+
# <% end %>
|
53
|
+
#
|
54
|
+
# @example With icons and counters
|
55
|
+
# <%= render(Primer::UnderlineNavComponent.new(label: "With icons and counters")) do |component| %>
|
56
|
+
# <% component.tab(href: "#", selected: true) do |t| %>
|
57
|
+
# <% t.icon(icon: :star) %>
|
58
|
+
# <% t.text { "Item 1" } %>
|
59
|
+
# <% end %>
|
60
|
+
# <% component.tab(href: "#") do |t| %>
|
61
|
+
# <% t.icon(icon: :star) %>
|
62
|
+
# <% t.text { "Item 2" } %>
|
63
|
+
# <% t.counter(count: 10) %>
|
64
|
+
# <% end %>
|
65
|
+
# <% component.tab(href: "#") do |t| %>
|
66
|
+
# <% t.text { "Item 3" } %>
|
67
|
+
# <% t.counter(count: 10) %>
|
36
68
|
# <% end %>
|
37
69
|
# <% component.actions do %>
|
38
70
|
# <%= render(Primer::ButtonComponent.new) { "Button!" } %>
|
@@ -40,27 +72,93 @@ module Primer
|
|
40
72
|
# <% end %>
|
41
73
|
#
|
42
74
|
# @example Align right
|
43
|
-
# <%= render(Primer::UnderlineNavComponent.new(align: :right)) do |component| %>
|
44
|
-
# <% component.
|
45
|
-
#
|
75
|
+
# <%= render(Primer::UnderlineNavComponent.new(label: "Align right", align: :right)) do |component| %>
|
76
|
+
# <% component.tab(href: "#", selected: true) do |t| %>
|
77
|
+
# <% t.text { "Item 1" } %>
|
78
|
+
# <% end %>
|
79
|
+
# <% component.tab(href: "#") do |t| %>
|
80
|
+
# <% t.text { "Item 2" } %>
|
46
81
|
# <% end %>
|
47
82
|
# <% component.actions do %>
|
48
83
|
# <%= render(Primer::ButtonComponent.new) { "Button!" } %>
|
49
84
|
# <% end %>
|
50
85
|
# <% end %>
|
51
86
|
#
|
87
|
+
# @example As a list
|
88
|
+
# <%= render(Primer::UnderlineNavComponent.new(label: "As a list", body_arguments: { tag: :ul })) do |component| %>
|
89
|
+
# <% component.tab(href: "#", selected: true) do |t| %>
|
90
|
+
# <% t.text { "Item 1" } %>
|
91
|
+
# <% end %>
|
92
|
+
# <% component.tab(href: "#") do |t| %>
|
93
|
+
# <% t.text { "Item 2" } %>
|
94
|
+
# <% end %>
|
95
|
+
# <% component.actions do %>
|
96
|
+
# <%= render(Primer::ButtonComponent.new) { "Button!" } %>
|
97
|
+
# <% end %>
|
98
|
+
# <% end %>
|
99
|
+
#
|
100
|
+
# @example With panels
|
101
|
+
# <%= render(Primer::UnderlineNavComponent.new(label: "With panels", with_panel: true)) do |component| %>
|
102
|
+
# <% component.tab(selected: true) do |t| %>
|
103
|
+
# <% t.text { "Item 1" } %>
|
104
|
+
# <% t.panel do %>
|
105
|
+
# Panel 1
|
106
|
+
# <% end %>
|
107
|
+
# <% end %>
|
108
|
+
# <% component.tab do |t| %>
|
109
|
+
# <% t.text { "Item 2" } %>
|
110
|
+
# <% t.panel do %>
|
111
|
+
# Panel 2
|
112
|
+
# <% end %>
|
113
|
+
# <% end %>
|
114
|
+
# <% component.actions do %>
|
115
|
+
# <%= render(Primer::ButtonComponent.new) { "Button!" } %>
|
116
|
+
# <% end %>
|
117
|
+
# <% end %>
|
118
|
+
#
|
119
|
+
# @param label [String] The `aria-label` on top level `<nav>` element.
|
120
|
+
# @param with_panel [Boolean] Whether the TabNav should navigate through pages or panels.
|
52
121
|
# @param align [Symbol] <%= one_of(Primer::UnderlineNavComponent::ALIGN_OPTIONS) %> - Defaults to <%= Primer::UnderlineNavComponent::ALIGN_DEFAULT %>
|
122
|
+
# @param body_arguments [Hash] <%= link_to_system_arguments_docs %> for the body wrapper.
|
53
123
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
54
|
-
def initialize(align: ALIGN_DEFAULT, **system_arguments)
|
124
|
+
def initialize(label:, with_panel: false, align: ALIGN_DEFAULT, body_arguments: { tag: BODY_TAG_DEFAULT }, **system_arguments)
|
125
|
+
@with_panel = with_panel
|
55
126
|
@align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
|
56
127
|
|
57
128
|
@system_arguments = system_arguments
|
58
|
-
@system_arguments[:tag] =
|
129
|
+
@system_arguments[:tag] = navigation_tag(with_panel)
|
59
130
|
@system_arguments[:classes] = class_names(
|
60
131
|
@system_arguments[:classes],
|
61
132
|
"UnderlineNav",
|
62
133
|
"UnderlineNav--right" => @align == :right
|
63
134
|
)
|
135
|
+
|
136
|
+
@body_arguments = body_arguments
|
137
|
+
@body_tag = fetch_or_fallback(BODY_TAG_OPTIONS, body_arguments[:tag]&.to_sym, BODY_TAG_DEFAULT)
|
138
|
+
|
139
|
+
@body_arguments[:tag] = @body_tag
|
140
|
+
@body_arguments[:classes] = class_names(
|
141
|
+
"UnderlineNav-body",
|
142
|
+
@body_arguments[:classes],
|
143
|
+
"list-style-none" => list?
|
144
|
+
)
|
145
|
+
|
146
|
+
if with_panel
|
147
|
+
@body_arguments[:role] = :tablist
|
148
|
+
@body_arguments[:"aria-label"] = label
|
149
|
+
else
|
150
|
+
@system_arguments[:"aria-label"] = label
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
def list?
|
157
|
+
@body_tag == :ul
|
158
|
+
end
|
159
|
+
|
160
|
+
def body
|
161
|
+
Primer::BaseComponent.new(**@body_arguments)
|
64
162
|
end
|
65
163
|
end
|
66
164
|
end
|