primer_view_components 0.0.39 → 0.0.44

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +269 -3
  3. data/app/assets/javascripts/primer_view_components.js +1 -1
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  5. data/app/components/primer/alpha/button_marketing.rb +70 -0
  6. data/app/components/primer/auto_complete.rb +99 -41
  7. data/app/components/primer/auto_complete/auto_complete.html.erb +1 -0
  8. data/app/components/primer/avatar_stack_component.rb +7 -4
  9. data/app/components/primer/base_component.rb +17 -7
  10. data/app/components/primer/beta/text.rb +27 -0
  11. data/app/components/primer/blankslate_component.html.erb +1 -0
  12. data/app/components/primer/blankslate_component.rb +68 -49
  13. data/app/components/primer/button_component.rb +3 -2
  14. data/app/components/primer/button_group.rb +2 -2
  15. data/app/components/primer/clipboard_copy_component.js +13 -2
  16. data/app/components/primer/clipboard_copy_component.ts +15 -2
  17. data/app/components/primer/component.rb +6 -1
  18. data/app/components/primer/counter_component.rb +6 -1
  19. data/app/components/primer/details_component.rb +12 -1
  20. data/app/components/primer/dropdown.d.ts +1 -0
  21. data/app/components/primer/{dropdown_component.html.erb → dropdown.html.erb} +2 -1
  22. data/app/components/primer/dropdown.js +1 -0
  23. data/app/components/primer/dropdown.rb +149 -0
  24. data/app/components/primer/dropdown.ts +1 -0
  25. data/app/components/primer/dropdown/menu.d.ts +1 -0
  26. data/app/components/primer/dropdown/menu.html.erb +25 -0
  27. data/app/components/primer/dropdown/menu.js +1 -0
  28. data/app/components/primer/dropdown/menu.rb +99 -0
  29. data/app/components/primer/dropdown/menu.ts +1 -0
  30. data/app/components/primer/flash_component.rb +2 -2
  31. data/app/components/primer/flex_component.rb +27 -0
  32. data/app/components/primer/flex_item_component.rb +1 -1
  33. data/app/components/primer/heading_component.rb +11 -18
  34. data/app/components/primer/hidden_text_expander.rb +3 -3
  35. data/app/components/primer/icon_button.rb +20 -3
  36. data/app/components/primer/image.rb +46 -0
  37. data/app/components/primer/image_crop.d.ts +1 -0
  38. data/app/components/primer/image_crop.html.erb +12 -0
  39. data/app/components/primer/image_crop.js +1 -0
  40. data/app/components/primer/image_crop.rb +36 -0
  41. data/app/components/primer/image_crop.ts +1 -0
  42. data/app/components/primer/label_component.rb +6 -2
  43. data/app/components/primer/local_time.d.ts +1 -0
  44. data/app/components/primer/local_time.js +1 -0
  45. data/app/components/primer/local_time.rb +59 -0
  46. data/app/components/primer/local_time.ts +1 -0
  47. data/app/components/primer/{markdown_component.rb → markdown.rb} +11 -6
  48. data/app/components/primer/navigation/tab_component.rb +10 -3
  49. data/app/components/primer/octicon_component.html.erb +7 -0
  50. data/app/components/primer/octicon_component.rb +25 -15
  51. data/app/components/primer/octicon_symbols_component.html.erb +3 -0
  52. data/app/components/primer/octicon_symbols_component.rb +61 -0
  53. data/app/components/primer/primer.d.ts +3 -0
  54. data/app/components/primer/primer.js +3 -0
  55. data/app/components/primer/primer.ts +3 -0
  56. data/app/components/primer/spinner_component.rb +4 -2
  57. data/app/components/primer/subhead_component.rb +34 -4
  58. data/app/components/primer/tab_nav_component.html.erb +5 -1
  59. data/app/components/primer/tab_nav_component.rb +62 -9
  60. data/app/components/primer/{tooltip_component.rb → tooltip.rb} +10 -8
  61. data/app/components/primer/truncate.rb +6 -2
  62. data/app/components/primer/underline_nav_component.html.erb +1 -1
  63. data/app/components/primer/underline_nav_component.rb +17 -1
  64. data/app/lib/primer/classify.rb +21 -8
  65. data/app/lib/primer/classify/cache.rb +16 -1
  66. data/app/lib/primer/classify/grid.rb +45 -0
  67. data/app/lib/primer/octicon/cache.rb +4 -0
  68. data/app/lib/primer/tabbed_component_helper.rb +2 -2
  69. data/app/lib/primer/view_helper.rb +2 -1
  70. data/lib/primer/view_components.rb +1 -1
  71. data/lib/primer/view_components/engine.rb +2 -0
  72. data/lib/primer/view_components/linters.rb +3 -0
  73. data/lib/primer/view_components/linters/argument_mappers/button.rb +82 -0
  74. data/lib/primer/view_components/linters/argument_mappers/conversion_error.rb +10 -0
  75. data/lib/primer/view_components/linters/argument_mappers/system_arguments.rb +46 -0
  76. data/lib/primer/view_components/linters/button_component_migration_counter.rb +35 -0
  77. data/lib/primer/view_components/linters/flash_component_migration_counter.rb +16 -0
  78. data/lib/primer/view_components/linters/helpers.rb +93 -0
  79. data/lib/primer/view_components/version.rb +1 -1
  80. data/lib/tasks/coverage.rake +14 -0
  81. data/lib/tasks/docs.rake +387 -0
  82. data/lib/tasks/statuses.rake +12 -0
  83. data/lib/yard/docs_helper.rb +67 -0
  84. data/static/statuses.json +56 -1
  85. metadata +72 -13
  86. data/app/components/primer/button_marketing_component.rb +0 -68
  87. data/app/components/primer/dropdown/menu_component.html.erb +0 -12
  88. data/app/components/primer/dropdown/menu_component.rb +0 -46
  89. data/app/components/primer/dropdown_component.rb +0 -73
  90. data/app/components/primer/text_component.rb +0 -22
@@ -1,3 +1,4 @@
1
+ <%= label %>
1
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
3
  <%= input %>
3
4
  <%= icon %>
@@ -8,6 +8,8 @@ module Primer
8
8
  ALIGN_DEFAULT = :left
9
9
  ALIGN_OPTIONS = [ALIGN_DEFAULT, :right].freeze
10
10
 
11
+ DEFAULT_TAG = :div
12
+ TAG_OPTIONS = [DEFAULT_TAG, :span].freeze
11
13
  # Required list of stacked avatars.
12
14
  #
13
15
  # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::AvatarComponent) %>.
@@ -34,11 +36,12 @@ module Primer
34
36
  # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
35
37
  # <% end %>
36
38
  #
39
+ # @param tag [Symbol] <%= one_of(Primer::AvatarStackComponent::TAG_OPTIONS) %>
37
40
  # @param align [Symbol] <%= one_of(Primer::AvatarStackComponent::ALIGN_OPTIONS) %>
38
41
  # @param tooltipped [Boolean] Whether to add a tooltip to the stack or not.
39
- # @param body_arguments [Hash] Parameters to add to the Body. If `tooltipped` is set, has the same arguments as <%= link_to_component(Primer::TooltipComponent) %>.
42
+ # @param body_arguments [Hash] Parameters to add to the Body. If `tooltipped` is set, has the same arguments as <%= link_to_component(Primer::Tooltip) %>.
40
43
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
41
- def initialize(align: ALIGN_DEFAULT, tooltipped: false, body_arguments: {}, **system_arguments)
44
+ def initialize(tag: DEFAULT_TAG, align: ALIGN_DEFAULT, tooltipped: false, body_arguments: {}, **system_arguments)
42
45
  @align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
43
46
  @system_arguments = system_arguments
44
47
  @tooltipped = tooltipped
@@ -50,7 +53,7 @@ module Primer
50
53
  @body_arguments[:classes]
51
54
  )
52
55
 
53
- @system_arguments[:tag] ||= :div
56
+ @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, DEFAULT_TAG)
54
57
  @system_arguments[:classes] = class_names(
55
58
  "AvatarStack",
56
59
  system_arguments[:classes],
@@ -60,7 +63,7 @@ module Primer
60
63
 
61
64
  def body_component
62
65
  if @tooltipped
63
- Primer::TooltipComponent.new(**@body_arguments)
66
+ Primer::Tooltip.new(**@body_arguments)
64
67
  else
65
68
  Primer::BaseComponent.new(**@body_arguments)
66
69
  end
@@ -77,20 +77,22 @@ module Primer
77
77
  # | `flex_shrink` | Integer | To enable, set to `0`. |
78
78
  # | `flex_wrap` | Symbol | <%= one_of(Primer::Classify::Flex::WRAP_MAPPINGS.keys) %> |
79
79
  # | `justify_content` | Symbol | <%= one_of(Primer::Classify::Flex::JUSTIFY_CONTENT_VALUES) %> |
80
- # | `width` | Symbol | <%= one_of([:fit, :fill]) %> |
80
+ # | `width` | Symbol | <%= one_of([:fit]) %> |
81
81
  #
82
82
  # ## Grid
83
83
  #
84
84
  # | Name | Type | Description |
85
85
  # | :- | :- | :- |
86
- # | `col` | Integer | Number of columns. |
86
+ # | `clearfix` | Boolean | Wether to assign the `clearfix` class. |
87
+ # | `col` | Integer | Number of columns. <%= one_of(Primer::Classify::Grid::COL_VALUES) %> |
88
+ # | `container` | Symbol | Size of the container. <%= one_of(Primer::Classify::Grid::CONTAINER_VALUES) %> |
87
89
  #
88
90
  # ## Layout
89
91
  #
90
92
  # | Name | Type | Description |
91
93
  # | :- | :- | :- |
92
94
  # | `display` | Symbol | <%= one_of([:none, :block, :flex, :inline, :inline_block, :inline_flex, :table, :table_cell]) %> |
93
- # | `height` | Symbol | <%= one_of([:fit, :fill]) %> |
95
+ # | `height` | Symbol | <%= one_of([:fit]) %> |
94
96
  # | `hide` | Symbol | Hide the element at a specific breakpoint. <%= one_of([:sm, :md, :lg, :xl]) %> |
95
97
  # | `v` | Symbol | Visibility. <%= one_of([:hidden, :visible]) %> |
96
98
  # | `vertical_align` | Symbol | <%= one_of([:baseline, :top, :middle, :bottom, :text_top, :text_bottom]) %> |
@@ -129,9 +131,12 @@ module Primer
129
131
  #
130
132
  # | Name | Type | Description |
131
133
  # | :- | :- | :- |
132
- # | `font_size` | String, Integer | <%= one_of(["00", 0, 1, 2, 3, 4, 5, 6]) %> |
133
- # | `font_weight` | Symbol | Font weight. <%= one_of([:light, :normal, :bold]) %> |
134
+ # | `font_family` | Symbol | Font weight. <%= one_of([:mono]) %> |
135
+ # | `font_size` | String, Integer, Symbol | <%= one_of(["00", 0, 1, 2, 3, 4, 5, 6, :small, :normal]) %> |
136
+ # | `font_style` | Symbol | Font weight. <%= one_of([:italic]) %> |
137
+ # | `font_weight` | Symbol | Font weight. <%= one_of([:light, :normal, :bold, :emphasized]) %> |
134
138
  # | `text_align` | Symbol | Text alignment. <%= one_of([:left, :right, :center]) %> |
139
+ # | `text_transform` | Symbol | Text alignment. <%= one_of([:uppercase]) %> |
135
140
  # | `underline` | Boolean | Whether text should be underlined. |
136
141
  # | `word_break` | Symbol | Whether to break words on line breaks. Can only be `:break_all`. |
137
142
  #
@@ -143,10 +148,15 @@ module Primer
143
148
  # | test_selector | String | Adds `data-test-selector='given value'` in non-Production environments for testing purposes. |
144
149
  def initialize(tag:, classes: nil, **system_arguments)
145
150
  @tag = tag
146
- @result = Primer::Classify.call(**system_arguments.merge(classes: classes))
151
+ @system_arguments = system_arguments
147
152
 
153
+ raise ArgumentError, "`class` is an invalid argument. Use `classes` instead." if system_arguments.key?(:class) && !Rails.env.production?
154
+
155
+ @result = Primer::Classify.call(**@system_arguments.merge(classes: classes))
156
+
157
+ @system_arguments[:"data-view-component"] = true
148
158
  # Filter out Primer keys so they don't get assigned as HTML attributes
149
- @content_tag_args = add_test_selector(system_arguments).except(*Primer::Classify::VALID_KEYS)
159
+ @content_tag_args = add_test_selector(@system_arguments).except(*Primer::Classify::VALID_KEYS)
150
160
  end
151
161
 
152
162
  def call
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Beta
5
+ # `Text` is a wrapper component that will apply typography styles to the text inside.
6
+ class Text < Primer::Component
7
+ status :beta
8
+
9
+ DEFAULT_TAG = :span
10
+
11
+ # @example Default
12
+ # <%= render(Primer::Beta::Text.new(tag: :p, font_weight: :bold)) { "Bold Text" } %>
13
+ # <%= render(Primer::Beta::Text.new(tag: :p, color: :text_danger)) { "Danger Text" } %>
14
+ #
15
+ # @param tag [Symbol]
16
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
17
+ def initialize(tag: DEFAULT_TAG, **system_arguments)
18
+ @system_arguments = system_arguments
19
+ @system_arguments[:tag] = tag
20
+ end
21
+
22
+ def call
23
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -1,3 +1,4 @@
1
+ <%# erblint:counter ButtonComponentMigrationCounter 1 %>
1
2
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
3
  <% if spinner.present? %>
3
4
  <%= spinner %>
@@ -3,8 +3,8 @@
3
3
  module Primer
4
4
  # Use `Blankslate` when there is a lack of content within a page or section. Use as placeholder to tell users why something isn't there.
5
5
  # @accessibility
6
- # `BlankSlate` renders an `<h3>` element for the title by default. Update the heading level based on what is appropriate for your page hierarchy by setting `title_tag`.
7
- # [Learn more about best heading practices (WAI Headings)](https://www.w3.org/WAI/tutorials/page-structure/headings/)
6
+ # `Blankslate` renders an `<h3>` element for the title by default. Update the heading level based on what is appropriate for your page hierarchy by setting `title_tag`.
7
+ # <%= link_to_heading_practices %>
8
8
  class BlankslateComponent < Primer::Component
9
9
  status :beta
10
10
 
@@ -23,61 +23,79 @@ module Primer
23
23
  # description: "Description",
24
24
  # ) %>
25
25
  #
26
- # @example Icon|Add an `icon` to give additional context. Refer to the [Octicons](https://primer.style/octicons/) documentation to choose an icon.
27
- # <%= render Primer::BlankslateComponent.new(
28
- # icon: "octoface",
29
- # title: "Title",
30
- # description: "Description",
31
- # ) %>
26
+ # @example Icon
27
+ # @description
28
+ # Add an `icon` to give additional context. Refer to the [Octicons](https://primer.style/octicons/) documentation to choose an icon.
29
+ # @code
30
+ # <%= render Primer::BlankslateComponent.new(
31
+ # icon: :globe,
32
+ # title: "Title",
33
+ # description: "Description",
34
+ # ) %>
32
35
  #
33
- # @example Loading|Add a [SpinnerComponent](https://primer.style/view-components/components/spinner) to the blankslate in place of an icon.
34
- # <%= render Primer::BlankslateComponent.new(
35
- # title: "Title",
36
- # description: "Description",
37
- # ) do |component| %>
38
- # <% component.spinner(size: :large) %>
39
- # <% end %>
36
+ # @example Loading
37
+ # @description
38
+ # Add a [SpinnerComponent](https://primer.style/view-components/components/spinner) to the blankslate in place of an icon.
39
+ # @code
40
+ # <%= render Primer::BlankslateComponent.new(
41
+ # title: "Title",
42
+ # description: "Description",
43
+ # ) do |component| %>
44
+ # <% component.spinner(size: :large) %>
45
+ # <% end %>
40
46
  #
41
- # @example Custom content|Pass custom content as a block in place of `description`.
42
- # <%= render Primer::BlankslateComponent.new(
43
- # title: "Title",
44
- # ) do %>
45
- # <em>Your custom content here</em>
46
- # <% end %>
47
+ # @example Custom content
48
+ # @description
49
+ # Pass custom content as a block in place of `description`.
50
+ # @code
51
+ # <%= render Primer::BlankslateComponent.new(
52
+ # title: "Title",
53
+ # ) do %>
54
+ # <em>Your custom content here</em>
55
+ # <% end %>
47
56
  #
48
- # @example Action button|Provide a button to guide users to take action from the blankslate. The button appears below the description and custom content.
49
- # <%= render Primer::BlankslateComponent.new(
50
- # icon: "book",
51
- # title: "Welcome to the mona wiki!",
52
- # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
57
+ # @example Action button
58
+ # @description
59
+ # Provide a button to guide users to take action from the blankslate. The button appears below the description and custom content.
60
+ # @code
61
+ # <%= render Primer::BlankslateComponent.new(
62
+ # icon: :book,
63
+ # title: "Welcome to the mona wiki!",
64
+ # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
53
65
  #
54
- # button_text: "Create the first page",
55
- # button_url: "https://github.com/monalisa/mona/wiki/_new",
56
- # ) %>
66
+ # button_text: "Create the first page",
67
+ # button_url: "https://github.com/monalisa/mona/wiki/_new",
68
+ # ) %>
57
69
  #
58
- # @example Link|Add an additional link to help users learn more about a feature. The link will be shown at the very bottom:
59
- # <%= render Primer::BlankslateComponent.new(
60
- # icon: "book",
61
- # title: "Welcome to the mona wiki!",
62
- # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
63
- # link_text: "Learn more about wikis",
64
- # link_url: "https://docs.github.com/en/github/building-a-strong-community/about-wikis",
65
- # ) %>
70
+ # @example Link
71
+ # @description
72
+ # Add an additional link to help users learn more about a feature. The link will be shown at the very bottom:
73
+ # @code
74
+ # <%= render Primer::BlankslateComponent.new(
75
+ # icon: :book,
76
+ # title: "Welcome to the mona wiki!",
77
+ # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
78
+ # link_text: "Learn more about wikis",
79
+ # link_url: "https://docs.github.com/en/github/building-a-strong-community/about-wikis",
80
+ # ) %>
66
81
  #
67
- # @example Variations|There are a few variations of how the Blankslate appears: `narrow` adds a maximum width, `large` increases the font size, and `spacious` adds extra padding.
68
- # <%= render Primer::BlankslateComponent.new(
69
- # icon: "book",
70
- # title: "Welcome to the mona wiki!",
71
- # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
72
- # narrow: true,
73
- # large: true,
74
- # spacious: true,
75
- # ) %>
82
+ # @example Variations
83
+ # @description
84
+ # There are a few variations of how the Blankslate appears: `narrow` adds a maximum width, `large` increases the font size, and `spacious` adds extra padding.
85
+ # @code
86
+ # <%= render Primer::BlankslateComponent.new(
87
+ # icon: :book,
88
+ # title: "Welcome to the mona wiki!",
89
+ # description: "Wikis provide a place in your repository to lay out the roadmap of your project, show the current status, and document software better, together.",
90
+ # narrow: true,
91
+ # large: true,
92
+ # spacious: true,
93
+ # ) %>
76
94
  #
77
95
  # @param title [String] Text that appears in a larger bold font.
78
96
  # @param title_tag [Symbol] HTML tag to use for title.
79
- # @param icon [String] Octicon icon to use at top of component.
80
- # @param icon_size [Symbol] <%= one_of(Primer::OcticonComponent::SIZE_MAPPINGS) %>
97
+ # @param icon [Symbol] Octicon icon to use at top of component.
98
+ # @param icon_size [Symbol] <%= one_of(Primer::OcticonComponent::SIZE_MAPPINGS, sort: false) %>
81
99
  # @param image_src [String] Image to display.
82
100
  # @param image_alt [String] Alt text for image.
83
101
  # @param description [String] Text that appears below the title. Typically a whole sentence.
@@ -89,6 +107,7 @@ module Primer
89
107
  # @param narrow [Boolean] Adds a maximum width.
90
108
  # @param large [Boolean] Increases the font size.
91
109
  # @param spacious [Boolean] Adds extra padding.
110
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
92
111
  def initialize(
93
112
  title: "",
94
113
  title_tag: :h3,
@@ -111,7 +130,7 @@ module Primer
111
130
  **system_arguments
112
131
  )
113
132
  @system_arguments = system_arguments
114
- @system_arguments[:tag] ||= :div
133
+ @system_arguments[:tag] = :div
115
134
  @system_arguments[:classes] = class_names(
116
135
  @system_arguments[:classes],
117
136
  "blankslate",
@@ -78,11 +78,12 @@ module Primer
78
78
  #
79
79
  # @param scheme [Symbol] <%= one_of(Primer::ButtonComponent::SCHEME_OPTIONS) %>
80
80
  # @param variant [Symbol] <%= one_of(Primer::ButtonComponent::VARIANT_OPTIONS) %>
81
- # @param tag [Symbol] <%= one_of(Primer::BaseButton::TAG_OPTIONS) %>
82
- # @param type [Symbol] <%= one_of(Primer::BaseButton::TYPE_OPTIONS) %>
81
+ # @param tag [Symbol] (Primer::BaseButton::DEFAULT_TAG) <%= one_of(Primer::BaseButton::TAG_OPTIONS) %>
82
+ # @param type [Symbol] (Primer::BaseButton::DEFAULT_TYPE) <%= one_of(Primer::BaseButton::TYPE_OPTIONS) %>
83
83
  # @param group_item [Boolean] Whether button is part of a ButtonGroup.
84
84
  # @param block [Boolean] Whether button is full-width with `display: block`.
85
85
  # @param caret [Boolean] Whether or not to render a caret.
86
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
86
87
  def initialize(
87
88
  scheme: DEFAULT_SCHEME,
88
89
  variant: DEFAULT_VARIANT,
@@ -22,7 +22,7 @@ module Primer
22
22
  # <% component.button(scheme: :primary) { "Primary" } %>
23
23
  # <% component.button(scheme: :danger) { "Danger" } %>
24
24
  # <% component.button(scheme: :outline) { "Outline" } %>
25
- # <% component.button(classes: "my-class") { "Custom class" } %>
25
+ # <% component.button(classes: "custom-class") { "Custom class" } %>
26
26
  # <% end %>
27
27
  #
28
28
  # @example Variants
@@ -46,7 +46,7 @@ module Primer
46
46
  def initialize(variant: Primer::ButtonComponent::DEFAULT_VARIANT, **system_arguments)
47
47
  @variant = variant
48
48
  @system_arguments = system_arguments
49
- @system_arguments[:tag] ||= :div
49
+ @system_arguments[:tag] = :div
50
50
 
51
51
  @system_arguments[:classes] = class_names(
52
52
  "BtnGroup",
@@ -1,4 +1,5 @@
1
1
  import '@github/clipboard-copy-element';
2
+ const CLIPBOARD_COPY_TIMER_DURATION = 2000;
2
3
  function toggleSVG(svg) {
3
4
  if (svg.style.display === '' || svg.style.display === 'block') {
4
5
  svg.style.display = 'none';
@@ -15,9 +16,19 @@ function toggleCopyButton(button) {
15
16
  toggleSVG(clippyIcon);
16
17
  toggleSVG(checkIcon);
17
18
  }
19
+ const clipboardCopyElementTimers = new WeakMap();
18
20
  document.addEventListener('clipboard-copy', function ({ target }) {
19
21
  if (!(target instanceof HTMLElement))
20
22
  return;
21
- toggleCopyButton(target);
22
- setTimeout(toggleCopyButton, 2000, target);
23
+ if (!target.hasAttribute('data-view-component'))
24
+ return;
25
+ const currentTimeout = clipboardCopyElementTimers.get(target);
26
+ if (currentTimeout) {
27
+ clearTimeout(currentTimeout);
28
+ clipboardCopyElementTimers.delete(target);
29
+ }
30
+ else {
31
+ toggleCopyButton(target);
32
+ }
33
+ clipboardCopyElementTimers.set(target, setTimeout(toggleCopyButton, CLIPBOARD_COPY_TIMER_DURATION, target));
23
34
  });
@@ -1,5 +1,7 @@
1
1
  import '@github/clipboard-copy-element'
2
2
 
3
+ const CLIPBOARD_COPY_TIMER_DURATION = 2000
4
+
3
5
  function toggleSVG(svg: SVGElement) {
4
6
  if (svg.style.display === '' || svg.style.display === 'block') {
5
7
  svg.style.display = 'none'
@@ -18,9 +20,20 @@ function toggleCopyButton(button: HTMLElement) {
18
20
  toggleSVG(checkIcon)
19
21
  }
20
22
 
23
+ const clipboardCopyElementTimers = new WeakMap<HTMLElement, number>()
24
+
21
25
  document.addEventListener('clipboard-copy', function ({target}) {
22
26
  if (!(target instanceof HTMLElement)) return
23
- toggleCopyButton(target)
27
+ if (!target.hasAttribute('data-view-component')) return
28
+
29
+ const currentTimeout = clipboardCopyElementTimers.get(target)
30
+
31
+ if (currentTimeout) {
32
+ clearTimeout(currentTimeout)
33
+ clipboardCopyElementTimers.delete(target)
34
+ } else {
35
+ toggleCopyButton(target)
36
+ }
24
37
 
25
- setTimeout(toggleCopyButton, 2000, target)
38
+ clipboardCopyElementTimers.set(target, setTimeout(toggleCopyButton, CLIPBOARD_COPY_TIMER_DURATION, target))
26
39
  })
@@ -5,7 +5,7 @@ require "view_component/version"
5
5
  module Primer
6
6
  # @private
7
7
  class Component < ViewComponent::Base
8
- include ViewComponent::SlotableV2 unless ViewComponent::VERSION::STRING.to_f >= 2.28
8
+ include ViewComponent::SlotableV2 unless ViewComponent::Base < ViewComponent::SlotableV2
9
9
  include ClassNameHelper
10
10
  include FetchOrFallbackHelper
11
11
  include TestSelectorHelper
@@ -25,6 +25,11 @@ module Primer
25
25
  ActiveSupport::Deprecation.warn(message)
26
26
  end
27
27
 
28
+ def validate_aria_label
29
+ aria_label = @system_arguments[:"aria-label"] || @system_arguments.dig(:aria, :label)
30
+ raise ArgumentError, "`aria-label` is required." if aria_label.nil? && !Rails.env.production?
31
+ end
32
+
28
33
  def silence_deprecations?
29
34
  Rails.application.config.primer_view_components.silence_deprecations
30
35
  end
@@ -1,7 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Primer
4
- # Use `CounterComponent` to add a count to navigational elements and buttons.
4
+ # Use `Counter` to add a count to navigational elements and buttons.
5
+ #
6
+ # @accessibility
7
+ # Always use `Counter` with adjacent text that provides supplementary information regarding what the count is for. For instance, `Counter`
8
+ # should be accompanied with text such as `issues` or `pull requests`.
9
+ #
5
10
  class CounterComponent < Primer::Component
6
11
  status :beta
7
12
 
@@ -14,7 +14,7 @@ module Primer
14
14
 
15
15
  # Use the Summary slot as a trigger to reveal the content.
16
16
  #
17
- # @param button [Boolean] Whether to render the Summary as a button or not.
17
+ # @param button [Boolean] (true) Whether to render the Summary as a button or not.
18
18
  # @param kwargs [Hash] The same arguments as <%= link_to_system_arguments_docs %>.
19
19
  renders_one :summary, lambda { |button: true, **system_arguments|
20
20
  system_arguments[:tag] = :summary
@@ -33,6 +33,17 @@ module Primer
33
33
  Primer::BaseComponent.new(**system_arguments)
34
34
  }
35
35
 
36
+ # @example Default
37
+ #
38
+ # <%= render Primer::DetailsComponent.new do |c| %>
39
+ # component.summary do
40
+ # "Summary"
41
+ # end
42
+ # component.body do
43
+ # "Body"
44
+ # end
45
+ # <% end %>
46
+ #
36
47
  # @param overlay [Symbol] Dictates the type of overlay to render with. <%= one_of(Primer::DetailsComponent::OVERLAY_MAPPINGS.keys) %>
37
48
  # @param reset [Boolean] Defatuls to false. If set to true, it will remove the default caret and remove style from the summary element
38
49
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>