primer_view_components 0.0.33 → 0.0.38

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +102 -0
  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/{auto_complete_component.rb → auto_complete.rb} +13 -11
  6. data/app/components/primer/{auto_complete_component.d.ts → auto_complete/auto_complete.d.ts} +0 -0
  7. data/app/components/primer/{auto_complete_component.html.erb → auto_complete/auto_complete.html.erb} +0 -0
  8. data/app/components/primer/{auto_complete_component.js → auto_complete/auto_complete.js} +0 -0
  9. data/app/components/primer/{auto_complete_component.ts → auto_complete/auto_complete.ts} +0 -0
  10. data/app/components/primer/auto_complete/auto_component.d.ts +1 -0
  11. data/app/components/primer/auto_complete/auto_component.js +1 -0
  12. data/app/components/primer/auto_complete/item.rb +42 -0
  13. data/app/components/primer/avatar_stack_component.rb +2 -0
  14. data/app/components/primer/base_button.rb +47 -0
  15. data/app/components/primer/base_component.rb +115 -85
  16. data/app/components/primer/button_component.rb +37 -32
  17. data/app/components/primer/button_component.rb.orig +138 -0
  18. data/app/components/primer/{button_group_component.html.erb → button_group.html.erb} +0 -0
  19. data/app/components/primer/button_group.rb +61 -0
  20. data/app/components/primer/button_marketing_component.rb +15 -20
  21. data/app/components/primer/clipboard_copy.html.erb +8 -0
  22. data/app/components/primer/clipboard_copy.rb +26 -0
  23. data/app/components/primer/clipboard_copy_component.d.ts +1 -0
  24. data/app/components/primer/clipboard_copy_component.js +25 -0
  25. data/app/components/primer/clipboard_copy_component.ts +28 -0
  26. data/app/components/primer/close_button.rb +37 -0
  27. data/app/components/primer/component.rb +1 -0
  28. data/app/components/primer/dropdown_component.rb +1 -1
  29. data/app/components/primer/dropdown_menu_component.rb +1 -1
  30. data/app/components/primer/flash_component.rb +10 -10
  31. data/app/components/primer/foo_bar.d.ts +1 -0
  32. data/app/components/primer/foo_bar.js +1 -0
  33. data/app/components/primer/heading_component.rb +32 -4
  34. data/app/components/primer/hidden_text_expander.rb +41 -0
  35. data/app/components/primer/link_component.rb +9 -9
  36. data/app/components/primer/navigation/tab_component.html.erb +9 -7
  37. data/app/components/primer/navigation/tab_component.rb +27 -3
  38. data/app/components/primer/octicon_component.rb +0 -4
  39. data/app/components/primer/primer.d.ts +2 -1
  40. data/app/components/primer/primer.js +2 -1
  41. data/app/components/primer/primer.ts +2 -1
  42. data/app/components/primer/state_component.rb +14 -14
  43. data/app/components/primer/subhead_component.rb +1 -1
  44. data/app/components/primer/tab_nav_component.html.erb +2 -2
  45. data/app/components/primer/tab_nav_component.rb +22 -8
  46. data/app/components/primer/{truncate_component.rb → truncate.rb} +8 -6
  47. data/app/components/primer/underline_nav_component.rb +46 -14
  48. data/app/lib/primer/classify.rb +4 -13
  49. data/app/lib/primer/classify/cache.rb +14 -4
  50. data/app/lib/primer/classify/spacing.rb +63 -0
  51. data/app/lib/primer/tabbed_component_helper.rb +4 -0
  52. data/lib/primer/view_components/version.rb +1 -1
  53. data/static/statuses.json +1 -1
  54. metadata +116 -32
  55. data/app/assets/javascripts/primer_view_components.js.map.orig +0 -5
  56. data/app/assets/javascripts/primer_view_components.js.orig +0 -6
  57. data/app/components/primer/auto_complete_item_component.rb +0 -38
  58. data/app/components/primer/button_group_component.rb +0 -35
@@ -3,14 +3,19 @@
3
3
  module Primer
4
4
  # Use buttons for actions (e.g. in forms). Use links for destinations, or moving from one page to another.
5
5
  class ButtonComponent < Primer::Component
6
- DEFAULT_BUTTON_TYPE = :default
7
- BUTTON_TYPE_MAPPINGS = {
8
- DEFAULT_BUTTON_TYPE => "",
6
+ status :beta
7
+
8
+ DEFAULT_SCHEME = :default
9
+ LINK_SCHEME = :link
10
+ SCHEME_MAPPINGS = {
11
+ DEFAULT_SCHEME => "",
9
12
  :primary => "btn-primary",
10
13
  :danger => "btn-danger",
11
- :outline => "btn-outline"
14
+ :outline => "btn-outline",
15
+ :invisible => "btn-invisible",
16
+ LINK_SCHEME => "btn-link"
12
17
  }.freeze
13
- BUTTON_TYPE_OPTIONS = BUTTON_TYPE_MAPPINGS.keys
18
+ SCHEME_OPTIONS = SCHEME_MAPPINGS.keys
14
19
 
15
20
  DEFAULT_VARIANT = :medium
16
21
  VARIANT_MAPPINGS = {
@@ -20,56 +25,56 @@ module Primer
20
25
  }.freeze
21
26
  VARIANT_OPTIONS = VARIANT_MAPPINGS.keys
22
27
 
23
- DEFAULT_TAG = :button
24
- TAG_OPTIONS = [DEFAULT_TAG, :a, :summary].freeze
25
-
26
- DEFAULT_TYPE = :button
27
- TYPE_OPTIONS = [DEFAULT_TYPE, :reset, :submit].freeze
28
-
29
- # @example Button types
28
+ # @example Schemes
30
29
  # <%= render(Primer::ButtonComponent.new) { "Default" } %>
31
- # <%= render(Primer::ButtonComponent.new(button_type: :primary)) { "Primary" } %>
32
- # <%= render(Primer::ButtonComponent.new(button_type: :danger)) { "Danger" } %>
33
- # <%= render(Primer::ButtonComponent.new(button_type: :outline)) { "Outline" } %>
30
+ # <%= render(Primer::ButtonComponent.new(scheme: :primary)) { "Primary" } %>
31
+ # <%= render(Primer::ButtonComponent.new(scheme: :danger)) { "Danger" } %>
32
+ # <%= render(Primer::ButtonComponent.new(scheme: :outline)) { "Outline" } %>
33
+ # <%= render(Primer::ButtonComponent.new(scheme: :invisible)) { "Invisible" } %>
34
+ # <%= render(Primer::ButtonComponent.new(scheme: :link)) { "Link" } %>
34
35
  #
35
36
  # @example Variants
36
37
  # <%= render(Primer::ButtonComponent.new(variant: :small)) { "Small" } %>
37
38
  # <%= render(Primer::ButtonComponent.new(variant: :medium)) { "Medium" } %>
38
39
  # <%= render(Primer::ButtonComponent.new(variant: :large)) { "Large" } %>
39
40
  #
40
- # @param button_type [Symbol] <%= one_of(Primer::ButtonComponent::BUTTON_TYPE_OPTIONS) %>
41
+ # @example Block
42
+ # <%= render(Primer::ButtonComponent.new(block: :true)) { "Block" } %>
43
+ # <%= render(Primer::ButtonComponent.new(block: :true, scheme: :primary)) { "Primary block" } %>
44
+ #
45
+ # @param scheme [Symbol] <%= one_of(Primer::ButtonComponent::SCHEME_OPTIONS) %>
41
46
  # @param variant [Symbol] <%= one_of(Primer::ButtonComponent::VARIANT_OPTIONS) %>
42
- # @param tag [Symbol] <%= one_of(Primer::ButtonComponent::TAG_OPTIONS) %>
43
- # @param type [Symbol] <%= one_of(Primer::ButtonComponent::TYPE_OPTIONS) %>
47
+ # @param tag [Symbol] <%= one_of(Primer::BaseButton::TAG_OPTIONS) %>
48
+ # @param type [Symbol] <%= one_of(Primer::BaseButton::TYPE_OPTIONS) %>
44
49
  # @param group_item [Boolean] Whether button is part of a ButtonGroup.
50
+ # @param block [Boolean] Whether button is full-width with `display: block`.
45
51
  def initialize(
46
- button_type: DEFAULT_BUTTON_TYPE,
52
+ scheme: DEFAULT_SCHEME,
47
53
  variant: DEFAULT_VARIANT,
48
- tag: DEFAULT_TAG,
49
- type: DEFAULT_TYPE,
50
54
  group_item: false,
55
+ block: false,
51
56
  **system_arguments
52
57
  )
58
+ @scheme = scheme
53
59
  @system_arguments = system_arguments
54
- @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, DEFAULT_TAG)
55
-
56
- if @system_arguments[:tag] == :a
57
- @system_arguments[:role] = :button
58
- else
59
- @system_arguments[:type] = type
60
- end
61
-
62
60
  @system_arguments[:classes] = class_names(
63
- "btn",
64
61
  system_arguments[:classes],
65
- BUTTON_TYPE_MAPPINGS[fetch_or_fallback(BUTTON_TYPE_OPTIONS, button_type, DEFAULT_BUTTON_TYPE)],
62
+ SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)],
66
63
  VARIANT_MAPPINGS[fetch_or_fallback(VARIANT_OPTIONS, variant, DEFAULT_VARIANT)],
64
+ "btn" => !link?,
65
+ "btn-block" => block,
67
66
  "BtnGroup-item" => group_item
68
67
  )
69
68
  end
70
69
 
71
70
  def call
72
- render(Primer::BaseComponent.new(**@system_arguments)) { content }
71
+ render(Primer::BaseButton.new(**@system_arguments)) { content }
72
+ end
73
+
74
+ private
75
+
76
+ def link?
77
+ @scheme == LINK_SCHEME
73
78
  end
74
79
  end
75
80
  end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # Use buttons for actions (e.g. in forms). Use links for destinations, or moving from one page to another.
5
+ class ButtonComponent < Primer::Component
6
+ status :beta
7
+
8
+ DEFAULT_SCHEME = :default
9
+ LINK_SCHEME = :link
10
+ SCHEME_MAPPINGS = {
11
+ DEFAULT_SCHEME => "",
12
+ :primary => "btn-primary",
13
+ :danger => "btn-danger",
14
+ :outline => "btn-outline",
15
+ :invisible => "btn-invisible",
16
+ LINK_SCHEME => "btn-link"
17
+ }.freeze
18
+ SCHEME_OPTIONS = SCHEME_MAPPINGS.keys
19
+
20
+ DEFAULT_VARIANT = :medium
21
+ VARIANT_MAPPINGS = {
22
+ :small => "btn-sm",
23
+ DEFAULT_VARIANT => "",
24
+ :large => "btn-large"
25
+ }.freeze
26
+ VARIANT_OPTIONS = VARIANT_MAPPINGS.keys
27
+
28
+ <<<<<<< HEAD
29
+ =======
30
+ DEFAULT_TAG = :button
31
+ TAG_OPTIONS = [DEFAULT_TAG, :a, :summary].freeze
32
+
33
+ DEFAULT_TYPE = :button
34
+ TYPE_OPTIONS = [DEFAULT_TYPE, :reset, :submit].freeze
35
+
36
+ DEFAULT_ICON_ALIGN = :left
37
+ ICON_ALIGN_OPTIONS = [DEFAULT_ICON_ALIGN, :right].freeze
38
+
39
+ # Icon to be rendered in the button.
40
+ #
41
+ # @param align [Symbol] <%= one_of(Primer::ButtonComponent::ICON_ALIGN_OPTIONS) %>
42
+ # @param system_arguments [Hash] Same arguments as <%= link_to_component(Primer::OcticonComponent) %>.
43
+ renders_one :icon, lambda { |align: DEFAULT_ICON_ALIGN, **system_arguments|
44
+ @icon_align = fetch_or_fallback(ICON_ALIGN_OPTIONS, align, DEFAULT_ICON_ALIGN)
45
+
46
+ Primer::OcticonComponent.new(**system_arguments)
47
+ }
48
+
49
+ # Counter to be rendered in the button.
50
+ #
51
+ # @param system_arguments [Hash] Same arguments as <%= link_to_component(Primer::CounterComponent) %>.
52
+ renders_one :counter, Primer::CounterComponent
53
+
54
+ >>>>>>> 05bacd3 (add icon and counter slots to button)
55
+ # @example Schemes
56
+ # <%= render(Primer::ButtonComponent.new) { "Default" } %>
57
+ # <%= render(Primer::ButtonComponent.new(scheme: :primary)) { "Primary" } %>
58
+ # <%= render(Primer::ButtonComponent.new(scheme: :danger)) { "Danger" } %>
59
+ # <%= render(Primer::ButtonComponent.new(scheme: :outline)) { "Outline" } %>
60
+ # <%= render(Primer::ButtonComponent.new(scheme: :invisible)) { "Invisible" } %>
61
+ # <%= render(Primer::ButtonComponent.new(scheme: :link)) { "Link" } %>
62
+ #
63
+ # @example Variants
64
+ # <%= render(Primer::ButtonComponent.new(variant: :small)) { "Small" } %>
65
+ # <%= render(Primer::ButtonComponent.new(variant: :medium)) { "Medium" } %>
66
+ # <%= render(Primer::ButtonComponent.new(variant: :large)) { "Large" } %>
67
+ #
68
+ # @example Block
69
+ # <%= render(Primer::ButtonComponent.new(block: :true)) { "Block" } %>
70
+ # <%= render(Primer::ButtonComponent.new(block: :true, scheme: :primary)) { "Primary block" } %>
71
+ #
72
+ # @example With icons
73
+ # <%= render(Primer::ButtonComponent.new) do |c| %>
74
+ # <% c.icon(icon: :star) %>
75
+ # Button
76
+ # <% end %>
77
+ # <%= render(Primer::ButtonComponent.new) do |c| %>
78
+ # <% c.icon(icon: :star, align: :right) %>
79
+ # Button
80
+ # <% end %>
81
+ #
82
+ # @example With counter
83
+ # <%= render(Primer::ButtonComponent.new) do |c| %>
84
+ # <% c.counter(count: 15) %>
85
+ # Button
86
+ # <% end %>
87
+ #
88
+ # @example With icons and counter
89
+ # <%= render(Primer::ButtonComponent.new) do |c| %>
90
+ # <% c.icon(icon: :star) %>
91
+ # <% c.counter(count: 15) %>
92
+ # Button
93
+ # <% end %>
94
+ # <%= render(Primer::ButtonComponent.new) do |c| %>
95
+ # <% c.icon(icon: :star, align: :right) %>
96
+ # <% c.counter(count: 15) %>
97
+ # Button
98
+ # <% end %>
99
+ #
100
+ # @param scheme [Symbol] <%= one_of(Primer::ButtonComponent::SCHEME_OPTIONS) %>
101
+ # @param variant [Symbol] <%= one_of(Primer::ButtonComponent::VARIANT_OPTIONS) %>
102
+ # @param tag [Symbol] <%= one_of(Primer::BaseButton::TAG_OPTIONS) %>
103
+ # @param type [Symbol] <%= one_of(Primer::BaseButton::TYPE_OPTIONS) %>
104
+ # @param group_item [Boolean] Whether button is part of a ButtonGroup.
105
+ # @param block [Boolean] Whether button is full-width with `display: block`.
106
+ def initialize(
107
+ scheme: DEFAULT_SCHEME,
108
+ variant: DEFAULT_VARIANT,
109
+ group_item: false,
110
+ block: false,
111
+ **system_arguments
112
+ )
113
+ @scheme = scheme
114
+ @system_arguments = system_arguments
115
+ @system_arguments[:classes] = class_names(
116
+ system_arguments[:classes],
117
+ SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)],
118
+ VARIANT_MAPPINGS[fetch_or_fallback(VARIANT_OPTIONS, variant, DEFAULT_VARIANT)],
119
+ "btn" => !link?,
120
+ "btn-block" => block,
121
+ "BtnGroup-item" => group_item
122
+ )
123
+ end
124
+
125
+ <<<<<<< HEAD
126
+ def call
127
+ render(Primer::BaseButton.new(**@system_arguments)) { content }
128
+ end
129
+
130
+ =======
131
+ >>>>>>> 05bacd3 (add icon and counter slots to button)
132
+ private
133
+
134
+ def link?
135
+ @scheme == LINK_SCHEME
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # Use ButtonGroup to render a series of buttons.
5
+ class ButtonGroup < Primer::Component
6
+ status :beta
7
+
8
+ # Required list of buttons to be rendered.
9
+ #
10
+ # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::ButtonComponent) %> except for `variant` and `group_item`.
11
+ renders_many :buttons, lambda { |**kwargs|
12
+ kwargs[:group_item] = true
13
+ kwargs[:variant] = @variant
14
+
15
+ Primer::ButtonComponent.new(**kwargs)
16
+ }
17
+
18
+ # @example Default
19
+ #
20
+ # <%= render(Primer::ButtonGroup.new) do |component| %>
21
+ # <% component.button { "Default" } %>
22
+ # <% component.button(scheme: :primary) { "Primary" } %>
23
+ # <% component.button(scheme: :danger) { "Danger" } %>
24
+ # <% component.button(scheme: :outline) { "Outline" } %>
25
+ # <% component.button(classes: "my-class") { "Custom class" } %>
26
+ # <% end %>
27
+ #
28
+ # @example Variants
29
+ #
30
+ # <%= render(Primer::ButtonGroup.new(variant: :small)) do |component| %>
31
+ # <% component.button { "Default" } %>
32
+ # <% component.button(scheme: :primary) { "Primary" } %>
33
+ # <% component.button(scheme: :danger) { "Danger" } %>
34
+ # <% component.button(scheme: :outline) { "Outline" } %>
35
+ # <% end %>
36
+ #
37
+ # <%= render(Primer::ButtonGroup.new(variant: :large)) do |component| %>
38
+ # <% component.button { "Default" } %>
39
+ # <% component.button(scheme: :primary) { "Primary" } %>
40
+ # <% component.button(scheme: :danger) { "Danger" } %>
41
+ # <% component.button(scheme: :outline) { "Outline" } %>
42
+ # <% end %>
43
+ #
44
+ # @param variant [Symbol] <%= one_of(Primer::ButtonComponent::VARIANT_OPTIONS) %>
45
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
46
+ def initialize(variant: Primer::ButtonComponent::DEFAULT_VARIANT, **system_arguments)
47
+ @variant = variant
48
+ @system_arguments = system_arguments
49
+ @system_arguments[:tag] ||= :div
50
+
51
+ @system_arguments[:classes] = class_names(
52
+ "BtnGroup",
53
+ system_arguments[:classes]
54
+ )
55
+ end
56
+
57
+ def render?
58
+ buttons.any?
59
+ end
60
+ end
61
+ end
@@ -3,14 +3,14 @@
3
3
  module Primer
4
4
  # Use buttons for actions (e.g. in forms). Use links for destinations, or moving from one page to another.
5
5
  class ButtonMarketingComponent < Primer::Component
6
- DEFAULT_BUTTON_TYPE = :default
7
- BUTTON_TYPE_MAPPINGS = {
8
- DEFAULT_BUTTON_TYPE => "",
6
+ DEFAULT_SCHEME = :default
7
+ SCHEME_MAPPINGS = {
8
+ DEFAULT_SCHEME => "",
9
9
  :primary => "btn-primary-mktg",
10
10
  :outline => "btn-outline-mktg",
11
11
  :transparent => "btn-transparent"
12
12
  }.freeze
13
- BUTTON_TYPE_OPTIONS = BUTTON_TYPE_MAPPINGS.keys
13
+ SCHEME_OPTIONS = SCHEME_MAPPINGS.keys
14
14
 
15
15
  DEFAULT_VARIANT = :default
16
16
  VARIANT_MAPPINGS = {
@@ -25,49 +25,44 @@ module Primer
25
25
  DEFAULT_TYPE = :button
26
26
  TYPE_OPTIONS = [DEFAULT_TYPE, :submit].freeze
27
27
 
28
- # @example Button types
28
+ # @example Schemes
29
29
  # <%= render(Primer::ButtonMarketingComponent.new(mr: 2)) { "Default" } %>
30
- # <%= render(Primer::ButtonMarketingComponent.new(button_type: :primary, mr: 2)) { "Primary" } %>
31
- # <%= render(Primer::ButtonMarketingComponent.new(button_type: :outline)) { "Outline" } %>
32
- # <div class="bg-gray-dark">
33
- # <%= render(Primer::ButtonMarketingComponent.new(button_type: :transparent)) { "Transparent" } %>
30
+ # <%= render(Primer::ButtonMarketingComponent.new(scheme: :primary, mr: 2)) { "Primary" } %>
31
+ # <%= render(Primer::ButtonMarketingComponent.new(scheme: :outline)) { "Outline" } %>
32
+ # <div class="color-bg-canvas-inverse">
33
+ # <%= render(Primer::ButtonMarketingComponent.new(scheme: :transparent)) { "Transparent" } %>
34
34
  # </div>
35
35
  #
36
36
  # @example Sizes
37
37
  # <%= render(Primer::ButtonMarketingComponent.new(mr: 2)) { "Default" } %>
38
38
  # <%= render(Primer::ButtonMarketingComponent.new(variant: :large)) { "Large" } %>
39
39
  #
40
- # @param button_type [Symbol] <%= one_of(Primer::ButtonMarketingComponent::BUTTON_TYPE_OPTIONS) %>
40
+ # @param scheme [Symbol] <%= one_of(Primer::ButtonMarketingComponent::SCHEME_OPTIONS) %>
41
41
  # @param variant [Symbol] <%= one_of(Primer::ButtonMarketingComponent::VARIANT_OPTIONS) %>
42
42
  # @param tag [Symbol] <%= one_of(Primer::ButtonMarketingComponent::TAG_OPTIONS) %>
43
43
  # @param type [Symbol] <%= one_of(Primer::ButtonMarketingComponent::TYPE_OPTIONS) %>
44
44
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
45
45
  def initialize(
46
- button_type: DEFAULT_BUTTON_TYPE,
46
+ scheme: DEFAULT_SCHEME,
47
47
  variant: DEFAULT_VARIANT,
48
48
  tag: DEFAULT_TAG,
49
49
  type: DEFAULT_TYPE,
50
50
  **system_arguments
51
51
  )
52
52
  @system_arguments = system_arguments
53
+ @system_arguments[:block] = false
53
54
  @system_arguments[:tag] = fetch_or_fallback(TAG_OPTIONS, tag, DEFAULT_TAG)
54
-
55
- if @system_arguments[:tag] == :a
56
- @system_arguments[:role] = :button
57
- else
58
- @system_arguments[:type] = fetch_or_fallback(TYPE_OPTIONS, type, DEFAULT_TYPE)
59
- end
60
-
55
+ @system_arguments[:type] = fetch_or_fallback(TYPE_OPTIONS, type, DEFAULT_TYPE)
61
56
  @system_arguments[:classes] = class_names(
62
57
  "btn-mktg",
63
- BUTTON_TYPE_MAPPINGS[fetch_or_fallback(BUTTON_TYPE_OPTIONS, button_type, DEFAULT_BUTTON_TYPE)],
58
+ SCHEME_MAPPINGS[fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)],
64
59
  VARIANT_MAPPINGS[fetch_or_fallback(VARIANT_OPTIONS, variant, DEFAULT_VARIANT)],
65
60
  system_arguments[:classes]
66
61
  )
67
62
  end
68
63
 
69
64
  def call
70
- render(Primer::BaseComponent.new(**@system_arguments)) { content }
65
+ render(Primer::BaseButton.new(**@system_arguments)) { content }
71
66
  end
72
67
  end
73
68
  end
@@ -0,0 +1,8 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <% if content.present? %>
3
+ <%= content %>
4
+ <% else %>
5
+ <%= render Primer::OcticonComponent.new("clippy") %>
6
+ <%= render Primer::OcticonComponent.new("check", color: :icon_success, style: "display: none;") %>
7
+ <% end %>
8
+ <% end %>
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # Use ClipboardCopy to copy element text content or input values to the clipboard.
5
+ class ClipboardCopy < Primer::Component
6
+ status :alpha
7
+
8
+ # @example Default
9
+ # <%= render(Primer::ClipboardCopy.new(value: "Text to copy", label: "Copy text to the system clipboard")) %>
10
+ #
11
+ # @example With text instead of icons
12
+ # <%= render(Primer::ClipboardCopy.new(value: "Text to copy", label: "Copy text to the system clipboard")) do %>
13
+ # Click to copy!
14
+ # <% end %>
15
+ #
16
+ # @param label [String] String that will be read to screenreaders when the component is focused
17
+ # @param value [String] Text to copy into the users clipboard when they click the component
18
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
19
+ def initialize(label:, value:, **system_arguments)
20
+ @system_arguments = system_arguments
21
+ @system_arguments[:tag] = "clipboard-copy"
22
+ @system_arguments[:value] = value
23
+ @system_arguments[:"aria-label"] = label
24
+ end
25
+ end
26
+ end
@@ -0,0 +1 @@
1
+ import '@github/clipboard-copy-element';
@@ -0,0 +1,25 @@
1
+ import '@github/clipboard-copy-element';
2
+ function toggleSVG(svg) {
3
+ if (svg.style.display === '' || svg.style.display === 'block') {
4
+ svg.style.display = 'none';
5
+ }
6
+ else {
7
+ svg.style.display = 'block';
8
+ }
9
+ }
10
+ // Toggle a copy button.
11
+ function toggleCopyButton(button) {
12
+ const [clippyIcon, checkIcon] = button.querySelectorAll('.octicon');
13
+ if (clippyIcon) {
14
+ toggleSVG(clippyIcon);
15
+ }
16
+ if (checkIcon) {
17
+ toggleSVG(checkIcon);
18
+ }
19
+ }
20
+ document.addEventListener('clipboard-copy', function ({ target }) {
21
+ if (!(target instanceof HTMLElement))
22
+ return;
23
+ toggleCopyButton(target);
24
+ setTimeout(toggleCopyButton, 2000, target);
25
+ });