primer_view_components 0.0.17 → 0.0.22

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +102 -0
  3. data/app/assets/javascripts/primer_view_components.js +2 -0
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -0
  5. data/app/components/primer/avatar_component.rb +27 -9
  6. data/app/components/primer/avatar_stack_component.html.erb +10 -0
  7. data/app/components/primer/avatar_stack_component.rb +81 -0
  8. data/app/components/primer/base_component.rb +8 -5
  9. data/app/components/primer/blankslate_component.html.erb +3 -3
  10. data/app/components/primer/blankslate_component.rb +18 -25
  11. data/app/components/primer/border_box_component.html.erb +4 -18
  12. data/app/components/primer/border_box_component.rb +75 -68
  13. data/app/components/primer/box_component.rb +10 -0
  14. data/app/components/primer/breadcrumb_component.rb +3 -2
  15. data/app/components/primer/button_component.rb +3 -3
  16. data/app/components/primer/button_group_component.html.erb +5 -0
  17. data/app/components/primer/button_group_component.rb +37 -0
  18. data/app/components/primer/button_marketing_component.rb +73 -0
  19. data/app/components/primer/component.rb +16 -0
  20. data/app/components/primer/counter_component.rb +16 -9
  21. data/app/components/primer/details_component.html.erb +2 -6
  22. data/app/components/primer/details_component.rb +28 -37
  23. data/app/components/primer/dropdown/menu_component.html.erb +12 -0
  24. data/app/components/primer/dropdown/menu_component.rb +48 -0
  25. data/app/components/primer/dropdown_component.html.erb +9 -0
  26. data/app/components/primer/dropdown_component.rb +75 -0
  27. data/app/components/primer/dropdown_menu_component.rb +35 -3
  28. data/app/components/primer/flash_component.html.erb +4 -7
  29. data/app/components/primer/flash_component.rb +18 -17
  30. data/app/components/primer/flex_component.rb +47 -9
  31. data/app/components/primer/flex_item_component.rb +16 -1
  32. data/app/components/primer/heading_component.rb +9 -0
  33. data/app/components/primer/label_component.rb +6 -6
  34. data/app/components/primer/layout_component.rb +2 -2
  35. data/app/components/primer/link_component.rb +6 -2
  36. data/app/components/primer/markdown_component.rb +293 -0
  37. data/app/components/primer/menu_component.html.erb +6 -0
  38. data/app/components/primer/menu_component.rb +71 -0
  39. data/app/components/primer/octicon_component.rb +13 -6
  40. data/app/components/primer/popover_component.rb +5 -3
  41. data/app/components/primer/primer.js +1 -0
  42. data/app/components/primer/primer.ts +1 -0
  43. data/app/components/primer/progress_bar_component.rb +6 -6
  44. data/app/components/primer/spinner_component.rb +8 -5
  45. data/app/components/primer/state_component.rb +23 -12
  46. data/app/components/primer/subhead_component.rb +6 -3
  47. data/app/components/primer/tab_container_component.js +1 -0
  48. data/app/components/primer/tab_container_component.rb +41 -0
  49. data/app/components/primer/tab_container_component.ts +1 -0
  50. data/app/components/primer/tab_nav_component.html.erb +17 -0
  51. data/app/components/primer/tab_nav_component.rb +108 -0
  52. data/app/components/primer/text_component.rb +1 -1
  53. data/app/components/primer/timeline_item_component.html.erb +4 -16
  54. data/app/components/primer/timeline_item_component.rb +41 -49
  55. data/app/components/primer/tooltip_component.rb +88 -0
  56. data/app/components/primer/truncate_component.rb +41 -0
  57. data/app/components/primer/underline_nav_component.rb +26 -1
  58. data/{lib → app/lib}/primer/class_name_helper.rb +1 -0
  59. data/app/lib/primer/classify.rb +280 -0
  60. data/app/lib/primer/classify/cache.rb +125 -0
  61. data/{lib → app/lib}/primer/fetch_or_fallback_helper.rb +1 -0
  62. data/{lib → app/lib}/primer/join_style_arguments_helper.rb +1 -0
  63. data/app/lib/primer/view_helper.rb +22 -0
  64. data/app/lib/primer/view_helper/dsl.rb +34 -0
  65. data/lib/primer/view_components.rb +32 -0
  66. data/lib/primer/view_components/engine.rb +11 -2
  67. data/lib/primer/view_components/version.rb +5 -1
  68. data/lib/yard/renders_many_handler.rb +19 -0
  69. data/lib/yard/renders_one_handler.rb +19 -0
  70. data/static/statuses.json +1 -0
  71. metadata +94 -24
  72. data/app/components/primer/view_components.rb +0 -52
  73. data/lib/primer/classify.rb +0 -250
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 70daa13e7909487e01c01f4759a88740922070c985ac9604df738614d48c57a1
4
- data.tar.gz: 257383c54d408d94c8aac723804a1db9b75dee88527f60ce101f70514259567c
3
+ metadata.gz: 3155227cd7ba3d3c02063d1021e1430df8d514a7feabe0b5fad0680c593ffc3c
4
+ data.tar.gz: 344362c292977c1dd6b84d283b1a5b5fea8894d2dd0aa5be0c1007fdbf4bf397
5
5
  SHA512:
6
- metadata.gz: 65bef1719944f20523e8670d382474fa15a49cd03eab6a39578ad3901933668c3d2bcfdff9da7e46ba9fdac8587447b92984a6e4c67028732f9ba2f18dc9cf52
7
- data.tar.gz: b578660620dc448087463fd24361c652a8fd9ead88cd6693a658af94f497eb68361e3236cb43386da66f58666c72051d5728bb67b4be6c832ee815c54f59e4c8
6
+ metadata.gz: 76e300f1f5cd3cf5e861f48246f6124ad2432014a003b4b8dffe3b373415d47c43af118965c879f8fe58bfd111dded1a9270c7e2f824020022b14990028210dd
7
+ data.tar.gz: 899f5cf473acde6ff778bd2a86ded0bbb90aea6d8bce9fca0483c455aefc3b8c68388cb0eec578129d6b5703ae53eeeacc14701d4b2fcbdaaba47fd447b117f6
data/CHANGELOG.md CHANGED
@@ -1,6 +1,108 @@
1
1
  # CHANGELOG
2
2
 
3
3
  ## main
4
+
5
+ ## 0.0.22
6
+
7
+ * Add view helpers to easily render Primer components.
8
+
9
+ *Manuel Puyol*
10
+
11
+ * Add `TabContainer` and `TabNav` components.
12
+
13
+ *Manuel Puyol*
14
+
15
+ * Promote `StateComponent` to beta.
16
+
17
+ *Simon Taranto*
18
+
19
+ * **Breaking change**: Upgrade `BorderBoxComponent` to use Slots V2.
20
+
21
+ *Manuel Puyol*
22
+
23
+ * **Breaking change**: Upgrade `StateComponent` to support functional colors. This change requires using [@primer/css-next](https://www.npmjs.com/package/@primer/css-next). The required changes will be upstreamed to @primer/css at a later date.
24
+
25
+ *Simon Taranto*
26
+
27
+ * **Breaking change**: Upgrade `DetailsComponent` to use Slots V2.
28
+
29
+ *Simon Taranto*
30
+
31
+ ## 0.0.21
32
+
33
+ * **Breaking change**: Upgrade `FlashComponent` to use Slots V2.
34
+
35
+ *Joel Hawksley, Simon Taranto*
36
+
37
+ * **Breaking change**: Upgrade `BlankslateComponent` to use Slots V2.
38
+
39
+ *Manuel Puyol*
40
+
41
+ * **Breaking change**: Upgrade `TimelineItemComponent` to use Slots V2.
42
+
43
+ *Manuel Puyol*
44
+
45
+ ## 0.0.20
46
+
47
+ * Fix bug when empty string was passed to Classify.
48
+
49
+ *Manuel Puyol*
50
+
51
+ ## 0.0.19
52
+
53
+ * Add support for functional colors to `color` system argument.
54
+
55
+ *Jake Shorty*
56
+
57
+ * Add `AvatarStack`, `Dropdown`, `Markdown` and `Menu` components.
58
+
59
+ *Manuel Puyol*
60
+
61
+ * Deprecate `DropdownMenuComponent`.
62
+
63
+ *Manuel Puyol*
64
+
65
+ * Fix `Avatar` bug when used with links.
66
+
67
+ *Manuel Puyol*
68
+
69
+ * Add cache for common Primer values.
70
+
71
+ *Blake Williams*
72
+
73
+ * Add support for `octicons_helper` v12.
74
+
75
+ *Cole Bemis*
76
+
77
+ * Add support for `border: true` to apply the `border` class.
78
+
79
+ *Simon Taranto*
80
+
81
+ * Promote `Avatar`, `Link`, and `Counter` components to beta.
82
+
83
+ *Simon Taranto*
84
+
85
+ * **Breaking change**: Drop support for Ruby 2.4.
86
+
87
+ *Simon Taranto*
88
+
89
+ ## 0.0.18
90
+
91
+ * Add `border_radius` system argument.
92
+
93
+ *Ash Guillaume*
94
+
95
+ * Add `animation` system argument.
96
+
97
+ *Manuel Puyol*
98
+
99
+ * Add `Truncate`, `ButtonGroup` and `ButtonMarketing` components.
100
+
101
+ *Manuel Puyol*
102
+
103
+ * Add `Tooltip` component.
104
+
105
+ *Simon Taranto*
4
106
 
5
107
  ## 0.0.17
6
108
 
@@ -0,0 +1,2 @@
1
+ class t extends HTMLElement{constructor(){super(),this.addEventListener("keydown",(t=>{const r=t.target;if(!(r instanceof HTMLElement))return;if("tab"!==r.getAttribute("role")&&!r.closest('[role="tablist"]'))return;const a=Array.from(this.querySelectorAll('[role="tablist"] [role="tab"]')),n=a.indexOf(a.find((t=>t.matches('[aria-selected="true"]'))));if("ArrowRight"===t.code){let t=n+1;t>=a.length&&(t=0),e(this,t)}else if("ArrowLeft"===t.code){let t=n-1;t<0&&(t=a.length-1),e(this,t)}else"Home"===t.code?(e(this,0),t.preventDefault()):"End"===t.code&&(e(this,a.length-1),t.preventDefault())})),this.addEventListener("click",(t=>{const r=Array.from(this.querySelectorAll('[role="tablist"] [role="tab"]'));if(!(t.target instanceof Element))return;const a=t.target.closest('[role="tab"]');if(!a||!a.closest('[role="tablist"]'))return;e(this,r.indexOf(a))}))}connectedCallback(){for(const t of this.querySelectorAll('[role="tablist"] [role="tab"]'))t.hasAttribute("aria-selected")||t.setAttribute("aria-selected","false"),t.hasAttribute("tabindex")||("true"===t.getAttribute("aria-selected")?t.setAttribute("tabindex","0"):t.setAttribute("tabindex","-1"))}}function e(t,e){const r=t.querySelectorAll('[role="tablist"] [role="tab"]'),a=t.querySelectorAll('[role="tabpanel"]'),n=r[e],i=a[e];if(!!t.dispatchEvent(new CustomEvent("tab-container-change",{bubbles:!0,cancelable:!0,detail:{relatedTarget:i}}))){for(const t of r)t.setAttribute("aria-selected","false"),t.setAttribute("tabindex","-1");for(const t of a)t.hidden=!0,t.hasAttribute("tabindex")||t.hasAttribute("data-tab-container-no-tabstop")||t.setAttribute("tabindex","0");n.setAttribute("aria-selected","true"),n.setAttribute("tabindex","0"),n.focus(),i.hidden=!1,t.dispatchEvent(new CustomEvent("tab-container-changed",{bubbles:!0,detail:{relatedTarget:i}}))}}window.customElements.get("tab-container")||(window.TabContainerElement=t,window.customElements.define("tab-container",t));
2
+ //# sourceMappingURL=primer_view_components.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primer_view_components.js","sources":["../../../node_modules/@github/tab-container-element/dist/index.js"],"sourcesContent":["export default class TabContainerElement extends HTMLElement {\n constructor() {\n super();\n this.addEventListener('keydown', (event) => {\n const target = event.target;\n if (!(target instanceof HTMLElement))\n return;\n if (target.getAttribute('role') !== 'tab' && !target.closest('[role=\"tablist\"]'))\n return;\n const tabs = Array.from(this.querySelectorAll('[role=\"tablist\"] [role=\"tab\"]'));\n const currentIndex = tabs.indexOf(tabs.find(tab => tab.matches('[aria-selected=\"true\"]')));\n if (event.code === 'ArrowRight') {\n let index = currentIndex + 1;\n if (index >= tabs.length)\n index = 0;\n selectTab(this, index);\n }\n else if (event.code === 'ArrowLeft') {\n let index = currentIndex - 1;\n if (index < 0)\n index = tabs.length - 1;\n selectTab(this, index);\n }\n else if (event.code === 'Home') {\n selectTab(this, 0);\n event.preventDefault();\n }\n else if (event.code === 'End') {\n selectTab(this, tabs.length - 1);\n event.preventDefault();\n }\n });\n this.addEventListener('click', (event) => {\n const tabs = Array.from(this.querySelectorAll('[role=\"tablist\"] [role=\"tab\"]'));\n if (!(event.target instanceof Element))\n return;\n const tab = event.target.closest('[role=\"tab\"]');\n if (!tab || !tab.closest('[role=\"tablist\"]'))\n return;\n const index = tabs.indexOf(tab);\n selectTab(this, index);\n });\n }\n connectedCallback() {\n for (const tab of this.querySelectorAll('[role=\"tablist\"] [role=\"tab\"]')) {\n if (!tab.hasAttribute('aria-selected')) {\n tab.setAttribute('aria-selected', 'false');\n }\n if (!tab.hasAttribute('tabindex')) {\n if (tab.getAttribute('aria-selected') === 'true') {\n tab.setAttribute('tabindex', '0');\n }\n else {\n tab.setAttribute('tabindex', '-1');\n }\n }\n }\n }\n}\nfunction selectTab(tabContainer, index) {\n const tabs = tabContainer.querySelectorAll('[role=\"tablist\"] [role=\"tab\"]');\n const panels = tabContainer.querySelectorAll('[role=\"tabpanel\"]');\n const selectedTab = tabs[index];\n const selectedPanel = panels[index];\n const cancelled = !tabContainer.dispatchEvent(new CustomEvent('tab-container-change', {\n bubbles: true,\n cancelable: true,\n detail: { relatedTarget: selectedPanel }\n }));\n if (cancelled)\n return;\n for (const tab of tabs) {\n tab.setAttribute('aria-selected', 'false');\n tab.setAttribute('tabindex', '-1');\n }\n for (const panel of panels) {\n panel.hidden = true;\n if (!panel.hasAttribute('tabindex') && !panel.hasAttribute('data-tab-container-no-tabstop')) {\n panel.setAttribute('tabindex', '0');\n }\n }\n selectedTab.setAttribute('aria-selected', 'true');\n selectedTab.setAttribute('tabindex', '0');\n selectedTab.focus();\n selectedPanel.hidden = false;\n tabContainer.dispatchEvent(new CustomEvent('tab-container-changed', {\n bubbles: true,\n detail: { relatedTarget: selectedPanel }\n }));\n}\nif (!window.customElements.get('tab-container')) {\n window.TabContainerElement = TabContainerElement;\n window.customElements.define('tab-container', TabContainerElement);\n}\n//# sourceMappingURL=index.js.map"],"names":["TabContainerElement","HTMLElement","[object Object]","super","this","addEventListener","event","target","getAttribute","closest","tabs","Array","from","querySelectorAll","currentIndex","indexOf","find","tab","matches","code","index","length","selectTab","preventDefault","Element","hasAttribute","setAttribute","tabContainer","panels","selectedTab","selectedPanel","dispatchEvent","CustomEvent","bubbles","cancelable","detail","relatedTarget","panel","hidden","focus","window","customElements","get","define"],"mappings":"AAAe,MAAMA,UAA4BC,YAC7CC,cACIC,QACAC,KAAKC,iBAAiB,WAAYC,IAC9B,MAAMC,EAASD,EAAMC,OACrB,KAAMA,aAAkBN,aACpB,OACJ,GAAoC,QAAhCM,EAAOC,aAAa,UAAsBD,EAAOE,QAAQ,oBACzD,OACJ,MAAMC,EAAOC,MAAMC,KAAKR,KAAKS,iBAAiB,kCACxCC,EAAeJ,EAAKK,QAAQL,EAAKM,MAAKC,GAAOA,EAAIC,QAAQ,6BAC/D,GAAmB,eAAfZ,EAAMa,KAAuB,CAC7B,IAAIC,EAAQN,EAAe,EACvBM,GAASV,EAAKW,SACdD,EAAQ,GACZE,EAAUlB,KAAMgB,QAEf,GAAmB,cAAfd,EAAMa,KAAsB,CACjC,IAAIC,EAAQN,EAAe,EACvBM,EAAQ,IACRA,EAAQV,EAAKW,OAAS,GAC1BC,EAAUlB,KAAMgB,OAEI,SAAfd,EAAMa,MACXG,EAAUlB,KAAM,GAChBE,EAAMiB,kBAEc,QAAfjB,EAAMa,OACXG,EAAUlB,KAAMM,EAAKW,OAAS,GAC9Bf,EAAMiB,qBAGdnB,KAAKC,iBAAiB,SAAUC,IAC5B,MAAMI,EAAOC,MAAMC,KAAKR,KAAKS,iBAAiB,kCAC9C,KAAMP,EAAMC,kBAAkBiB,SAC1B,OACJ,MAAMP,EAAMX,EAAMC,OAAOE,QAAQ,gBACjC,IAAKQ,IAAQA,EAAIR,QAAQ,oBACrB,OAEJa,EAAUlB,KADIM,EAAKK,QAAQE,OAInCf,oBACI,IAAK,MAAMe,KAAOb,KAAKS,iBAAiB,iCAC/BI,EAAIQ,aAAa,kBAClBR,EAAIS,aAAa,gBAAiB,SAEjCT,EAAIQ,aAAa,cACwB,SAAtCR,EAAIT,aAAa,iBACjBS,EAAIS,aAAa,WAAY,KAG7BT,EAAIS,aAAa,WAAY,QAMjD,SAASJ,EAAUK,EAAcP,GAC7B,MAAMV,EAAOiB,EAAad,iBAAiB,iCACrCe,EAASD,EAAad,iBAAiB,qBACvCgB,EAAcnB,EAAKU,GACnBU,EAAgBF,EAAOR,GAM7B,KALmBO,EAAaI,cAAc,IAAIC,YAAY,uBAAwB,CAClFC,SAAS,EACTC,YAAY,EACZC,OAAQ,CAAEC,cAAeN,MAE7B,CAEA,IAAK,MAAMb,KAAOP,EACdO,EAAIS,aAAa,gBAAiB,SAClCT,EAAIS,aAAa,WAAY,MAEjC,IAAK,MAAMW,KAAST,EAChBS,EAAMC,QAAS,EACVD,EAAMZ,aAAa,aAAgBY,EAAMZ,aAAa,kCACvDY,EAAMX,aAAa,WAAY,KAGvCG,EAAYH,aAAa,gBAAiB,QAC1CG,EAAYH,aAAa,WAAY,KACrCG,EAAYU,QACZT,EAAcQ,QAAS,EACvBX,EAAaI,cAAc,IAAIC,YAAY,wBAAyB,CAChEC,SAAS,EACTE,OAAQ,CAAEC,cAAeN,OAG5BU,OAAOC,eAAeC,IAAI,mBAC3BF,OAAOxC,oBAAsBA,EAC7BwC,OAAOC,eAAeE,OAAO,gBAAiB3C"}
@@ -7,15 +7,23 @@ module Primer
7
7
  class AvatarComponent < Primer::Component
8
8
  SMALL_THRESHOLD = 24
9
9
 
10
- #
11
- # @example 34|Default
10
+ # @example Default
12
11
  # <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser")) %>
13
12
  #
14
- # @param src [String] The source url of the avatar image
15
- # @param alt [String] Passed through to alt on img tag
16
- # @param size [Integer] Adds the avatar-small class if less than 24
13
+ # @example Square
14
+ # <%= render(Primer::AvatarComponent.new(src: "http://placekitten.com/200/200", alt: "@kittenuser", square: true)) %>
15
+ #
16
+ # @example Link
17
+ # <%= render(Primer::AvatarComponent.new(href: "#", src: "http://placekitten.com/200/200", alt: "@kittenuser")) %>
18
+ #
19
+ # @param src [String] The source url of the avatar image.
20
+ # @param alt [String] Passed through to alt on img tag.
21
+ # @param size [Integer] Adds the avatar-small class if less than 24.
17
22
  # @param square [Boolean] Used to create a square avatar.
18
- def initialize(src:, alt:, size: 20, square: false, **system_arguments)
23
+ # @param href [String] The URL to link to. If used, component will be wrapped by an `<a>` tag.
24
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
25
+ def initialize(src:, alt:, size: 20, square: false, href: nil, **system_arguments)
26
+ @href = href
19
27
  @system_arguments = system_arguments
20
28
  @system_arguments[:tag] = :img
21
29
  @system_arguments[:src] = src
@@ -25,15 +33,25 @@ module Primer
25
33
  @system_arguments[:width] = size
26
34
 
27
35
  @system_arguments[:classes] = class_names(
28
- "avatar",
29
36
  system_arguments[:classes],
37
+ "avatar" => !href,
30
38
  "avatar--small" => size < SMALL_THRESHOLD,
31
- "CircleBadge" => !square
39
+ "circle" => !square
32
40
  )
33
41
  end
34
42
 
35
43
  def call
36
- render(Primer::BaseComponent.new(**@system_arguments)) { content }
44
+ if @href
45
+ render(Primer::LinkComponent.new(href: @href, classes: "avatar")) do
46
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
47
+ end
48
+ else
49
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
50
+ end
51
+ end
52
+
53
+ def self.status
54
+ Primer::Component::STATUSES[:beta]
37
55
  end
38
56
  end
39
57
  end
@@ -0,0 +1,10 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <%= render body_component do %>
3
+ <% avatars.each_with_index do |avatar, i| %>
4
+ <% if i == 2 %>
5
+ <div class="avatar avatar-more"></div>
6
+ <% end %>
7
+ <%= avatar %>
8
+ <% end %>
9
+ <% end %>
10
+ <% end %>
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ # Use AvatarStack to stack multiple avatars together.
5
+ class AvatarStackComponent < Primer::Component
6
+ include ViewComponent::SlotableV2
7
+
8
+ ALIGN_DEFAULT = :left
9
+ ALIGN_OPTIONS = [ALIGN_DEFAULT, :right].freeze
10
+
11
+ # Required list of stacked avatars.
12
+ #
13
+ # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::AvatarComponent) %>.
14
+ renders_many :avatars, Primer::AvatarComponent
15
+
16
+ # @example Default
17
+ # <%= render(Primer::AvatarStackComponent.new) do |c| %>
18
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
19
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
20
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
21
+ # <% end %>
22
+ #
23
+ # @example Align right
24
+ # <%= render(Primer::AvatarStackComponent.new(align: :right)) do |c| %>
25
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
26
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
27
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
28
+ # <% end %>
29
+ #
30
+ # @example With tooltip
31
+ # <%= render(Primer::AvatarStackComponent.new(tooltipped: true, body_arguments: { label: 'This is a tooltip!' })) do |c| %>
32
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
33
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
34
+ # <%= c.avatar(src: "http://placekitten.com/200/200", alt: "@kittenuser") %>
35
+ # <% end %>
36
+ #
37
+ # @param align [Symbol] <%= one_of(Primer::AvatarStackComponent::ALIGN_OPTIONS) %>
38
+ # @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) %>.
40
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
41
+ def initialize(align: ALIGN_DEFAULT, tooltipped: false, body_arguments: {}, **system_arguments)
42
+ @align = fetch_or_fallback(ALIGN_OPTIONS, align, ALIGN_DEFAULT)
43
+ @system_arguments = system_arguments
44
+ @tooltipped = tooltipped
45
+ @body_arguments = body_arguments
46
+
47
+ @body_arguments[:tag] ||= :div
48
+ @body_arguments[:classes] = class_names(
49
+ "AvatarStack-body",
50
+ @body_arguments[:classes]
51
+ )
52
+
53
+ @system_arguments[:tag] ||= :div
54
+ @system_arguments[:classes] = class_names(
55
+ "AvatarStack",
56
+ system_arguments[:classes],
57
+ "AvatarStack--right" => @align == :right
58
+ )
59
+ end
60
+
61
+ def body_component
62
+ if @tooltipped
63
+ Primer::TooltipComponent.new(**@body_arguments)
64
+ else
65
+ Primer::BaseComponent.new(**@body_arguments)
66
+ end
67
+ end
68
+
69
+ def before_render
70
+ @system_arguments[:classes] = class_names(
71
+ @system_arguments[:classes],
72
+ "AvatarStack--two" => avatars.size == 2,
73
+ "AvatarStack--three-plus" => avatars.size > 2
74
+ )
75
+ end
76
+
77
+ def render?
78
+ avatars.any?
79
+ end
80
+ end
81
+ end
@@ -41,7 +41,7 @@ module Primer
41
41
  # @param test_selector [String] Adds `data-test-selector='given value'` in non-Production environments for testing purposes.
42
42
  #
43
43
  # @param m [Integer] Margin. <%= one_of((-6..6).to_a) %>
44
- # @param mt [Integer] Margin left. <%= one_of((-6..6).to_a) %>
44
+ # @param mt [Integer] Margin top. <%= one_of((-6..6).to_a) %>
45
45
  # @param mr [Integer] Margin right. <%= one_of((-6..6).to_a) %>
46
46
  # @param mb [Integer] Margin bottom. <%= one_of((-6..6).to_a) %>
47
47
  # @param ml [Integer] Margin left. <%= one_of((-6..6).to_a) %>
@@ -62,7 +62,7 @@ module Primer
62
62
  # @param bottom [Boolean] If `false`, sets `bottom: 0`.
63
63
  # @param left [Boolean] If `false`, sets `left: 0`.
64
64
  #
65
- # @param display [Symbol] <%= one_of([:block, :none, :inline, :inline_block, :table, :table_cell]) %>
65
+ # @param display [Symbol] <%= one_of([:none, :block, :flex, :inline, :inline_block, :table, :table_cell]) %>
66
66
  #
67
67
  # @param v [Symbol] Visibility. <%= one_of([:hidden, :visible]) %>
68
68
  #
@@ -76,16 +76,17 @@ module Primer
76
76
  #
77
77
  # @param underline [Boolean] Whether text should be underlined.
78
78
  #
79
- # @param color [Symbol] Text color. <%= one_of([:blue, :red, :gray_light, :gray, :gray_dark, :green, :orange, :orange_light, :purple, :pink, :white, :inherit]) %> Note: this API is subject to change as we move to functional colors.
79
+ # @param color [Symbol] Text color. <%= one_of([:blue, :red, :gray_light, :gray, :gray_dark, :green, :orange, :orange_light, :purple, :pink, :white, :inherit, :text_primary, :text_secondary, :text_tertiary, :text_link, :text_success, :text_warning, :text_danger, :icon_primary, :icon_secondary, :icon_tertiary, :icon_info, :icon_success, :icon_warning, :icon_danger]) %>
80
80
  # @param bg [String, Symbol] Background color. Accepts either a hex value as a String or a color name as a Symbol.
81
81
  #
82
82
  # @param box_shadow [Boolean, Symbol] Box shadow. <%= one_of([true, :medium, :large, :extra_large, :none]) %>
83
- # @param border [Symbol] <%= one_of([:left, :top, :bottom, :right, :y, :x]) %>
83
+ # @param border [Symbol] <%= one_of([:left, :top, :bottom, :right, :y, :x, true]) %>
84
84
  # @param border_color [Symbol] <%= one_of([:blue, :blue_light, :gray, :gray_dark, :green, :purple, :red, :red_light, :white, :yellow, :black_fade]) %> Note: this API is subject to change as we move to functional colors.
85
85
  # @param border_top [Integer] Set to `0` to remove the top border.
86
86
  # @param border_bottom [Integer] Set to `0` to remove the bottom border.
87
87
  # @param border_left [Integer] Set to `0` to remove the left border.
88
88
  # @param border_right [Integer] Set to `0` to remove the right border.
89
+ # @param border_radius [Integer] <%= one_of([0, 1, 2, 3]) %>
89
90
  #
90
91
  # @param font_size [String, Integer] <%= one_of(["00", 0, 1, 2, 3, 4, 5, 6]) %>
91
92
  # @param text_align [Symbol] Text alignment. <%= one_of([:left, :right, :center]) %>
@@ -102,6 +103,8 @@ module Primer
102
103
  #
103
104
  # @param word_break [Symbol] Whether to break words on line breaks. Can only be `:break_all`.
104
105
  #
106
+ # @param animation [Symbol] <%= one_of([:fade_in, :fade_out, :fade_up, :fade_down, :scale_in, :pulse, :grow_x, :grow]) %>
107
+ #
105
108
  # @param tag [Symbol] HTML tag name to be passed to `tag.send`.
106
109
  # @param classes [String] CSS class name value to be concatenated with generated Primer CSS classes.
107
110
  def initialize(tag:, classes: nil, **system_arguments)
@@ -113,7 +116,7 @@ module Primer
113
116
  end
114
117
 
115
118
  def call
116
- content_tag(@tag, content, **@content_tag_args.merge(@result))
119
+ content_tag(@tag, content, @content_tag_args.merge(@result))
117
120
  end
118
121
 
119
122
  private
@@ -1,12 +1,12 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
2
  <% if spinner.present? %>
3
- <%= render spinner.component %>
3
+ <%= spinner %>
4
4
  <% elsif @icon.present? %>
5
- <%= render(Primer::OcticonComponent.new(
5
+ <%= primer(:octicon,
6
6
  icon: @icon,
7
7
  size: @icon_size,
8
8
  classes: "blankslate-icon"
9
- )) %>
9
+ ) %>
10
10
  <% elsif @image_src.present? && @image_alt.present? %>
11
11
  <%= image_tag "#{@image_src}", class: "mb-3", size: "56x56", alt: "#{@image_alt}" %>
12
12
  <% end %>
@@ -3,40 +3,46 @@
3
3
  module Primer
4
4
  # Use Primer::BlankslateComponent 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
  class BlankslateComponent < Primer::Component
6
- include ViewComponent::Slotable
6
+ include ViewComponent::SlotableV2
7
7
 
8
- with_slot :spinner, class_name: "Spinner"
8
+ # Optional Spinner.
9
+ #
10
+ # @param kwargs [Hash] The same arguments as <%= link_to_component(Primer::SpinnerComponent) %>.
11
+ renders_one :spinner, lambda { |**system_arguments|
12
+ system_arguments[:mb] ||= 3
13
+ Primer::SpinnerComponent.new(**system_arguments)
14
+ }
9
15
 
10
16
  #
11
- # @example 150|Basic
17
+ # @example Basic
12
18
  # <%= render Primer::BlankslateComponent.new(
13
19
  # title: "Title",
14
20
  # description: "Description",
15
21
  # ) %>
16
22
  #
17
- # @example 190|Icon|Add an `icon` to give additional context. Refer to the [Octicons](https://primer.style/octicons/) documentation to choose an icon.
23
+ # @example Icon|Add an `icon` to give additional context. Refer to the [Octicons](https://primer.style/octicons/) documentation to choose an icon.
18
24
  # <%= render Primer::BlankslateComponent.new(
19
25
  # icon: "octoface",
20
26
  # title: "Title",
21
27
  # description: "Description",
22
28
  # ) %>
23
29
  #
24
- # @example 220|Loading|Add a [SpinnerComponent](https://primer.style/view-components/components/spinner) to the blankslate in place of an icon.
30
+ # @example Loading|Add a [SpinnerComponent](https://primer.style/view-components/components/spinner) to the blankslate in place of an icon.
25
31
  # <%= render Primer::BlankslateComponent.new(
26
32
  # title: "Title",
27
33
  # description: "Description",
28
34
  # ) do |component| %>
29
- # <% component.slot(:spinner, size: :large) %>
35
+ # <% component.spinner(size: :large) %>
30
36
  # <% end %>
31
37
  #
32
- # @example 150|Custom content|Pass custom content as a block in place of `description`.
38
+ # @example Custom content|Pass custom content as a block in place of `description`.
33
39
  # <%= render Primer::BlankslateComponent.new(
34
40
  # title: "Title",
35
41
  # ) do %>
36
42
  # <em>Your custom content here</em>
37
43
  # <% end %>
38
44
  #
39
- # @example 270|Action button|Provide a button to guide users to take action from the blankslate. The button appears below the description and custom content.
45
+ # @example Action button|Provide a button to guide users to take action from the blankslate. The button appears below the description and custom content.
40
46
  # <%= render Primer::BlankslateComponent.new(
41
47
  # icon: "book",
42
48
  # title: "Welcome to the mona wiki!",
@@ -46,7 +52,7 @@ module Primer
46
52
  # button_url: "https://github.com/monalisa/mona/wiki/_new",
47
53
  # ) %>
48
54
  #
49
- # @example 225|Link|Add an additional link to help users learn more about a feature. The link will be shown at the very bottom:
55
+ # @example Link|Add an additional link to help users learn more about a feature. The link will be shown at the very bottom:
50
56
  # <%= render Primer::BlankslateComponent.new(
51
57
  # icon: "book",
52
58
  # title: "Welcome to the mona wiki!",
@@ -55,7 +61,7 @@ module Primer
55
61
  # link_url: "https://docs.github.com/en/github/building-a-strong-community/about-wikis",
56
62
  # ) %>
57
63
  #
58
- # @example 340|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.
64
+ # @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.
59
65
  # <%= render Primer::BlankslateComponent.new(
60
66
  # icon: "book",
61
67
  # title: "Welcome to the mona wiki!",
@@ -94,7 +100,7 @@ module Primer
94
100
  link_text: "",
95
101
  link_url: "",
96
102
 
97
- #variations
103
+ # variations
98
104
  narrow: false,
99
105
  large: false,
100
106
  spacious: false,
@@ -108,7 +114,7 @@ module Primer
108
114
  "blankslate",
109
115
  "blankslate-narrow": narrow,
110
116
  "blankslate-large": large,
111
- "blankslate-spacious": spacious,
117
+ "blankslate-spacious": spacious
112
118
  )
113
119
 
114
120
  @title_tag = title_tag
@@ -124,18 +130,5 @@ module Primer
124
130
  @link_text = link_text
125
131
  @link_url = link_url
126
132
  end
127
-
128
- class Spinner < Primer::Slot
129
- # @param size [Symbol] <%= one_of(Primer::SpinnerComponent::SIZE_MAPPINGS) %>
130
- # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
131
- def initialize(**system_arguments)
132
- @system_arguments = system_arguments
133
- @system_arguments[:mb] ||= 3
134
- end
135
-
136
- def component
137
- Primer::SpinnerComponent.new(**@system_arguments)
138
- end
139
- end
140
133
  end
141
134
  end