primer_view_components 0.0.54 → 0.0.55

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/app/components/primer/alpha/tab_nav.html.erb +11 -0
  4. data/app/components/primer/alpha/tab_nav.rb +130 -0
  5. data/app/components/primer/{tab_nav_component.html.erb → alpha/tab_panels.html.erb} +3 -8
  6. data/app/components/primer/alpha/tab_panels.rb +82 -0
  7. data/app/components/primer/alpha/underline_nav.rb +1 -7
  8. data/app/components/primer/alpha/underline_panels.html.erb +1 -1
  9. data/app/components/primer/base_component.rb +1 -1
  10. data/app/components/primer/beta/breadcrumbs.html.erb +2 -1
  11. data/app/components/primer/beta/breadcrumbs.rb +15 -13
  12. data/app/components/primer/navigation/tab_component.rb +2 -2
  13. data/app/components/primer/octicon_component.rb +6 -1
  14. data/app/components/primer/tab_container_component.rb +1 -1
  15. data/app/lib/primer/class_name_helper.rb +14 -13
  16. data/app/lib/primer/octicon/cache.rb +10 -2
  17. data/app/lib/primer/tab_nav_helper.rb +35 -0
  18. data/app/lib/primer/tabbed_component_helper.rb +3 -3
  19. data/lib/primer/classify/cache.rb +0 -6
  20. data/lib/primer/classify/utilities.rb +1 -1
  21. data/lib/primer/classify/utilities.yml +35 -0
  22. data/lib/primer/classify.rb +0 -5
  23. data/lib/primer/view_components/version.rb +1 -1
  24. data/lib/rubocop/cop/primer/base_cop.rb +28 -0
  25. data/lib/rubocop/cop/primer/deprecated_arguments.rb +1 -15
  26. data/lib/rubocop/cop/primer/system_argument_instead_of_class.rb +1 -15
  27. data/lib/tasks/docs.rake +5 -5
  28. data/lib/tasks/utilities.rake +2 -0
  29. data/static/arguments.yml +29 -36
  30. data/static/classes.yml +1 -0
  31. data/static/constants.json +16 -17
  32. data/static/statuses.json +2 -1
  33. metadata +22 -5
  34. data/app/components/primer/tab_nav_component.rb +0 -151
  35. data/lib/primer/classify/functional_text_colors.rb +0 -64
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c9b70049a9f24586f7b1239cdd97832cb9e813cc063ca475c77ae00ed448a6c4
4
- data.tar.gz: 8df167c58fa86039a008d301969af68f7efa8e4345d49abf269cb09734ec1841
3
+ metadata.gz: 24d9b6954280f4366b91f69fe7d29af41b8ce480b015a6d2f281c9e6c3bd4637
4
+ data.tar.gz: cae48c352697db57fd18b2712850cdc5a47da809449dcbd1f32398a777135cda
5
5
  SHA512:
6
- metadata.gz: 7c87327784f69a03b4636e2952c98da1feb4b5c47776c8e46cd423ae562d25aa061c99f0ff3ebee605984816db3b3c6209fd7ddb5ed0577a1ed7b1ff8a68bbc8
7
- data.tar.gz: c386eb3940ee79d8992b45168e18846863c6d503801674d13efe6ea8617cfc9d7a3957e3e324959c884d13bdd66113188ea23c9bcbf9dce00ff9eb54ce0deef3
6
+ metadata.gz: e334ce2c9e71f8b54f0a22d094a333ce1df7216a601885732c2a1f669e03d67f4b0e2d9799c39600edc33e9ef972949a02de1a8adc4081c702b14d4bfe6bacbc
7
+ data.tar.gz: 4640a31794a5e6df77bcf1a707758bb970d80a33afbcd42a812efd3ce3c9f032b7789de55f3ab0d74d7d8657c1d06f3965f926437cf609455f3db4b2c4a2bc6f
data/CHANGELOG.md CHANGED
@@ -30,6 +30,39 @@ The category for changes related to documentation, testing and tooling. Also, fo
30
30
 
31
31
  ## main
32
32
 
33
+ ## 0.0.55
34
+
35
+ ### Breaking changes
36
+
37
+ * `Primer::Breadcrumbs` requires `href`s for all items and no longer accepts the `selected` argument.
38
+
39
+ *Joel Hawksley*
40
+
41
+ * Split `TabNav` into `TabNav` and `TabPanels`.
42
+
43
+ *Kate Higa*
44
+
45
+ ### New
46
+
47
+ * Use the allocation_stats gem to count object allocations in our benchmarks.
48
+ * Improve performance of Octicon cache key construction.
49
+
50
+ *Cameron Dutro*
51
+
52
+ * Update `@primer/css` to `17.7.0` which includes a new argument for `word_break`
53
+
54
+ *Jon Rohan*
55
+
56
+ ### Misc
57
+
58
+ * Clean up extra constants in `UnderlineNav`.
59
+
60
+ *Kate Higa*
61
+
62
+ * Refactor some of the rubocop valid_node? logic into BaseCop class.
63
+
64
+ *Jon Rohan*
65
+
33
66
  ## 0.0.54
34
67
 
35
68
  ### Breaking changes
@@ -68,6 +101,10 @@ The category for changes related to documentation, testing and tooling. Also, fo
68
101
 
69
102
  *Manuel Puyol*
70
103
 
104
+ * Moving text color variables to Utilities class
105
+
106
+ *Jon Rohan*
107
+
71
108
  ### Bug fixes
72
109
 
73
110
  * Linters won't convert HTML special elements.
@@ -0,0 +1,11 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <%= extra if @align == :left %>
3
+
4
+ <%= render Primer::BaseComponent.new(**@body_arguments) do %>
5
+ <% tabs.each do |tab| %>
6
+ <%= tab %>
7
+ <% end %>
8
+ <% end %>
9
+
10
+ <%= extra if @align == :right %>
11
+ <% end %>
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ # Use `TabNav` to style navigation with a tab-based selected state, typically used for navigation placed at the top of the page.
6
+ # For panel navigation, use <%= link_to_component(Primer::Alpha::TabPanels) %> instead.
7
+ #
8
+ # @accessibility
9
+ # - By default, `TabNav` renders links within a `<nav>` element. `<nav>` has an
10
+ # implicit landmark role of `navigation` which should be reserved for main links.
11
+ # For all other set of links, set tag to `:div`.
12
+ # - See <%= link_to_component(Primer::Navigation::TabComponent) %> for additional
13
+ # accessibility considerations.
14
+ class TabNav < Primer::Component
15
+ include Primer::TabbedComponentHelper
16
+ include Primer::TabNavHelper
17
+
18
+ status :alpha
19
+
20
+ BODY_TAG_DEFAULT = :ul
21
+
22
+ TAG_DEFAULT = :nav
23
+ TAG_OPTIONS = [TAG_DEFAULT, :div].freeze
24
+
25
+ # Tabs to be rendered. For more information, refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
26
+ #
27
+ # @param selected [Boolean] Whether the tab is selected.
28
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
29
+ renders_many :tabs, lambda { |selected: false, **system_arguments|
30
+ system_arguments[:classes] = tab_nav_tab_classes(system_arguments[:classes])
31
+ Primer::Navigation::TabComponent.new(
32
+ list: true,
33
+ selected: selected,
34
+ **system_arguments
35
+ )
36
+ }
37
+
38
+ # Renders extra content to the `TabNav`. This will be rendered after the tabs.
39
+ #
40
+ # @param align [Symbol] <%= one_of(Primer::Alpha::TabNav::EXTRA_ALIGN_OPTIONS) %>
41
+ renders_one :extra, lambda { |align: EXTRA_ALIGN_DEFAULT, &block|
42
+ @align = fetch_or_fallback(EXTRA_ALIGN_OPTIONS, align, EXTRA_ALIGN_DEFAULT)
43
+
44
+ view_context.capture { block&.call }
45
+ }
46
+
47
+ # @example Default with `<nav>`
48
+ # @description
49
+ # `<nav>` is a landmark and should be reserved for main navigation links. See <%= link_to_accessibility %>.
50
+ # @code
51
+ # <%= render(Primer::Alpha::TabNav.new(label: "Default")) do |c| %>
52
+ # <% c.tab(selected: true, href: "#") { "Tab 1" } %>
53
+ # <% c.tab(href: "#") { "Tab 2" } %>
54
+ # <% c.tab(href: "#") { "Tab 3" } %>
55
+ # <% end %>
56
+ #
57
+ # @example Default with `<div>`
58
+ # <%= render(Primer::Alpha::TabNav.new(label: "Default")) do |c| %>
59
+ # <% c.tab(selected: true, href: "#") { "Tab 1" } %>
60
+ # <% c.tab(href: "#") { "Tab 2" } %>
61
+ # <% c.tab(href: "#") { "Tab 3" } %>
62
+ # <% end %>
63
+ #
64
+ # @example With icons and counters
65
+ # <%= render(Primer::Alpha::TabNav.new(label: "With icons and counters")) do |component| %>
66
+ # <% component.tab(href: "#", selected: true) do |t| %>
67
+ # <% t.icon(icon: :star) %>
68
+ # <% t.text { "Item 1" } %>
69
+ # <% end %>
70
+ # <% component.tab(href: "#") do |t| %>
71
+ # <% t.icon(icon: :star) %>
72
+ # <% t.text { "Item 2" } %>
73
+ # <% t.counter(count: 10) %>
74
+ # <% end %>
75
+ # <% component.tab(href: "#") do |t| %>
76
+ # <% t.text { "Item 3" } %>
77
+ # <% t.counter(count: 10) %>
78
+ # <% end %>
79
+ # <% end %>
80
+ #
81
+ # @example With extra content
82
+ # <%= render(Primer::Alpha::TabNav.new(label: "With extra content")) do |c| %>
83
+ # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
84
+ # <% c.tab(href: "#") { "Tab 2" } %>
85
+ # <% c.tab(href: "#") { "Tab 3" } %>
86
+ # <% c.extra do %>
87
+ # <%= render(Primer::ButtonComponent.new(float: :right)) { "Button" } %>
88
+ # <% end %>
89
+ # <% end %>
90
+ #
91
+ # @example Adding extra content after the tabs
92
+ # <%= render(Primer::Alpha::TabNav.new(label: "Adding extra content after the tabs", display: :flex, body_arguments: { flex: 1 })) do |c| %>
93
+ # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
94
+ # <% c.tab(href: "#") { "Tab 2" } %>
95
+ # <% c.tab(href: "#") { "Tab 3" } %>
96
+ # <% c.extra(align: :right) do %>
97
+ # <div>
98
+ # <%= render(Primer::ButtonComponent.new) { "Button" } %>
99
+ # </div>
100
+ # <% end %>
101
+ # <% end %>
102
+ #
103
+ # @example Customizing the body
104
+ # <%= render(Primer::Alpha::TabNav.new(label: "Default", body_arguments: { classes: "custom-class", border: true, border_color: :info })) do |c| %>
105
+ # <% c.tab(selected: true, href: "#") { "Tab 1" }%>
106
+ # <% c.tab(href: "#") { "Tab 2" } %>
107
+ # <% c.tab(href: "#") { "Tab 3" } %>
108
+ # <% end %>
109
+ #
110
+ # @param tag [Symbol] <%= one_of(Primer::Alpha::TabNav::TAG_OPTIONS) %>
111
+ # @param label [String] Sets an `aria-label` that helps assistive technology users understand the purpose of the links, and distinguish it from similar elements.
112
+ # @param body_arguments [Hash] <%= link_to_system_arguments_docs %> for the body wrapper.
113
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
114
+ def initialize(label:, tag: TAG_DEFAULT, body_arguments: {}, **system_arguments)
115
+ @align = EXTRA_ALIGN_DEFAULT
116
+ @system_arguments = system_arguments
117
+ @body_arguments = body_arguments
118
+
119
+ @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, TAG_DEFAULT)
120
+ @system_arguments[:classes] = tab_nav_classes(system_arguments[:classes])
121
+
122
+ @body_arguments = body_arguments
123
+ @body_arguments[:tag] = BODY_TAG_DEFAULT
124
+ @body_arguments[:classes] = tab_nav_body_classes(system_arguments[:classes])
125
+
126
+ aria_label_for_page_nav(label)
127
+ end
128
+ end
129
+ end
130
+ end
@@ -1,19 +1,14 @@
1
- <%= wrapper(with_panel: @with_panel, **@wrapper_arguments) do %>
1
+ <%= tab_container_wrapper(with_panel: true, **@wrapper_arguments) do %>
2
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
3
3
  <%= extra if @align == :left %>
4
-
5
4
  <%= render Primer::BaseComponent.new(**@body_arguments) do %>
6
5
  <% tabs.each do |tab| %>
7
6
  <%= tab %>
8
7
  <% end %>
9
8
  <% end %>
10
-
11
9
  <%= extra if @align == :right %>
12
10
  <% end %>
13
-
14
- <% if @with_panel %>
15
- <% tabs.each do |tab| %>
16
- <%= tab.panel %>
17
- <% end %>
11
+ <% tabs.each do |tab| %>
12
+ <%= tab.panel %>
18
13
  <% end %>
19
14
  <% end %>
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ # Use `TabPanels` for tabs with panel navigation.
6
+ class TabPanels < Primer::Component
7
+ include Primer::TabbedComponentHelper
8
+ include Primer::TabNavHelper
9
+
10
+ status :alpha
11
+
12
+ BODY_TAG_DEFAULT = :ul
13
+
14
+ TAG_DEFAULT = :nav
15
+ TAG_OPTIONS = [TAG_DEFAULT, :div].freeze
16
+
17
+ # Tabs to be rendered. For more information, refer to <%= link_to_component(Primer::Navigation::TabComponent) %>.
18
+ #
19
+ # @param id [String] Unique ID of tab.
20
+ # @param selected [Boolean] Whether the tab is selected.
21
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
22
+ renders_many :tabs, lambda { |id:, selected: false, **system_arguments|
23
+ system_arguments[:id] = id
24
+ system_arguments[:classes] = tab_nav_tab_classes(system_arguments[:classes])
25
+
26
+ Primer::Navigation::TabComponent.new(
27
+ selected: selected,
28
+ with_panel: true,
29
+ list: true,
30
+ panel_id: "panel-#{id}",
31
+ **system_arguments
32
+ )
33
+ }
34
+
35
+ # Renders extra content to the `TabPanels`. This will be rendered after the tabs.
36
+ #
37
+ # @param align [Symbol] <%= one_of(Primer::Alpha::TabNav::EXTRA_ALIGN_OPTIONS) %>
38
+ renders_one :extra, lambda { |align: EXTRA_ALIGN_DEFAULT, &block|
39
+ @align = fetch_or_fallback(EXTRA_ALIGN_OPTIONS, align, EXTRA_ALIGN_DEFAULT)
40
+
41
+ view_context.capture { block&.call }
42
+ }
43
+
44
+ # @example Default
45
+ # <%= render(Primer::Alpha::TabPanels.new(label: "With panels")) do |component| %>
46
+ # <% component.tab(id: "tab-1", selected: true) do |t| %>
47
+ # <% t.text { "Tab 1" } %>
48
+ # <% t.panel do %>
49
+ # Panel 1
50
+ # <% end %>
51
+ # <% end %>
52
+ # <% component.tab(id: "tab-2") do |t| %>
53
+ # <% t.text { "Tab 2" } %>
54
+ # <% t.panel do %>
55
+ # Panel 2
56
+ # <% end %>
57
+ # <% end %>
58
+ # <% end %>
59
+ #
60
+ # @param label [String] Sets an `aria-label` that helps assistive technology users understand the purpose of the tabs.
61
+ # @param align [Symbol] <%= one_of(Primer::TabNavHelper::EXTRA_ALIGN_OPTIONS) %> - Defaults to <%= Primer::TabNavHelper::EXTRA_ALIGN_DEFAULT %>
62
+ # @param body_arguments [Hash] <%= link_to_system_arguments_docs %> for the body wrapper.
63
+ # @param wrapper_arguments [Hash] <%= link_to_system_arguments_docs %> for the `TabContainer` wrapper.
64
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
65
+ def initialize(label:, body_arguments: {}, wrapper_arguments: {}, **system_arguments)
66
+ @align = EXTRA_ALIGN_DEFAULT
67
+ @wrapper_arguments = wrapper_arguments
68
+
69
+ @system_arguments = system_arguments
70
+ @system_arguments[:tag] = :div
71
+ @system_arguments[:classes] = tab_nav_classes(@system_arguments[:classes])
72
+
73
+ @body_arguments = body_arguments
74
+ @body_arguments[:tag] = :ul
75
+ @body_arguments[:classes] = tab_nav_body_classes(@body_arguments[:classes])
76
+
77
+ @body_arguments[:role] = :tablist
78
+ @body_arguments[:"aria-label"] = label
79
+ end
80
+ end
81
+ end
82
+ end
@@ -17,17 +17,11 @@ module Primer
17
17
  include Primer::TabbedComponentHelper
18
18
  include Primer::UnderlineNavHelper
19
19
 
20
- ALIGN_DEFAULT = :left
21
- ALIGN_OPTIONS = [ALIGN_DEFAULT, :right].freeze
22
-
23
20
  BODY_TAG_DEFAULT = :ul
24
21
 
25
22
  TAG_DEFAULT = :nav
26
23
  TAG_OPTIONS = [TAG_DEFAULT, :div].freeze
27
24
 
28
- ACTIONS_TAG_DEFAULT = :div
29
- ACTIONS_TAG_OPTIONS = [ACTIONS_TAG_DEFAULT, :span].freeze
30
-
31
25
  # Use the tabs to list page links.
32
26
  #
33
27
  # @param selected [Boolean] Whether the tab is selected.
@@ -130,7 +124,7 @@ module Primer
130
124
  @body_arguments[:tag] = :ul
131
125
  @body_arguments[:classes] = underline_nav_body_classes(@body_arguments[:classes])
132
126
 
133
- @system_arguments[:tag] == :nav ? @system_arguments[:"aria-label"] = label : @body_arguments[:"aria-label"] = label
127
+ aria_label_for_page_nav(label)
134
128
  end
135
129
 
136
130
  private
@@ -1,4 +1,4 @@
1
- <%= wrapper(with_panel: true, **@wrapper_arguments) do %>
1
+ <%= tab_container_wrapper(with_panel: true, **@wrapper_arguments) do %>
2
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
3
3
  <% if @align == :right %>
4
4
  <%= actions %>
@@ -65,7 +65,7 @@ module Primer
65
65
  # | :- | :- | :- |
66
66
  # | `bg` | String, Symbol | Background color. Accepts either a hex value as a String or <%= one_of(Primer::Classify::FunctionalBackgroundColors::OPTIONS, lower: true) %> |
67
67
  # | `border_color` | Symbol | Border color. <%= one_of(Primer::Classify::FunctionalBorderColors::OPTIONS) %> |
68
- # | `color` | Symbol | Text color. <%= one_of(Primer::Classify::FunctionalTextColors::OPTIONS) %> |
68
+ # | `color` | Symbol | Text color. <%= one_of(Primer::Classify::Utilities.mappings(:color)) %> |
69
69
  #
70
70
  # ## Flex
71
71
  #
@@ -1,6 +1,7 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
2
  <ol>
3
- <% items.each do |item| %>
3
+ <% items.each_with_index do |item, index| %>
4
+ <% item.selected = index == items.length - 1 %>
4
5
  <%= item %>
5
6
  <% end %>
6
7
  </ol>
@@ -2,14 +2,11 @@
2
2
 
3
3
  module Primer
4
4
  module Beta
5
- # Use `Breadcrumb` to display page hierarchy within a section of the site. All of the items in the breadcrumb "trail" are links except for the final item, which is a plain string indicating the current page.
5
+ # Use `Breadcrumbs` to display page hierarchy.
6
6
  class Breadcrumbs < Primer::Component
7
7
  status :beta
8
8
 
9
- # _Note: if both `href` and `selected: true` are passed in, `href` will be ignored and the item will not be rendered as a link._
10
- #
11
9
  # @param href [String] The URL to link to.
12
- # @param selected [Boolean] Whether or not the item is selected and not rendered as a link.
13
10
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
14
11
  renders_many :items, "Item"
15
12
 
@@ -17,7 +14,7 @@ module Primer
17
14
  # <%= render(Primer::Beta::Breadcrumbs.new) do |component| %>
18
15
  # <% component.item(href: "/") do %>Home<% end %>
19
16
  # <% component.item(href: "/about") do %>About<% end %>
20
- # <% component.item(selected: true) do %>Team<% end %>
17
+ # <% component.item(href: "/about/team") do %>Team<% end %>
21
18
  # <% end %>
22
19
  #
23
20
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
@@ -34,23 +31,28 @@ module Primer
34
31
  # This component is part of `Primer::Beta::Breadcrumbs` and should not be
35
32
  # used as a standalone component.
36
33
  class Item < Primer::Component
37
- def initialize(href: nil, selected: false, **system_arguments)
34
+ attr_accessor :selected, :href
35
+
36
+ def initialize(href:, **system_arguments)
38
37
  @href = href
39
38
  @system_arguments = system_arguments
39
+ @selected = false
40
40
 
41
- @href = nil if selected
42
41
  @system_arguments[:tag] = :li
43
- @system_arguments[:"aria-current"] = "page" if selected
44
42
  @system_arguments[:classes] = "breadcrumb-item #{@system_arguments[:classes]}"
45
43
  end
46
44
 
47
45
  def call
46
+ link_arguments = { href: @href }
47
+
48
+ if selected
49
+ link_arguments[:"aria-current"] = "page"
50
+ link_arguments[:classes] = "breadcrumb-item-selected"
51
+ @system_arguments[:classes] = "#{@system_arguments[:classes]} breadcrumb-item-selected"
52
+ end
53
+
48
54
  render(Primer::BaseComponent.new(**@system_arguments)) do
49
- if @href.present?
50
- render(Primer::LinkComponent.new(href: @href)) { content }
51
- else
52
- content
53
- end
55
+ render(Primer::LinkComponent.new(**link_arguments)) { content }
54
56
  end
55
57
  end
56
58
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Primer
4
4
  module Navigation
5
- # This component is part of navigation components such as `Primer::TabNavComponent`
5
+ # This component is part of navigation components such as `Primer::Alpha::TabNav`
6
6
  # and `Primer::Alpha::UnderlineNav` and should not be used by itself.
7
7
  #
8
8
  # @accessibility
@@ -14,7 +14,7 @@ module Primer
14
14
  # Panel controlled by the Tab. This will not render anything in the tab itself.
15
15
  # It will provide a accessor for the Tab's parent to call and render the panel
16
16
  # content in the appropriate place.
17
- # Refer to `UnderlineNav` and `TabNavComponent` implementations for examples.
17
+ # Refer to `UnderlineNav` and `TabNav` implementations for examples.
18
18
  #
19
19
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
20
20
  renders_one :panel, lambda { |**system_arguments|