primer_view_components 0.0.47 → 0.0.48

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1b0ba62c9f5f11df09d24b40ca5e61e7d618046aba651ad733c8db06c482fe26
4
- data.tar.gz: 34c0b8066b85d5392dd241baeb3b654ba47d7de1f360b793ac893750989d99dd
3
+ metadata.gz: 2c751bc60362c19e97ba5fbe22227e19186efa799862932a6f7b8541ad8e1eaa
4
+ data.tar.gz: 4efd584159e4883f8bcc72954fff356c753b0b8980056ee0c58b7a3bd650cb90
5
5
  SHA512:
6
- metadata.gz: 47e1bca34582e4406fcc268ac786a322cc3f99a62789aeece262b91e1ca26a15c145835ad60afbcd85a13b3a37da7a54541aedf8e2af5b60c43d7d6cf6767072
7
- data.tar.gz: 2edfb035e82896ea22bec576a98b34eb2e3c18cccf2d3ba18744f7b77135f6a1310b466179025c216d396708fdf5fbe802a2dc436c57d1510632eb9567776df1
6
+ metadata.gz: c6169f90241d046f9cee4faf1fb971cac34360c8ebb116e2c2e39fdd0aeff5e8cca17e899bdd8a97f94ebefa4c3705d6929b0978a96f0264dcab3fa96342faaf
7
+ data.tar.gz: 8576857a521647f43ccb3fe413b0e24b5d65a8c06e9036dd3035b37d8fb5989aa43a7ac2d33863f5faa022c099c6a8386d30de8b764e19cf93b9dcb207fd4eef
data/CHANGELOG.md CHANGED
@@ -30,6 +30,24 @@ The category for changes related to documentation, testing and tooling. Also, fo
30
30
 
31
31
  ## main
32
32
 
33
+ ## 0.0.48
34
+
35
+ ### Breaking changes
36
+
37
+ * Ensure panels in `Navigation::Tab` have a label.
38
+
39
+ *Kate Higa*
40
+
41
+ ### Misc
42
+
43
+ * Expose custom cops and default config for erblint.
44
+
45
+ *Manuel Puyol*
46
+
47
+ * Fix double constant assign.
48
+
49
+ *Manuel Puyol*
50
+
33
51
  ## 0.0.47
34
52
 
35
53
  ### Breaking changes
@@ -12,7 +12,7 @@ module Primer
12
12
  TAG_OPTIONS = [DEFAULT_TAG, :span].freeze
13
13
 
14
14
  DEFAULT_BODY_TAG = :div
15
- BODY_TAG_OPTIONS = TAG_OPTIONS = [DEFAULT_TAG, :span].freeze
15
+ BODY_TAG_OPTIONS = [DEFAULT_BODY_TAG, :span].freeze
16
16
  # Required list of stacked avatars.
17
17
  #
18
18
  # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::Beta::Avatar) %>.
@@ -29,7 +29,7 @@ module Primer
29
29
  # @param type [Symbol] <%= one_of(Primer::Beta::AutoComplete::Input::TYPE_OPTIONS) %>
30
30
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
31
31
  renders_one :input, lambda { |**system_arguments|
32
- aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label) || @aria_label
32
+ aria_label = aria("label", system_arguments) || @aria_label
33
33
  if aria_label.present?
34
34
  system_arguments[:"aria-label"] = aria_label
35
35
  system_arguments[:aria]&.delete(:label)
@@ -106,7 +106,7 @@ module Primer
106
106
  def initialize(src:, list_id:, input_id:, **system_arguments)
107
107
  @list_id = list_id
108
108
  @input_id = input_id
109
- @aria_label = system_arguments[:"aria-label"] || system_arguments.dig(:aria, :label)
109
+ @aria_label = aria("label", system_arguments)
110
110
 
111
111
  system_arguments.delete(:"aria-label") && system_arguments[:aria]&.delete(:label)
112
112
 
@@ -29,8 +29,12 @@ module Primer
29
29
  ActiveSupport::Deprecation.warn(message)
30
30
  end
31
31
 
32
+ def aria(val, system_arguments)
33
+ system_arguments[:"aria-#{val}"] || system_arguments.dig(:aria, val.to_sym)
34
+ end
35
+
32
36
  def validate_aria_label
33
- aria_label = @system_arguments[:"aria-label"] || @system_arguments.dig(:aria, :label)
37
+ aria_label = aria("label", @system_arguments)
34
38
  raise ArgumentError, "`aria-label` is required." if aria_label.nil? && !Rails.env.production?
35
39
  end
36
40
 
@@ -18,10 +18,22 @@ module Primer
18
18
  #
19
19
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
20
20
  renders_one :panel, lambda { |**system_arguments|
21
+ return unless @with_panel
22
+
21
23
  system_arguments[:tag] = :div
22
24
  system_arguments[:role] ||= :tabpanel
25
+ system_arguments[:tabindex] = 0
23
26
  system_arguments[:hidden] = true unless @selected
24
27
 
28
+ label_present = aria("label", system_arguments) || aria("labelledby", system_arguments)
29
+ unless label_present
30
+ if @id.present?
31
+ system_arguments[:"aria-labelledby"] = @id
32
+ elsif !Rails.env.production?
33
+ raise ArgumentError, "Panels must be labelled. Either set a unique `id` on the tab, or set an `aria-label` directly on the panel"
34
+ end
35
+ end
36
+
25
37
  Primer::BaseComponent.new(**system_arguments)
26
38
  }
27
39
 
@@ -93,8 +105,10 @@ module Primer
93
105
  @selected = selected
94
106
  @icon_classes = icon_classes
95
107
  @list = list
108
+ @with_panel = with_panel
96
109
 
97
110
  @system_arguments = system_arguments
111
+ @id = @system_arguments[:id]
98
112
 
99
113
  if with_panel || @system_arguments[:tag] == :button
100
114
  @system_arguments[:tag] = :button
@@ -111,7 +125,7 @@ module Primer
111
125
  return unless @selected
112
126
 
113
127
  if @system_arguments[:tag] == :a
114
- aria_current = @system_arguments[:"aria-current"] || @system_arguments.dig(:aria, :current) || DEFAULT_ARIA_CURRENT_FOR_ANCHOR
128
+ aria_current = aria("current", system_arguments) || DEFAULT_ARIA_CURRENT_FOR_ANCHOR
115
129
  @system_arguments[:"aria-current"] = fetch_or_fallback(ARIA_CURRENT_OPTIONS_FOR_ANCHOR, aria_current, DEFAULT_ARIA_CURRENT_FOR_ANCHOR)
116
130
  else
117
131
  @system_arguments[:"aria-selected"] = true
@@ -63,19 +63,19 @@ module Primer
63
63
  #
64
64
  # @example With panels
65
65
  # <%= render(Primer::TabNavComponent.new(label: "With panels", with_panel: true)) do |c| %>
66
- # <% c.tab(selected: true) do |t| %>
66
+ # <% c.tab(selected: true, id: "tab-1") do |t| %>
67
67
  # <% t.text { "Tab 1" } %>
68
68
  # <% t.panel do %>
69
69
  # Panel 1
70
70
  # <% end %>
71
71
  # <% end %>
72
- # <% c.tab do |t| %>
72
+ # <% c.tab(id: "tab-2") do |t| %>
73
73
  # <% t.text { "Tab 2" } %>
74
74
  # <% t.panel do %>
75
75
  # Panel 2
76
76
  # <% end %>
77
77
  # <% end %>
78
- # <% c.tab do |t| %>
78
+ # <% c.tab(id: "tab-3") do |t| %>
79
79
  # <% t.text { "Tab 3" } %>
80
80
  # <% t.panel do %>
81
81
  # Panel 3
@@ -104,13 +104,13 @@ module Primer
104
104
  #
105
105
  # @example With panels
106
106
  # <%= render(Primer::UnderlineNavComponent.new(label: "With panels", with_panel: true)) do |component| %>
107
- # <% component.tab(selected: true) do |t| %>
107
+ # <% component.tab(selected: true, id: "tab-1") do |t| %>
108
108
  # <% t.text { "Item 1" } %>
109
109
  # <% t.panel do %>
110
110
  # Panel 1
111
111
  # <% end %>
112
112
  # <% end %>
113
- # <% component.tab do |t| %>
113
+ # <% component.tab(id: "tab-2") do |t| %>
114
114
  # <% t.text { "Item 2" } %>
115
115
  # <% t.panel do %>
116
116
  # Panel 2
@@ -5,7 +5,7 @@ module Primer
5
5
  module VERSION
6
6
  MAJOR = 0
7
7
  MINOR = 0
8
- PATCH = 47
8
+ PATCH = 48
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
@@ -0,0 +1,12 @@
1
+ require:
2
+ - rubocop/cop/primer
3
+
4
+ AllCops:
5
+ DisabledByDefault: true
6
+
7
+ Primer/SystemArgumentInsteadOfClass:
8
+ Enabled: true
9
+
10
+ Primer/NoTagMemoize:
11
+ Enabled: false
12
+
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop/cop/primer/no_tag_memoize"
4
+ require "rubocop/cop/primer/system_argument_instead_of_class"
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+
5
+ module RuboCop
6
+ module Cop
7
+ module Primer
8
+ # This cop ensures that tags are not set with ||=
9
+ #
10
+ # bad
11
+ # @system_arguments[:tag] ||= :h1
12
+ #
13
+ # good
14
+ # @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, DEFAULT_TAG)
15
+ #
16
+ # good
17
+ # @system_arguments[:tag] = :h2
18
+ class NoTagMemoize < RuboCop::Cop::Cop
19
+ INVALID_MESSAGE = <<~STR
20
+ Avoid `[:tag] ||=`. Instead, try one of the following:
21
+ - Don't allow consumers to update the tag by having a fixed tag (e.g. `system_arguments[:tag] = :div`)
22
+ - Use the `fetch_or_fallback` helper to only allow a tag from a restricted list.
23
+ STR
24
+
25
+ def_node_search :tag_memoized?, <<~PATTERN
26
+ (or-asgn
27
+ (send
28
+ _
29
+ _
30
+ (sym :tag)
31
+ )
32
+ _
33
+ )
34
+ PATTERN
35
+
36
+ def on_or_asgn(node)
37
+ add_offense(node, message: INVALID_MESSAGE) if tag_memoized?(node)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rubocop"
4
+ require "primer/classify/utilities"
5
+ require "primer/view_components/statuses"
6
+
7
+ module RuboCop
8
+ module Cop
9
+ module Primer
10
+ # This cop ensures that components use System Arguments instead of CSS classes.
11
+ #
12
+ # bad
13
+ # Component.new(classes: "mr-1")
14
+ #
15
+ # good
16
+ # Component.new(mr: 1)
17
+ class SystemArgumentInsteadOfClass < RuboCop::Cop::Cop
18
+ INVALID_MESSAGE = <<~STR
19
+ Avoid using CSS classes when you can use System Arguments: https://primer.style/view-components/system-arguments.
20
+ STR
21
+
22
+ def on_send(node)
23
+ return unless node.method_name == :new
24
+ return unless ::Primer::ViewComponents::STATUSES.key?(node.receiver.const_name)
25
+ return unless node.arguments?
26
+
27
+ # we are looking for hash arguments and they are always last
28
+ kwargs = node.arguments.last
29
+
30
+ return unless kwargs.type == :hash
31
+
32
+ # find classes pair
33
+ classes_arg = kwargs.pairs.find { |kwarg| kwarg.key.value == :classes }
34
+
35
+ return if classes_arg.nil?
36
+ return unless classes_arg.value.type == :str
37
+
38
+ # get actual classes
39
+ classes = classes_arg.value.value
40
+
41
+ system_arguments = ::Primer::Classify::Utilities.classes_to_hash(classes)
42
+
43
+ # no classes are fixable
44
+ return if system_arguments[:classes] == classes
45
+
46
+ add_offense(classes_arg, message: INVALID_MESSAGE)
47
+ end
48
+
49
+ def autocorrect(node)
50
+ lambda do |corrector|
51
+ system_arguments = ::Primer::Classify::Utilities.classes_to_hash(node.value.value)
52
+ corrector.replace(node.loc.expression, arguments_as_string(system_arguments))
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def arguments_as_string(system_arguments)
59
+ system_arguments.map do |key, value|
60
+ val = case value
61
+ when Symbol
62
+ ":#{value}"
63
+ when String
64
+ value.to_json
65
+ else
66
+ value
67
+ end
68
+
69
+ "#{key}: #{val}"
70
+ end.join(", ")
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: primer_view_components
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.47
4
+ version: 0.0.48
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitHub Open Source
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-20 00:00:00.000000000 Z
11
+ date: 2021-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
@@ -487,6 +487,10 @@ files:
487
487
  - lib/primer/view_components/linters/helpers.rb
488
488
  - lib/primer/view_components/statuses.rb
489
489
  - lib/primer/view_components/version.rb
490
+ - lib/rubocop/config/default.yml
491
+ - lib/rubocop/cop/primer.rb
492
+ - lib/rubocop/cop/primer/no_tag_memoize.rb
493
+ - lib/rubocop/cop/primer/system_argument_instead_of_class.rb
490
494
  - lib/tasks/coverage.rake
491
495
  - lib/tasks/docs.rake
492
496
  - lib/tasks/statuses.rake