primer_view_components 0.1.8 → 0.2.0

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 (209) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +79 -0
  3. data/README.md +1 -1
  4. data/app/assets/javascripts/primer_view_components.js +1 -1
  5. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  6. data/app/assets/styles/primer_view_components.css +1 -3
  7. data/app/assets/styles/primer_view_components.css.map +1 -1
  8. data/app/components/primer/alpha/action_list/item.rb +3 -5
  9. data/app/components/primer/alpha/action_list.css +1 -1
  10. data/app/components/primer/alpha/action_list.css.json +16 -16
  11. data/app/components/primer/alpha/action_list.css.map +1 -1
  12. data/app/components/primer/alpha/action_list.pcss +145 -145
  13. data/app/components/primer/alpha/action_list.rb +30 -15
  14. data/app/components/primer/alpha/action_menu/action_menu_element.d.ts +2 -1
  15. data/app/components/primer/alpha/action_menu/action_menu_element.js +44 -34
  16. data/app/components/primer/alpha/action_menu/action_menu_element.ts +32 -30
  17. data/app/components/primer/alpha/action_menu/list.rb +6 -1
  18. data/app/components/primer/alpha/action_menu.rb +1 -1
  19. data/app/components/primer/alpha/auto_complete.css +1 -1
  20. data/app/components/primer/alpha/auto_complete.css.map +1 -1
  21. data/app/components/primer/alpha/auto_complete.pcss +3 -3
  22. data/app/components/primer/alpha/banner.css +1 -1
  23. data/app/components/primer/alpha/banner.css.map +1 -1
  24. data/app/components/primer/alpha/banner.pcss +11 -11
  25. data/app/components/primer/alpha/button_marketing.css.map +1 -1
  26. data/app/components/primer/alpha/button_marketing.pcss +5 -12
  27. data/app/components/primer/alpha/button_marketing.rb +3 -0
  28. data/app/components/primer/alpha/dialog.css +1 -1
  29. data/app/components/primer/alpha/dialog.css.map +1 -1
  30. data/app/components/primer/alpha/dialog.pcss +36 -36
  31. data/app/components/primer/alpha/dropdown.css +1 -1
  32. data/app/components/primer/alpha/dropdown.css.map +1 -1
  33. data/app/components/primer/alpha/dropdown.pcss +12 -12
  34. data/app/components/primer/alpha/form_control.html.erb +1 -1
  35. data/app/components/primer/alpha/hellip_button.rb +3 -1
  36. data/app/components/primer/alpha/layout.css +1 -1
  37. data/app/components/primer/alpha/layout.css.map +1 -1
  38. data/app/components/primer/alpha/layout.pcss +4 -4
  39. data/app/components/primer/alpha/menu.css +1 -1
  40. data/app/components/primer/alpha/menu.css.map +1 -1
  41. data/app/components/primer/alpha/menu.pcss +21 -21
  42. data/app/components/primer/alpha/modal_dialog.js +17 -4
  43. data/app/components/primer/alpha/modal_dialog.ts +17 -4
  44. data/app/components/primer/alpha/nav_list/item.rb +2 -0
  45. data/app/components/primer/alpha/nav_list.js +6 -0
  46. data/app/components/primer/alpha/nav_list.rb +55 -36
  47. data/app/components/primer/alpha/nav_list.ts +8 -0
  48. data/app/components/primer/alpha/octicon_symbols.html.erb +1 -1
  49. data/app/components/primer/alpha/overlay/header.html.erb +5 -3
  50. data/app/components/primer/alpha/overlay/header.rb +4 -1
  51. data/app/components/primer/alpha/overlay.css +1 -1
  52. data/app/components/primer/alpha/overlay.css.json +1 -2
  53. data/app/components/primer/alpha/overlay.css.map +1 -1
  54. data/app/components/primer/alpha/overlay.pcss +14 -4
  55. data/app/components/primer/alpha/overlay.rb +1 -0
  56. data/app/components/primer/alpha/segmented_control.css +1 -1
  57. data/app/components/primer/alpha/segmented_control.css.map +1 -1
  58. data/app/components/primer/alpha/segmented_control.pcss +24 -33
  59. data/app/components/primer/alpha/tab_nav.css +1 -1
  60. data/app/components/primer/alpha/tab_nav.css.map +1 -1
  61. data/app/components/primer/alpha/tab_nav.pcss +12 -12
  62. data/app/components/primer/alpha/text_field.css +1 -3
  63. data/app/components/primer/alpha/text_field.css.json +1 -0
  64. data/app/components/primer/alpha/text_field.css.map +1 -1
  65. data/app/components/primer/alpha/text_field.pcss +87 -83
  66. data/app/components/primer/alpha/toggle_switch.css +1 -1
  67. data/app/components/primer/alpha/toggle_switch.css.json +11 -11
  68. data/app/components/primer/alpha/toggle_switch.css.map +1 -1
  69. data/app/components/primer/alpha/toggle_switch.d.ts +1 -1
  70. data/app/components/primer/alpha/toggle_switch.html.erb +2 -2
  71. data/app/components/primer/alpha/toggle_switch.js +44 -42
  72. data/app/components/primer/alpha/toggle_switch.pcss +16 -16
  73. data/app/components/primer/alpha/toggle_switch.rb +7 -0
  74. data/app/components/primer/alpha/toggle_switch.ts +50 -41
  75. data/app/components/primer/alpha/underline_nav.css +1 -1
  76. data/app/components/primer/alpha/underline_nav.css.map +1 -1
  77. data/app/components/primer/alpha/underline_nav.pcss +11 -11
  78. data/app/components/primer/beta/auto_complete.rb +1 -1
  79. data/app/components/primer/beta/avatar.css +1 -1
  80. data/app/components/primer/beta/avatar.css.map +1 -1
  81. data/app/components/primer/beta/avatar.pcss +18 -18
  82. data/app/components/primer/beta/avatar_stack.css +1 -1
  83. data/app/components/primer/beta/avatar_stack.css.map +1 -1
  84. data/app/components/primer/beta/avatar_stack.pcss +5 -5
  85. data/app/components/primer/beta/base_button.rb +11 -0
  86. data/app/components/primer/beta/blankslate.css +1 -1
  87. data/app/components/primer/beta/blankslate.css.map +1 -1
  88. data/app/components/primer/beta/blankslate.pcss +16 -16
  89. data/app/components/primer/beta/border_box.css +1 -1
  90. data/app/components/primer/beta/border_box.css.json +1 -1
  91. data/app/components/primer/beta/border_box.css.map +1 -1
  92. data/app/components/primer/beta/border_box.pcss +40 -42
  93. data/app/components/primer/beta/button.css +1 -1
  94. data/app/components/primer/beta/button.css.json +4 -0
  95. data/app/components/primer/beta/button.css.map +1 -1
  96. data/app/components/primer/beta/button.pcss +39 -24
  97. data/app/components/primer/beta/button.rb +3 -0
  98. data/app/components/primer/beta/button_group.css +1 -0
  99. data/app/components/primer/beta/button_group.css.json +14 -0
  100. data/app/components/primer/beta/button_group.css.map +1 -0
  101. data/app/components/primer/beta/button_group.pcss +27 -0
  102. data/app/components/primer/beta/button_group.rb +19 -19
  103. data/app/components/primer/beta/close_button.rb +3 -1
  104. data/app/components/primer/beta/counter.css +1 -1
  105. data/app/components/primer/beta/counter.css.map +1 -1
  106. data/app/components/primer/beta/counter.pcss +5 -5
  107. data/app/components/primer/beta/details.html.erb +6 -2
  108. data/app/components/primer/beta/details.rb +18 -10
  109. data/app/components/primer/beta/flash.css +1 -1
  110. data/app/components/primer/beta/flash.css.map +1 -1
  111. data/app/components/primer/beta/flash.pcss +12 -12
  112. data/app/components/primer/beta/icon_button.rb +7 -3
  113. data/app/components/primer/beta/label.css +1 -1
  114. data/app/components/primer/beta/label.css.map +1 -1
  115. data/app/components/primer/beta/label.pcss +3 -3
  116. data/app/components/primer/beta/popover.css +1 -1
  117. data/app/components/primer/beta/popover.css.map +1 -1
  118. data/app/components/primer/beta/popover.pcss +4 -4
  119. data/app/components/primer/beta/state.css +1 -1
  120. data/app/components/primer/beta/state.css.map +1 -1
  121. data/app/components/primer/beta/state.pcss +7 -7
  122. data/app/components/primer/beta/subhead.css +1 -1
  123. data/app/components/primer/beta/subhead.css.map +1 -1
  124. data/app/components/primer/beta/subhead.pcss +9 -9
  125. data/app/components/primer/beta/timeline_item.css +1 -1
  126. data/app/components/primer/beta/timeline_item.css.map +1 -1
  127. data/app/components/primer/beta/timeline_item.pcss +18 -18
  128. data/app/components/primer/beta/truncate.css +1 -1
  129. data/app/components/primer/beta/truncate.css.map +1 -1
  130. data/app/components/primer/beta/truncate.pcss +1 -1
  131. data/app/components/primer/focus_group.js +8 -13
  132. data/app/components/primer/focus_group.ts +8 -12
  133. data/app/components/primer/primer.d.ts +1 -0
  134. data/app/components/primer/primer.js +1 -0
  135. data/app/components/primer/primer.pcss +1 -0
  136. data/app/components/primer/primer.ts +1 -0
  137. data/lib/postcss_mixins/activeIndicatorLine.pcss +4 -4
  138. data/lib/primer/accessibility.rb +74 -0
  139. data/lib/primer/forms/dsl/input.rb +4 -8
  140. data/lib/primer/forms/dsl/text_field_input.rb +0 -4
  141. data/lib/primer/forms/dsl/toggle_switch_input.rb +4 -0
  142. data/lib/primer/forms/form_control.html.erb +3 -5
  143. data/lib/primer/forms/primer_base_component_wrapper.html.erb +3 -0
  144. data/lib/primer/forms/primer_base_component_wrapper.rb +24 -0
  145. data/lib/primer/forms/toggle_switch.html.erb +3 -3
  146. data/lib/primer/forms/toggle_switch.rb +6 -2
  147. data/lib/primer/forms/toggle_switch_input.js +7 -2
  148. data/lib/primer/forms/toggle_switch_input.ts +9 -2
  149. data/lib/primer/static/generate_info_arch.rb +3 -0
  150. data/lib/primer/static/generate_previews.rb +15 -8
  151. data/lib/primer/view_components/linters/deprecated_components_counter.rb +37 -13
  152. data/lib/primer/view_components/version.rb +2 -2
  153. data/lib/primer/yard/component_manifest.rb +1 -1
  154. data/lib/primer/yard/lookbook_pages_backend.rb +8 -2
  155. data/lib/primer/yard/registry.rb +4 -0
  156. data/previews/pages/forms/03_caption_templates.md.erb +1 -1
  157. data/previews/pages/forms/04_after_content.md.erb +1 -1
  158. data/previews/pages/forms/06_miscellaneous_inputs.md.erb +1 -1
  159. data/previews/pages/forms/07_toggle_switch_forms.md.erb +1 -1
  160. data/previews/primer/alpha/action_menu_preview/two_menus.html.erb +13 -0
  161. data/previews/primer/alpha/action_menu_preview/with_actions.html.erb +21 -0
  162. data/previews/primer/alpha/action_menu_preview.rb +5 -13
  163. data/previews/primer/alpha/button_marketing_preview.rb +3 -2
  164. data/previews/primer/alpha/dialog_preview.rb +4 -3
  165. data/previews/primer/alpha/hellip_button_preview.rb +3 -2
  166. data/previews/primer/alpha/nav_list_preview.rb +1 -1
  167. data/previews/primer/alpha/overlay_preview/middle_of_page_with_relative_container.html.erb +19 -0
  168. data/previews/primer/alpha/overlay_preview.rb +31 -0
  169. data/previews/primer/beta/base_button_preview.rb +9 -2
  170. data/previews/primer/beta/button_group_preview/action_menus.html.erb +8 -0
  171. data/previews/primer/beta/button_group_preview.rb +49 -11
  172. data/previews/primer/beta/button_preview/trailing_counter.html.erb +1 -1
  173. data/previews/primer/beta/button_preview.rb +5 -2
  174. data/previews/primer/beta/close_button_preview.rb +3 -2
  175. data/previews/primer/beta/details_preview.rb +11 -8
  176. data/previews/primer/forms_preview.rb +44 -0
  177. data/static/arguments.json +11 -5
  178. data/static/classes.json +378 -372
  179. data/static/constants.json +0 -1
  180. data/static/info_arch.json +5457 -1364
  181. data/static/previews.json +5197 -1428
  182. metadata +40 -36
  183. data/lib/tasks/docs.rake +0 -185
  184. data/lib/tasks/helpers/ast_processor.rb +0 -44
  185. data/lib/tasks/helpers/ast_traverser.rb +0 -77
  186. data/lib/tasks/primer_view_components.rake +0 -47
  187. data/lib/tasks/static.rake +0 -29
  188. data/lib/tasks/test.rake +0 -83
  189. data/lib/tasks/utilities.rake +0 -109
  190. data/previews/primer/forms/forms_preview.rb +0 -48
  191. /data/previews/primer/{forms/forms_preview → forms_preview}/after_content_form.html.erb +0 -0
  192. /data/previews/primer/{forms/forms_preview → forms_preview}/array_check_box_group_form.html.erb +0 -0
  193. /data/previews/primer/{forms/forms_preview → forms_preview}/caption_template_form.html.erb +0 -0
  194. /data/previews/primer/{forms/forms_preview → forms_preview}/check_box_group_form.html.erb +0 -0
  195. /data/previews/primer/{forms/forms_preview → forms_preview}/check_box_with_nested_form.html.erb +0 -0
  196. /data/previews/primer/{forms/forms_preview → forms_preview}/composed_form.html.erb +0 -0
  197. /data/previews/primer/{forms/forms_preview → forms_preview}/example_toggle_switch_form.html.erb +0 -0
  198. /data/previews/primer/{forms/forms_preview → forms_preview}/horizontal_form.html.erb +0 -0
  199. /data/previews/primer/{forms/forms_preview → forms_preview}/immediate_validation_form.html.erb +0 -0
  200. /data/previews/primer/{forms/forms_preview → forms_preview}/invalid_form.html.erb +0 -0
  201. /data/previews/primer/{forms/forms_preview → forms_preview}/multi_input_form.html.erb +0 -0
  202. /data/previews/primer/{forms/forms_preview → forms_preview}/multi_text_field_form.html.erb +0 -0
  203. /data/previews/primer/{forms/forms_preview → forms_preview}/name_with_question_mark_form.html.erb +0 -0
  204. /data/previews/primer/{forms/forms_preview → forms_preview}/radio_button_group_form.html.erb +0 -0
  205. /data/previews/primer/{forms/forms_preview → forms_preview}/radio_button_with_nested_form.html.erb +0 -0
  206. /data/previews/primer/{forms/forms_preview → forms_preview}/select_form.html.erb +0 -0
  207. /data/previews/primer/{forms/forms_preview → forms_preview}/single_text_field_form.html.erb +0 -0
  208. /data/previews/primer/{forms/forms_preview → forms_preview}/submit_button_form.html.erb +0 -0
  209. /data/previews/primer/{forms/forms_preview → forms_preview}/text_field_and_checkbox_form.html.erb +0 -0
@@ -9,11 +9,9 @@
9
9
  <% end %>
10
10
  <% end %>
11
11
  <%= content %>
12
- <% if @input.need_validation_element? %>
13
- <%= content_tag(:div, **@input.validation_arguments) do %>
14
- <%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %>
15
- <%= content_tag(:span, @input.validation_messages.first, **@input.validation_message_arguments) %>
16
- <% end %>
12
+ <%= content_tag(:div, **@input.validation_arguments) do %>
13
+ <span class="FormControl-inlineValidation--visual"><%= render(Primer::Beta::Octicon.new(icon: :"alert-fill", size: :xsmall, aria: { hidden: true })) %></span>
14
+ <%= content_tag(:span, @input.invalid? ? @input.validation_messages.first : "", **@input.validation_message_arguments) %>
17
15
  <% end %>
18
16
  <%= render(Caption.new(input: @input)) %>
19
17
  <% end %>
@@ -0,0 +1,3 @@
1
+ <%= render(Primer::BaseComponent.new(classes: @classes, **@system_arguments)) do %>
2
+ <%= content %>
3
+ <% end %>
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "primer/class_name_helper"
4
+
5
+ module Primer
6
+ module Forms
7
+ # Wraps Primer::BaseComponent.
8
+ class PrimerBaseComponentWrapper < BaseComponent
9
+ include Primer::ClassNameHelper
10
+
11
+ def initialize(**system_arguments)
12
+ @system_arguments = system_arguments
13
+
14
+ # Extract class and classes so they can be passed to Primer::BaseComponent
15
+ # as classes:. The class: argument is expected by Rails, but Primer expects
16
+ # classes:, reminiscent of HashWithIndifferentAccess shenanigans.
17
+ @classes = class_names(
18
+ system_arguments.delete(:classes),
19
+ system_arguments.delete(:class)
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,6 +1,6 @@
1
- <%= content_tag("toggle-switch-input", **@input.input_arguments) do %>
1
+ <%= content_tag("toggle-switch-input", class: "FormControl-toggleSwitchInput", hidden: @input.hidden?) do %>
2
2
  <span style="flex-grow: 1">
3
- <%= builder.label(@input.name, **@input.label_arguments) do %>
3
+ <%= render(Primer::Forms::PrimerBaseComponentWrapper.new(tag: :span, **@input.label_arguments)) do %>
4
4
  <%= @input.label %>
5
5
  <% end %>
6
6
 
@@ -18,5 +18,5 @@
18
18
  }
19
19
  )
20
20
  %>
21
- <%= render(Primer::Alpha::ToggleSwitch.new(src: @input.src, csrf: csrf)) %>
21
+ <%= render(Primer::Alpha::ToggleSwitch.new(src: @input.src, csrf: csrf, **@input.input_arguments)) %>
22
22
  <% end %>
@@ -9,8 +9,12 @@ module Primer
9
9
  def initialize(input:)
10
10
  @input = input
11
11
  @input.add_label_classes("FormControl-label")
12
- @input.add_input_classes("FormControl-toggleSwitchInput")
13
- @input.input_arguments[:hidden] = "hidden" if @input.hidden?
12
+ @input.label_arguments[:id] = label_id
13
+ @input.add_input_aria(:labelledby, label_id)
14
+ end
15
+
16
+ def label_id
17
+ @label_id ||= "label-#{@input.base_id}"
14
18
  end
15
19
  end
16
20
  end
@@ -1,3 +1,4 @@
1
+ /* eslint-disable custom-elements/expose-class-on-global */
1
2
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -8,11 +9,15 @@ import { controller, target } from '@github/catalyst';
8
9
  let ToggleSwitchInputElement = class ToggleSwitchInputElement extends HTMLElement {
9
10
  connectedCallback() {
10
11
  this.addEventListener('toggleSwitchError', (event) => {
11
- this.validationMessageElement.innerText = event.detail;
12
+ this.validationMessageElement.textContent = event.detail;
12
13
  this.validationElement.removeAttribute('hidden');
13
14
  });
14
15
  this.addEventListener('toggleSwitchSuccess', () => {
15
- this.validationMessageElement.innerText = '';
16
+ this.validationMessageElement.textContent = '';
17
+ this.validationElement.setAttribute('hidden', 'hidden');
18
+ });
19
+ this.addEventListener('toggleSwitchLoading', () => {
20
+ this.validationMessageElement.textContent = '';
16
21
  this.validationElement.setAttribute('hidden', 'hidden');
17
22
  });
18
23
  }
@@ -1,3 +1,5 @@
1
+ /* eslint-disable custom-elements/expose-class-on-global */
2
+
1
3
  import {controller, target} from '@github/catalyst'
2
4
 
3
5
  @controller
@@ -7,12 +9,17 @@ export class ToggleSwitchInputElement extends HTMLElement {
7
9
 
8
10
  connectedCallback() {
9
11
  this.addEventListener('toggleSwitchError', (event: Event) => {
10
- this.validationMessageElement.innerText = (event as CustomEvent).detail
12
+ this.validationMessageElement.textContent = (event as CustomEvent).detail
11
13
  this.validationElement.removeAttribute('hidden')
12
14
  })
13
15
 
14
16
  this.addEventListener('toggleSwitchSuccess', () => {
15
- this.validationMessageElement.innerText = ''
17
+ this.validationMessageElement.textContent = ''
18
+ this.validationElement.setAttribute('hidden', 'hidden')
19
+ })
20
+
21
+ this.addEventListener('toggleSwitchLoading', () => {
22
+ this.validationMessageElement.textContent = ''
16
23
  this.validationElement.setAttribute('hidden', 'hidden')
17
24
  })
18
25
  }
@@ -72,6 +72,9 @@ module Primer
72
72
  memo[component] = {
73
73
  "fully_qualified_name" => component.name,
74
74
  "description" => description,
75
+ "is_form_component" => docs.manifest_entry.form_component?,
76
+ "is_published" => docs.manifest_entry.published?,
77
+ "requires_js" => docs.manifest_entry.requires_js?,
75
78
  **arg_data,
76
79
  "slots" => slot_docs,
77
80
  "methods" => method_docs,
@@ -11,8 +11,8 @@ module Primer
11
11
  class << self
12
12
  def call
13
13
  Lookbook.previews.filter_map do |preview|
14
- next if preview.preview_class.name.start_with?("Docs::")
15
- next if preview.preview_class == Primer::Forms::FormsPreview
14
+ next if preview.preview_class == Primer::FormsPreview
15
+ next if Primer::Accessibility.ignore_preview?(preview.preview_class)
16
16
 
17
17
  component = preview.components.first&.component_class
18
18
 
@@ -29,12 +29,19 @@ module Primer
29
29
  component: class_name,
30
30
  status: component.status.to_s,
31
31
  lookup_path: preview.lookup_path,
32
- examples: preview.examples.map do |example|
33
- {
34
- inspect_path: example.url_path,
35
- preview_path: example.url_path.sub("/inspect/", "/preview/"),
36
- name: example.name
37
- }
32
+ examples: preview.scenarios.flat_map do |parent_scenario|
33
+ scenarios = parent_scenario.type == :scenario_group ? parent_scenario.scenarios : [parent_scenario]
34
+
35
+ scenarios.map do |scenario|
36
+ {
37
+ preview_path: scenario.lookup_path,
38
+ name: scenario.name,
39
+ skip_rules: Primer::Accessibility.axe_rules_to_skip(
40
+ component: component,
41
+ scenario_name: scenario.name
42
+ )
43
+ }
44
+ end
38
45
  end
39
46
  }
40
47
  end
@@ -3,13 +3,10 @@
3
3
  require_relative "helpers/deprecated_components_helpers"
4
4
  require_relative "severity_schema"
5
5
 
6
- require "erblint-github/linters/custom_helpers"
7
-
8
6
  module ERBLint
9
7
  module Linters
10
8
  # Lints against deprecated components
11
- class DeprecatedComponentsCounter < Linter
12
- include CustomHelpers
9
+ class DeprecatedComponentsCounter < BaseLinter
13
10
  include ERBLint::LinterRegistry
14
11
  include Helpers::DeprecatedComponentsHelpers
15
12
 
@@ -25,7 +22,7 @@ module ERBLint
25
22
  deprecated_components.each do |component|
26
23
  next unless code.include?(component)
27
24
 
28
- add_offense(erb_node.loc, message(component))
25
+ add_offense_with_severity(erb_node.loc, message(component))
29
26
  end
30
27
  end
31
28
 
@@ -46,14 +43,41 @@ module ERBLint
46
43
  end
47
44
  end
48
45
 
49
- # this override is necessary because of the github/erblint-github `CustomHelpers`
50
- # module. `counter_correct?` is provided by this module, and calls `add_offense`
51
- # directly. there is no simple way to modify this without updating the gem and
52
- # creating what would likely be an API that is non-standard and/or difficult to use
53
- #
54
- # https://github.com/github/erblint-github/blob/main/lib/erblint-github/linters/custom_helpers.rb
55
- def add_offense(source_range, message, context = nil, severity = nil)
56
- super(source_range, message, context, severity || @config.severity)
46
+ def counter_correct?(processed_source)
47
+ comment_node = nil
48
+ expected_count = 0
49
+ rule_name = self.class.name.gsub("ERBLint::Linters::", "")
50
+ offenses_count = @offenses.length
51
+
52
+ processed_source.parser.ast.descendants(:erb).each do |node|
53
+ indicator_node, _, code_node, = *node
54
+ indicator = indicator_node&.loc&.source
55
+ comment = code_node&.loc&.source&.strip
56
+
57
+ if indicator == "#" && comment.start_with?("erblint:counter") && comment.match(rule_name)
58
+ comment_node = node
59
+ expected_count = comment.match(/\s(\d+)\s?$/)[1].to_i
60
+ end
61
+ end
62
+
63
+ if offenses_count.zero?
64
+ # have to adjust to get `\n` so we delete the whole line
65
+ add_offense_with_severity(processed_source.to_source_range(comment_node.loc.adjust(end_pos: 1)), "Unused erblint:counter comment for #{rule_name}", "") if comment_node
66
+ return
67
+ end
68
+
69
+ first_offense = @offenses[0]
70
+
71
+ if comment_node.nil?
72
+ add_offense_with_severity(processed_source.to_source_range(first_offense.source_range), "#{rule_name}: If you must, add <%# erblint:counter #{rule_name} #{offenses_count} %> to bypass this check.", "<%# erblint:counter #{rule_name} #{offenses_count} %>")
73
+ else
74
+ clear_offenses
75
+ add_offense_with_severity(processed_source.to_source_range(comment_node.loc), "Incorrect erblint:counter number for #{rule_name}. Expected: #{expected_count}, actual: #{offenses_count}.", "<%# erblint:counter #{rule_name} #{offenses_count} %>") if expected_count != offenses_count
76
+ end
77
+ end
78
+
79
+ def add_offense_with_severity(source_range, message, context = nil, severity = nil)
80
+ add_offense(source_range, message, context, severity || @config.severity)
57
81
  end
58
82
  end
59
83
  end
@@ -5,8 +5,8 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 1
9
- PATCH = 8
8
+ MINOR = 2
9
+ PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -129,7 +129,7 @@ module Primer
129
129
  end
130
130
 
131
131
  def ref_for(klass)
132
- ref_cache[klass] ||= ComponentRef.new(klass, COMPONENTS[klass])
132
+ ref_cache[klass] ||= ComponentRef.new(klass, COMPONENTS.fetch(klass, {}))
133
133
  end
134
134
 
135
135
  private
@@ -10,7 +10,7 @@ module Primer
10
10
  PREVIEW_MAP = {
11
11
  Primer::Alpha::TextField => [:single_text_field_form, :multi_text_field_form],
12
12
  Primer::Alpha::TextArea => [],
13
- Primer::Alpha::Select => [:select_list_form],
13
+ Primer::Alpha::Select => [:select_form],
14
14
  Primer::Alpha::MultiInput => [:multi_input_form],
15
15
  Primer::Alpha::RadioButton => [:radio_button_with_nested_form],
16
16
  Primer::Alpha::RadioButtonGroup => [:radio_button_group_form],
@@ -49,7 +49,13 @@ module Primer
49
49
 
50
50
  preview_methods = PREVIEW_MAP[component]
51
51
  preview_erbs = preview_methods.map do |preview_method|
52
- "<%= embed Primer::Forms::FormsPreview, #{preview_method.inspect} %>"
52
+ # rubocop:disable Style/IfUnlessModifier
53
+ if Primer::FormsPreview.instance_methods.exclude?(preview_method)
54
+ raise "Preview '#{preview_method}' does not exist in Primer::FormsPreview"
55
+ end
56
+ # rubocop:enable Style/IfUnlessModifier
57
+
58
+ "<%= embed Primer::FormsPreview, #{preview_method.inspect} %>"
53
59
  end
54
60
  # rubocop:enable Lint/UselessAssignment
55
61
 
@@ -89,6 +89,10 @@ module Primer
89
89
  def a11y_reviewed?
90
90
  metadata[:a11y_reviewed]
91
91
  end
92
+
93
+ def manifest_entry
94
+ @manifest_entry ||= ComponentManifest.ref_for(component)
95
+ end
92
96
  end
93
97
 
94
98
  # Wrapper around an instance of YARD::Registry that provides easy access to component
@@ -27,4 +27,4 @@ In cases where the `caption:` argument _and_ a caption template are provided, th
27
27
 
28
28
  ## Example
29
29
 
30
- <%= embed Primer::Forms::FormsPreview, :caption_template_form %>
30
+ <%= embed Primer::FormsPreview, :caption_template_form %>
@@ -36,4 +36,4 @@ For such cases, Primer forms feature "after" content. Like [caption templates](<
36
36
 
37
37
  ## Example
38
38
 
39
- <%= embed Primer::Forms::FormsPreview, :after_content_form %>
39
+ <%= embed Primer::FormsPreview, :after_content_form %>
@@ -40,4 +40,4 @@ Occasionally it can be appealing to visually distinguish parts of a form from ea
40
40
 
41
41
  ### Example
42
42
 
43
- <%= embed Primer::Forms::FormsPreview, :multi_text_field_form %>
43
+ <%= embed Primer::FormsPreview, :multi_text_field_form %>
@@ -55,4 +55,4 @@ The server can indicate that an error occurred by responding with a non-2xx stat
55
55
 
56
56
  ## Example
57
57
 
58
- <%= embed Primer::Forms::FormsPreview, :example_toggle_switch_form %>
58
+ <%= embed Primer::FormsPreview, :example_toggle_switch_form %>
@@ -0,0 +1,13 @@
1
+ <%= render(Primer::Alpha::ActionMenu.new(menu_id: "menu-1")) do |menu| %>
2
+ <% menu.with_show_button { |button| button.with_trailing_action_icon(icon: :"triangle-down"); "Pac-Man" } %>
3
+ <% menu.with_item(label: "Eat a dot") %>
4
+ <% menu.with_item(label: "Avoid a ghost") %>
5
+ <% menu.with_item(label: "Eat a stunned ghost") %>
6
+ <% end %>
7
+
8
+ <%= render(Primer::Alpha::ActionMenu.new(menu_id: "menu-2")) do |menu| %>
9
+ <% menu.with_show_button { |button| button.with_trailing_action_icon(icon: :"triangle-down"); "Mario Bros" } %>
10
+ <% menu.with_item(label: "Stomp a turtle") %>
11
+ <% menu.with_item(label: "Collect a gold coin") %>
12
+ <% menu.with_item(label: "Save the princess") %>
13
+ <% end %>
@@ -0,0 +1,21 @@
1
+ <script type="text/javascript">
2
+ window.addEventListener('load', function() {
3
+ document.querySelector('button#alert-item').addEventListener('click', (_e) => {
4
+ alert('Foo')
5
+ });
6
+ }, false);
7
+ </script>
8
+
9
+ <%= render(Primer::Alpha::ActionMenu.new) do |component| %>
10
+ <% component.with_show_button { "Trigger" } %>
11
+ <% component.with_item(label: "Alert", tag: :button, id: "alert-item") %>
12
+ <% component.with_item(label: "Navigate", tag: :a, content_arguments: { href: action_menu_landing_path }) %>
13
+ <% component.with_item(label: "Copy text", tag: :"clipboard-copy", content_arguments: { value: "Text to copy" }) %>
14
+ <% component.with_item(
15
+ label: "Submit form",
16
+ href: action_menu_form_action_path,
17
+ form_arguments: {
18
+ name: "foo", value: "bar", method: :post
19
+ }
20
+ ) %>
21
+ <% end %>
@@ -180,19 +180,6 @@ module Primer
180
180
  # @label With actions
181
181
  #
182
182
  def with_actions
183
- render(Primer::Alpha::ActionMenu.new) do |component|
184
- component.with_show_button { "Trigger" }
185
- component.with_item(label: "Alert", tag: :button, content_arguments: { onclick: "alert('Foo')", onkeydown: "if (event.key === 'Enter') { alert(event.key) }" })
186
- component.with_item(label: "Navigate", tag: :a, content_arguments: { href: UrlHelpers.action_menu_landing_path })
187
- component.with_item(label: "Copy text", tag: :"clipboard-copy", content_arguments: { value: "Text to copy" })
188
- component.with_item(
189
- label: "Submit form",
190
- href: UrlHelpers.action_menu_form_action_path,
191
- form_arguments: {
192
- name: "foo", value: "bar", method: :post
193
- }
194
- )
195
- end
196
183
  end
197
184
 
198
185
  # @label Single select form
@@ -284,6 +271,11 @@ module Primer
284
271
  end
285
272
  end
286
273
  end
274
+
275
+ # @label Two menus
276
+ #
277
+ def two_menus
278
+ end
287
279
  end
288
280
  end
289
281
  end
@@ -9,8 +9,9 @@ module Primer
9
9
  # @param variant [Symbol] select [default, large]
10
10
  # @param tag [Symbol] select [button, a]
11
11
  # @param type [Symbol] select [button, submit]
12
- def playground(tag: :button, type: :button, scheme: :default, variant: :default)
13
- render(Primer::Alpha::ButtonMarketing.new(tag: tag, type: type, scheme: scheme, variant: variant)) { "Default" }
12
+ # @param disabled [Boolean]
13
+ def playground(tag: :button, type: :button, scheme: :default, variant: :default, disabled: false)
14
+ render(Primer::Alpha::ButtonMarketing.new(tag: tag, type: type, scheme: scheme, variant: variant, disabled: disabled)) { "Default" }
14
15
  end
15
16
 
16
17
  # @label Default options
@@ -12,15 +12,16 @@ module Primer
12
12
  # @param position [Symbol] select [center, left, right]
13
13
  # @param position_narrow [Symbol] select [inherit, bottom, fullscreen, left, right]
14
14
  # @param visually_hide_title [Boolean] toggle
15
+ # @param disable_button [Boolean] toggle
15
16
  # @param button_text [String] text
16
17
  # @param body_text [String] text
17
18
  # @param icon [Symbol] octicon
18
- def playground(title: "Test Dialog", subtitle: nil, size: :medium, button_text: "Show Dialog", body_text: "Content", position: :center, position_narrow: :fullscreen, visually_hide_title: false, icon: nil)
19
+ def playground(title: "Test Dialog", subtitle: nil, size: :medium, button_text: "Show Dialog", body_text: "Content", position: :center, position_narrow: :fullscreen, visually_hide_title: false, icon: nil, disable_button: false)
19
20
  render(Primer::Alpha::Dialog.new(title: title, subtitle: subtitle, size: size, position: position, position_narrow: position_narrow, visually_hide_title: visually_hide_title)) do |d|
20
21
  if icon.present? && (icon != :none)
21
- d.with_show_button(icon: icon, "aria-label": icon.to_s)
22
+ d.with_show_button(icon: icon, "aria-label": icon.to_s, disabled: disable_button)
22
23
  else
23
- d.with_show_button { button_text }
24
+ d.with_show_button(disabled: disable_button) { button_text }
24
25
  end
25
26
  d.with_body { body_text }
26
27
  end
@@ -16,8 +16,9 @@ module Primer
16
16
  #
17
17
  # @param aria_label [String]
18
18
  # @param inline [Boolean]
19
- def playground(inline: false, aria_label: "No effect")
20
- render(Primer::Alpha::HellipButton.new(inline: inline, "aria-label": aria_label))
19
+ # @param disabled [Boolean]
20
+ def playground(inline: false, aria_label: "No effect", disabled: false)
21
+ render(Primer::Alpha::HellipButton.new(inline: inline, "aria-label": aria_label, disabled: disabled))
21
22
  end
22
23
  end
23
24
  end
@@ -6,7 +6,7 @@ module Primer
6
6
  class NavListPreview < ViewComponent::Preview
7
7
  # @label Playground
8
8
  def playground
9
- render(Primer::Alpha::NavList.new(aria: { label: "Repository settings" }, selected_item_id: :code_review_limits)) do |list|
9
+ render(Primer::Alpha::NavList.new(aria: { label: "Repository settings" }, selected_item_id: :collaborators)) do |list|
10
10
  list.with_heading(title: "Repository settings")
11
11
 
12
12
  list.with_item(label: "General", href: "/general") do |item|
@@ -0,0 +1,19 @@
1
+ <div style="width:100%; height: 400px; display: flex; justify-content: center; align-items: center;">
2
+ <div style="position:relative;">
3
+ <%= render(Primer::Alpha::Overlay.new(
4
+ title: title,
5
+ subtitle: subtitle,
6
+ role: role,
7
+ size: size,
8
+ placement: placement,
9
+ anchor_align: anchor_align,
10
+ anchor_side: anchor_side,
11
+ allow_out_of_bounds: allow_out_of_bounds,
12
+ visually_hide_title: visually_hide_title,
13
+ )) do |d| %>
14
+ <% d.with_header(title: title, size: header_size) %>
15
+ <% d.with_show_button { button_text } %>
16
+ <% d.with_body { body_text } %>
17
+ <% end %>
18
+ </div>
19
+ </div>
@@ -132,6 +132,37 @@ module Primer
132
132
  body_text: body_text
133
133
  })
134
134
  end
135
+
136
+ # @label Middle Of Page with relative container
137
+ #
138
+ # @param title [String] text
139
+ # @param subtitle [String] text
140
+ # @param role [Symbol] select [dialog, menu]
141
+ # @param size [Symbol] select [auto, small, medium, medium_portrait, large, xlarge]
142
+ # @param anchor_align [Symbol] select [start, center, end]
143
+ # @param anchor_side [Symbol] select [inside_top, inside_bottom, inside_left, inside_right, inside_center, outside_top, outside_bottom, outside_left, outside_right]
144
+ # @param allow_out_of_bounds [Boolean] toggle
145
+ # @param visually_hide_title [Boolean] toggle
146
+ #
147
+ # @param header_size [Symbol] select [medium, large]
148
+ # @param button_text [String] text
149
+ # @param body_text [String] text
150
+ def middle_of_page_with_relative_container(title: "Test Overlay", subtitle: nil, role: :dialog, size: :auto, placement: :anchored, anchor_align: :center, anchor_side: :outside_bottom, allow_out_of_bounds: false, visually_hide_title: false, header_size: :medium, button_text: "Show Overlay", body_text: "")
151
+ render_with_template(locals: {
152
+ title: title,
153
+ subtitle: subtitle,
154
+ role: role,
155
+ size: size,
156
+ placement: placement,
157
+ anchor_align: anchor_align,
158
+ anchor_side: anchor_side,
159
+ allow_out_of_bounds: allow_out_of_bounds,
160
+ visually_hide_title: visually_hide_title,
161
+ header_size: header_size,
162
+ button_text: button_text,
163
+ body_text: body_text
164
+ })
165
+ end
135
166
  end
136
167
  end
137
168
  end
@@ -9,8 +9,9 @@ module Primer
9
9
  # @param type [Symbol] select [button, submit]
10
10
  # @param tag [Symbol] select [button, a, summary]
11
11
  # @param block [Boolean] toggle
12
- def playground(tag: :button, block: false, type: :button)
13
- render(Primer::Beta::BaseButton.new(tag: tag, block: block, type: type)) { "Button" }
12
+ # @param disabled [Boolean]
13
+ def playground(tag: :button, block: false, type: :button, disabled: false)
14
+ render(Primer::Beta::BaseButton.new(tag: tag, block: block, type: type, disabled: disabled)) { "Button" }
14
15
  end
15
16
 
16
17
  # @label Default options
@@ -21,6 +22,12 @@ module Primer
21
22
  def default(tag: :button, block: false, type: :button)
22
23
  render(Primer::Beta::BaseButton.new(tag: tag, block: block, type: type)) { "Button" }
23
24
  end
25
+
26
+ # @label Disabled
27
+ #
28
+ def disabled
29
+ render(Primer::Beta::BaseButton.new(disabled: true)) { "Button" }
30
+ end
24
31
  end
25
32
  end
26
33
  end
@@ -0,0 +1,8 @@
1
+ <%= render(Primer::Beta::ButtonGroup.new) do |component| %>
2
+ <% component.with_button() { "Main menu" } %>
3
+ <% component.with_button(icon: "triangle-down", "aria-label": "secondary menu", data: { "menu-id": "my-id" }) %>
4
+ <% end %>
5
+
6
+ <%= render(Primer::Alpha::ActionMenu.new(anchor_align: :end, menu_id: "my-id")) do |component| %>
7
+ <% component.with_item(label: "Item", tag: :button, value: "") %>
8
+ <% end %>
@@ -6,13 +6,13 @@ module Primer
6
6
  class ButtonGroupPreview < ViewComponent::Preview
7
7
  # @label Playground
8
8
  #
9
- # @param size [Symbol] select [medium, small]
10
- def playground(size: :medium)
11
- render(Primer::Beta::ButtonGroup.new(size: size)) do |component|
12
- component.with_button { "Button" }
13
- component.with_button(scheme: :primary) { "Primary" }
14
- component.with_button(scheme: :danger) { "Danger" }
15
- component.with_button(scheme: :outline) { "Outline" }
9
+ # @param size [Symbol] select [small, medium, large]
10
+ # @param scheme [Symbol] select [default, primary, secondary, danger, invisible]
11
+ def playground(size: :medium, scheme: :default)
12
+ render(Primer::Beta::ButtonGroup.new(size: size, scheme: scheme)) do |component|
13
+ component.with_button { "Button 1" }
14
+ component.with_button { "Button 2" }
15
+ component.with_button { "Button 3" }
16
16
  end
17
17
  end
18
18
 
@@ -21,10 +21,48 @@ module Primer
21
21
  # @param size [Symbol] select [medium, small]
22
22
  def default(size: :medium)
23
23
  render(Primer::Beta::ButtonGroup.new(size: size)) do |component|
24
- component.with_button { "Button" }
25
- component.with_button(scheme: :primary) { "Primary" }
26
- component.with_button(scheme: :danger) { "Danger" }
27
- component.with_button(scheme: :outline) { "Outline" }
24
+ component.with_button { "Button 1" }
25
+ component.with_button { "Button 2" }
26
+ component.with_button { "Button 3" }
27
+ end
28
+ end
29
+
30
+ # @label Split button
31
+ #
32
+ # @param size [Symbol] select [medium, small]
33
+ def split_button(size: :medium)
34
+ render(Primer::Beta::ButtonGroup.new(size: size)) do |component|
35
+ component.with_button { "Button 1" }
36
+ component.with_button(icon: "triangle-down", "aria-label": "menu")
37
+ end
38
+ end
39
+
40
+ # @label Icon buttons
41
+ #
42
+ # @param size [Symbol] select [medium, small]
43
+ def icon_buttons(size: :medium)
44
+ render(Primer::Beta::ButtonGroup.new(size: size)) do |component|
45
+ component.with_button(icon: :note, "aria-label": "button 1")
46
+ component.with_button(icon: :rows, "aria-label": "button 2")
47
+ component.with_button(icon: "sort-desc", "aria-label": "button 3")
48
+ end
49
+ end
50
+
51
+ # @label Button group with all tags
52
+ def all_tags
53
+ render(Primer::Beta::ButtonGroup.new) do |component|
54
+ component.with_button(id: "button-1", tag: :button) do |component|
55
+ component.with_tooltip(text: "Button Tooltip")
56
+ "Button 1"
57
+ end
58
+ component.with_button(id: "button-2", tag: :a) do |component|
59
+ component.with_tooltip(text: "Button Tooltip")
60
+ "Button 2"
61
+ end
62
+ component.with_button(id: "button-3", tag: :summary) do |component|
63
+ component.with_tooltip(text: "Button Tooltip")
64
+ "Button 3"
65
+ end
28
66
  end
29
67
  end
30
68
  end
@@ -1,5 +1,5 @@
1
1
  <%= render(Primer::Beta::Button.new(
2
- scheme: :primary,
2
+ scheme: scheme,
3
3
  size: :medium,
4
4
  block: block,
5
5
  id: id,