primer_view_components 0.49.0 → 0.51.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 (84) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -0
  3. data/README.md +20 -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 -1
  7. data/app/assets/styles/primer_view_components.css.map +1 -1
  8. data/app/components/primer/alpha/action_bar_element.js +1 -1
  9. data/app/components/primer/alpha/action_bar_element.ts +1 -1
  10. data/app/components/primer/alpha/action_list/item.rb +2 -1
  11. data/app/components/primer/alpha/action_list.js +1 -1
  12. data/app/components/primer/alpha/action_list.ts +1 -1
  13. data/app/components/primer/alpha/action_menu/action_menu_element.js +1 -1
  14. data/app/components/primer/alpha/action_menu/action_menu_element.ts +1 -1
  15. data/app/components/primer/alpha/layout.rb +6 -2
  16. data/app/components/primer/alpha/segmented_control.js +1 -1
  17. data/app/components/primer/alpha/segmented_control.ts +1 -1
  18. data/app/components/primer/alpha/select_panel.rb +1 -1
  19. data/app/components/primer/alpha/select_panel_element.js +4 -2
  20. data/app/components/primer/alpha/select_panel_element.ts +5 -2
  21. data/app/components/primer/alpha/stack.rb +1 -0
  22. data/app/components/primer/alpha/tab_nav.css +1 -1
  23. data/app/components/primer/alpha/tab_nav.css.json +1 -0
  24. data/app/components/primer/alpha/tab_nav.css.map +1 -1
  25. data/app/components/primer/alpha/tab_nav.pcss +7 -1
  26. data/app/components/primer/alpha/toggle_switch.js +1 -1
  27. data/app/components/primer/alpha/toggle_switch.rb +3 -0
  28. data/app/components/primer/alpha/toggle_switch.ts +1 -1
  29. data/app/components/primer/alpha/tree_view/tree_view.js +1 -1
  30. data/app/components/primer/alpha/tree_view/tree_view.ts +1 -1
  31. data/app/components/primer/alpha/tree_view/tree_view_icon_pair_element.js +1 -1
  32. data/app/components/primer/alpha/tree_view/tree_view_icon_pair_element.ts +1 -1
  33. data/app/components/primer/alpha/tree_view/tree_view_include_fragment_element.js +1 -1
  34. data/app/components/primer/alpha/tree_view/tree_view_include_fragment_element.ts +1 -1
  35. data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.js +25 -2
  36. data/app/components/primer/alpha/tree_view/tree_view_sub_tree_node_element.ts +27 -1
  37. data/app/components/primer/alpha/x_banner.js +1 -1
  38. data/app/components/primer/alpha/x_banner.ts +1 -1
  39. data/app/components/primer/beta/blankslate.css +1 -1
  40. data/app/components/primer/beta/blankslate.css.json +1 -0
  41. data/app/components/primer/beta/blankslate.css.map +1 -1
  42. data/app/components/primer/beta/blankslate.pcss +5 -0
  43. data/app/components/primer/beta/blankslate.rb +1 -0
  44. data/app/components/primer/beta/details_toggle_element.js +1 -1
  45. data/app/components/primer/beta/details_toggle_element.ts +1 -1
  46. data/app/components/primer/beta/nav_list.js +1 -1
  47. data/app/components/primer/beta/nav_list.ts +1 -1
  48. data/app/components/primer/beta/nav_list_group_element.js +1 -1
  49. data/app/components/primer/beta/nav_list_group_element.ts +1 -1
  50. data/app/components/primer/dialog_helper.js +17 -8
  51. data/app/components/primer/dialog_helper.ts +17 -8
  52. data/app/components/primer/scrollable_region.js +1 -1
  53. data/app/components/primer/scrollable_region.ts +1 -1
  54. data/app/controllers/primer/view_components/toggle_switch_controller.rb +2 -2
  55. data/app/forms/check_box_with_nested_form.rb +9 -5
  56. data/app/lib/primer/forms/check_box.rb +28 -0
  57. data/app/lib/primer/forms/dsl/multi_input.rb +3 -1
  58. data/app/lib/primer/forms/dsl/text_field_input.rb +2 -1
  59. data/app/lib/primer/forms/form_control.html.erb +2 -1
  60. data/app/lib/primer/forms/primer_multi_input.js +1 -1
  61. data/app/lib/primer/forms/primer_multi_input.ts +1 -1
  62. data/app/lib/primer/forms/primer_text_area.js +1 -1
  63. data/app/lib/primer/forms/primer_text_area.ts +1 -1
  64. data/app/lib/primer/forms/primer_text_field.js +1 -1
  65. data/app/lib/primer/forms/primer_text_field.ts +1 -1
  66. data/app/lib/primer/forms/text_field.html.erb +1 -1
  67. data/app/lib/primer/forms/toggle_switch_input.js +1 -1
  68. data/app/lib/primer/forms/toggle_switch_input.ts +1 -1
  69. data/lib/primer/accessibility.rb +9 -3
  70. data/lib/primer/view_components/engine.rb +1 -4
  71. data/lib/primer/view_components/version.rb +1 -1
  72. data/previews/primer/alpha/form_control_preview/playground.html.erb +4 -2
  73. data/previews/primer/alpha/octicon_symbols_preview/playground.html.erb +1 -1
  74. data/previews/primer/alpha/overlay_preview.rb +0 -25
  75. data/previews/primer/alpha/text_area_preview.rb +11 -11
  76. data/previews/primer/alpha/text_field_preview.rb +9 -0
  77. data/previews/primer/alpha/toggle_switch_preview.rb +14 -14
  78. data/previews/primer/beta/button_preview/all_schemes.html.erb +1 -1
  79. data/previews/primer/beta/button_preview/invisible_all_visuals.html.erb +1 -1
  80. data/previews/primer/beta/button_preview/summary_as_button.html.erb +9 -1
  81. data/static/arguments.json +7 -1
  82. data/static/info_arch.json +24 -17
  83. data/static/previews.json +15 -14
  84. metadata +2 -2
@@ -105,7 +105,7 @@ __decorate([
105
105
  targets
106
106
  ], NavListGroupElement.prototype, "focusMarkers", void 0);
107
107
  NavListGroupElement = __decorate([
108
- controller
108
+ controller('nav-list-group')
109
109
  ], NavListGroupElement);
110
110
  export { NavListGroupElement };
111
111
  window.NavListGroupElement = NavListGroupElement;
@@ -1,7 +1,7 @@
1
1
  import {controller, target, targets} from '@github/catalyst'
2
2
  import {ActionListTruncationObserver} from '../alpha/action_list'
3
3
 
4
- @controller
4
+ @controller('nav-list-group')
5
5
  export class NavListGroupElement extends HTMLElement {
6
6
  @target showMoreItem: HTMLElement
7
7
  @targets focusMarkers: HTMLElement[]
@@ -25,20 +25,29 @@ function dialogInvokerButtonHandler(event) {
25
25
  // If the behaviour is allowed through the dialog will be shown but then
26
26
  // quickly hidden- as if it were never shown. This prevents that.
27
27
  event.preventDefault();
28
- // In some older browsers, such as Chrome 122, when a top layer element (such as a dialog)
29
- // opens from within a popover, the "hide all popovers" internal algorithm runs, hiding
30
- // any popover that is currently open, regardless of whether or not another top layer element,
31
- // such as a <dialog> is nested inside.
32
- // See https://github.com/whatwg/html/issues/9998.
33
- // This is fixed by https://github.com/whatwg/html/pull/10116, but while we still support browsers
34
- // that present this bug, we must undo the work they did to hide ancestral popovers of the dialog:
28
+ // When a <dialog> is opened with showModal() from inside a popover with popover="auto",
29
+ // there are two related issues:
30
+ //
31
+ // 1. In older browsers (e.g. Chrome 122), the "hide all popovers" algorithm runs when a
32
+ // top layer element opens, closing any ancestor popover. We must re-open those popovers.
33
+ // See https://github.com/whatwg/html/issues/9998,
34
+ // fixed by https://github.com/whatwg/html/pull/10116.
35
+ //
36
+ // 2. In newer browsers where the popover stays open, the popover="auto" behavior still
37
+ // interferes with the native <dialog> focus trap, causing focus to escape the dialog
38
+ // when tabbing past the last focusable element. Converting the popover to "manual"
39
+ // prevents this interference.
40
+ //
41
+ // In both cases, the fix is the same: convert ancestor auto popovers to manual.
35
42
  let node = button;
36
43
  let fixed = false;
37
44
  while (node) {
38
- node = node.parentElement?.closest('[popover]:not(:popover-open)');
45
+ node = node.parentElement?.closest('[popover]');
39
46
  if (node && node.popover === 'auto') {
40
47
  node.classList.add('dialog-inside-popover-fix');
41
48
  node.popover = 'manual';
49
+ // Changing popover from "auto" to "manual" closes the popover,
50
+ // so we need to re-show it regardless of whether it was previously open.
42
51
  node.showPopover();
43
52
  fixed = true;
44
53
  }
@@ -15,20 +15,29 @@ function dialogInvokerButtonHandler(event: Event) {
15
15
  // quickly hidden- as if it were never shown. This prevents that.
16
16
  event.preventDefault()
17
17
 
18
- // In some older browsers, such as Chrome 122, when a top layer element (such as a dialog)
19
- // opens from within a popover, the "hide all popovers" internal algorithm runs, hiding
20
- // any popover that is currently open, regardless of whether or not another top layer element,
21
- // such as a <dialog> is nested inside.
22
- // See https://github.com/whatwg/html/issues/9998.
23
- // This is fixed by https://github.com/whatwg/html/pull/10116, but while we still support browsers
24
- // that present this bug, we must undo the work they did to hide ancestral popovers of the dialog:
18
+ // When a <dialog> is opened with showModal() from inside a popover with popover="auto",
19
+ // there are two related issues:
20
+ //
21
+ // 1. In older browsers (e.g. Chrome 122), the "hide all popovers" algorithm runs when a
22
+ // top layer element opens, closing any ancestor popover. We must re-open those popovers.
23
+ // See https://github.com/whatwg/html/issues/9998,
24
+ // fixed by https://github.com/whatwg/html/pull/10116.
25
+ //
26
+ // 2. In newer browsers where the popover stays open, the popover="auto" behavior still
27
+ // interferes with the native <dialog> focus trap, causing focus to escape the dialog
28
+ // when tabbing past the last focusable element. Converting the popover to "manual"
29
+ // prevents this interference.
30
+ //
31
+ // In both cases, the fix is the same: convert ancestor auto popovers to manual.
25
32
  let node: HTMLElement | null | undefined = button
26
33
  let fixed = false
27
34
  while (node) {
28
- node = node.parentElement?.closest('[popover]:not(:popover-open)')
35
+ node = node.parentElement?.closest('[popover]')
29
36
  if (node && node.popover === 'auto') {
30
37
  node.classList.add('dialog-inside-popover-fix')
31
38
  node.popover = 'manual'
39
+ // Changing popover from "auto" to "manual" closes the popover,
40
+ // so we need to re-show it regardless of whether it was previously open.
32
41
  node.showPopover()
33
42
  fixed = true
34
43
  }
@@ -46,7 +46,7 @@ __decorate([
46
46
  attr
47
47
  ], ScrollableRegionElement.prototype, "labelledBy", void 0);
48
48
  ScrollableRegionElement = __decorate([
49
- controller
49
+ controller('scrollable-region')
50
50
  ], ScrollableRegionElement);
51
51
  export { ScrollableRegionElement };
52
52
  window.ScrollableRegionElement = ScrollableRegionElement;
@@ -1,6 +1,6 @@
1
1
  import {controller, attr} from '@github/catalyst'
2
2
 
3
- @controller
3
+ @controller('scrollable-region')
4
4
  export class ScrollableRegionElement extends HTMLElement {
5
5
  @attr hasOverflow = false
6
6
  @attr labelledBy = ''
@@ -9,7 +9,7 @@ module Primer
9
9
  attr_accessor :last_request
10
10
  end
11
11
 
12
- rescue_from ActionController::InvalidAuthenticityToken, with: :handle_invalid_authenticity_token
12
+ rescue_from ActionController::InvalidCrossOriginRequest, with: :handle_invalid_cross_origin_request
13
13
 
14
14
  before_action :reject_non_ajax_request
15
15
 
@@ -29,7 +29,7 @@ module Primer
29
29
 
30
30
  private
31
31
 
32
- def handle_invalid_authenticity_token
32
+ def handle_invalid_cross_origin_request
33
33
  render status: :unauthorized, plain: "Bad CSRF token."
34
34
  end
35
35
 
@@ -8,27 +8,31 @@ class CheckBoxWithNestedForm < ApplicationForm
8
8
  custom_cities_form.text_field(
9
9
  name: :custom_cities,
10
10
  label: "Custom cities",
11
- description: "A space-separated list of cities"
11
+ caption: "A space-separated list of cities"
12
12
  )
13
13
  end
14
14
  end
15
15
 
16
16
  form do |check_form|
17
- check_form.check_box_group(name: :city_categories) do |check_group|
17
+ check_form.check_box_group(
18
+ name: :city_categories,
19
+ label: "City categories",
20
+ caption: "Select all that apply."
21
+ ) do |check_group|
18
22
  check_group.check_box(
19
23
  value: "capital",
20
24
  label: "Capital",
21
- description: "The capital city"
25
+ caption: "The capital city"
22
26
  )
23
27
  check_group.check_box(
24
28
  value: "populous",
25
29
  label: "Most-populous",
26
- description: "The five most-populous cities"
30
+ caption: "The five most-populous cities"
27
31
  )
28
32
  check_group.check_box(
29
33
  value: "custom",
30
34
  label: "Custom",
31
- description: "A custom list of cities"
35
+ caption: "A custom list of cities"
32
36
  ) do |custom_check_box|
33
37
  custom_check_box.nested_form do |builder|
34
38
  CustomCitiesForm.new(builder)
@@ -11,6 +11,13 @@ module Primer
11
11
  @input.add_label_classes("FormControl-label")
12
12
  @input.add_input_classes("FormControl-checkbox")
13
13
 
14
+ # Generate custom ID that preserves brackets from the name
15
+ unless @input.input_arguments[:id].present?
16
+ generate_custom_id
17
+ # Update the label's for attribute to match the new ID
18
+ @input.label_arguments[:for] = @input.input_arguments[:id]
19
+ end
20
+
14
21
  return unless @input.scheme == :array
15
22
 
16
23
  @input.input_arguments[:multiple] = true
@@ -32,6 +39,27 @@ module Primer
32
39
 
33
40
  private
34
41
 
42
+ def generate_custom_id
43
+ # Generate an ID from the name that preserves special characters like brackets
44
+ # For array scheme: name + "_" + value (e.g., "permissions[3]_foo")
45
+ # For boolean scheme: just the name (e.g., "long_o")
46
+ base_name = @input.name.to_s
47
+
48
+ # For array scheme, Rails appends [] to the name, so we remove it for ID generation
49
+ # but only the trailing [] that Rails adds, not brackets that are part of the original name
50
+ # Regex /\[\]$/ matches literal "[]" at the end of the string
51
+ base_name = base_name.sub(/\[\]$/, "")
52
+
53
+ # For array scheme, append the value to make IDs unique
54
+ # For boolean scheme, just use the base name
55
+ # Note: Rails automatically escapes HTML attributes, so special characters are safe
56
+ if @input.scheme == :array && @input.value.present?
57
+ @input.input_arguments[:id] = "#{base_name}_#{@input.value}"
58
+ else
59
+ @input.input_arguments[:id] = base_name
60
+ end
61
+ end
62
+
35
63
  def checked_value
36
64
  @input.value || "1"
37
65
  end
@@ -39,7 +39,9 @@ module Primer
39
39
  new_options[:data] ||= {}
40
40
  new_options[:data][:name] = name
41
41
  new_options[:data][:targets] = "primer-multi-input.fields"
42
- new_options[:id] = nil if options[:hidden]
42
+ new_options[:id] = "#{@name}_#{name}"
43
+ new_options[:aria] ||= {}
44
+ new_options[:aria][:labelledby] = "label-#{base_id}"
43
45
  new_options[:disabled] = true if options[:hidden] # disable to avoid submitting to server
44
46
  new_options
45
47
  end
@@ -6,7 +6,7 @@ module Primer
6
6
  attr_reader(
7
7
  *%i[
8
8
  name label show_clear_button leading_visual leading_spinner trailing_visual clear_button_id
9
- visually_hide_label inset monospace field_wrap_classes auto_check_src character_limit
9
+ clear_button_label visually_hide_label inset monospace field_wrap_classes auto_check_src character_limit
10
10
  ]
11
11
  )
12
12
 
@@ -21,6 +21,7 @@ module Primer
21
21
  @trailing_visual = system_arguments.delete(:trailing_visual)
22
22
  @leading_spinner = !!system_arguments.delete(:leading_spinner)
23
23
  @clear_button_id = system_arguments.delete(:clear_button_id) || SecureRandom.uuid
24
+ @clear_button_label = system_arguments.delete(:clear_button_label)
24
25
  @inset = system_arguments.delete(:inset)
25
26
  @monospace = system_arguments.delete(:monospace)
26
27
  @auto_check_src = system_arguments.delete(:auto_check_src)
@@ -1,7 +1,8 @@
1
1
  <% if @input.form_control? %>
2
2
  <%= content_tag(@tag, **@form_group_arguments) do %>
3
3
  <% if @input.label %>
4
- <%= builder.label(@input.name, **@input.label_arguments) do %>
4
+ <% label_id = @input.label_arguments[:id] || "label-#{@input.base_id}" %>
5
+ <%= builder.label(@input.name, **@input.label_arguments.merge(id: label_id)) do %>
5
6
  <%= @input.label %>
6
7
  <% if @input.required? %>
7
8
  <span aria-hidden="true">*</span>
@@ -35,7 +35,7 @@ __decorate([
35
35
  targets
36
36
  ], PrimerMultiInputElement.prototype, "fields", void 0);
37
37
  PrimerMultiInputElement = __decorate([
38
- controller
38
+ controller('primer-multi-input')
39
39
  ], PrimerMultiInputElement);
40
40
  export { PrimerMultiInputElement };
41
41
  if (!window.customElements.get('primer-multi-input')) {
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable custom-elements/expose-class-on-global */
2
2
  import {controller, targets} from '@github/catalyst'
3
3
 
4
- @controller
4
+ @controller('primer-multi-input')
5
5
  export class PrimerMultiInputElement extends HTMLElement {
6
6
  @targets fields: HTMLInputElement[]
7
7
 
@@ -44,7 +44,7 @@ __decorate([
44
44
  target
45
45
  ], PrimerTextAreaElement.prototype, "characterLimitSrElement", void 0);
46
46
  PrimerTextAreaElement = __decorate([
47
- controller
47
+ controller('primer-text-area')
48
48
  ], PrimerTextAreaElement);
49
49
  export { PrimerTextAreaElement };
50
50
  if (!window.customElements.get('primer-text-area')) {
@@ -1,7 +1,7 @@
1
1
  import {controller, target} from '@github/catalyst'
2
2
  import {CharacterCounter} from './character_counter'
3
3
 
4
- @controller
4
+ @controller('primer-text-area')
5
5
  export class PrimerTextAreaElement extends HTMLElement {
6
6
  @target inputElement: HTMLTextAreaElement
7
7
  @target characterLimitElement: HTMLElement
@@ -128,6 +128,6 @@ __decorate([
128
128
  target
129
129
  ], PrimerTextFieldElement.prototype, "characterLimitSrElement", void 0);
130
130
  PrimerTextFieldElement = __decorate([
131
- controller
131
+ controller('primer-text-field')
132
132
  ], PrimerTextFieldElement);
133
133
  export { PrimerTextFieldElement };
@@ -10,7 +10,7 @@ declare global {
10
10
  }
11
11
  }
12
12
 
13
- @controller
13
+ @controller('primer-text-field')
14
14
  export class PrimerTextFieldElement extends HTMLElement {
15
15
  @target inputElement: HTMLInputElement
16
16
  @target validationElement: HTMLElement
@@ -13,7 +13,7 @@
13
13
  <%= builder.text_field(@input.name, **@input.input_arguments) %>
14
14
  <% end %>
15
15
  <% if @input.show_clear_button? %>
16
- <button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="Clear" data-action="click:primer-text-field#clearContents">
16
+ <button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="<%= @input.clear_button_label || 'Clear' %>" data-action="click:primer-text-field#clearContents">
17
17
  <%= render(Primer::Beta::Octicon.new(icon: :"x-circle-fill")) %>
18
18
  </button>
19
19
  <% end %>
@@ -29,6 +29,6 @@ __decorate([
29
29
  target
30
30
  ], ToggleSwitchInputElement.prototype, "validationMessageElement", void 0);
31
31
  ToggleSwitchInputElement = __decorate([
32
- controller
32
+ controller('toggle-switch-input')
33
33
  ], ToggleSwitchInputElement);
34
34
  export { ToggleSwitchInputElement };
@@ -2,7 +2,7 @@
2
2
 
3
3
  import {controller, target} from '@github/catalyst'
4
4
 
5
- @controller
5
+ @controller('toggle-switch-input')
6
6
  export class ToggleSwitchInputElement extends HTMLElement {
7
7
  @target validationElement: HTMLElement
8
8
  @target validationMessageElement: HTMLElement
@@ -32,6 +32,10 @@ module Primer
32
32
  per_component: {
33
33
  Primer::Alpha::ToggleSwitch => {
34
34
  all_scenarios: %i[button-name]
35
+ },
36
+
37
+ Primer::Alpha::MultiInput => {
38
+ visually_hide_label: %i[label-title-only]
35
39
  }
36
40
  }
37
41
  }
@@ -46,6 +50,8 @@ module Primer
46
50
  end
47
51
 
48
52
  def axe_rules_to_skip(component: nil, scenario_name: nil, flatten: false)
53
+ scenario_key = scenario_name.is_a?(String) ? scenario_name.to_sym : scenario_name
54
+
49
55
  to_skip = {
50
56
  wont_fix: Set.new(AXE_RULES_TO_SKIP.dig(:wont_fix, :global) || []),
51
57
  will_fix: Set.new(AXE_RULES_TO_SKIP.dig(:will_fix, :global) || [])
@@ -55,9 +61,9 @@ module Primer
55
61
  to_skip[:wont_fix].merge(AXE_RULES_TO_SKIP.dig(:wont_fix, :per_component, component, :all_scenarios) || [])
56
62
  to_skip[:will_fix].merge(AXE_RULES_TO_SKIP.dig(:will_fix, :per_component, component, :all_scenarios) || [])
57
63
 
58
- if scenario_name
59
- to_skip[:wont_fix].merge(AXE_RULES_TO_SKIP.dig(:wont_fix, :per_component, component, scenario_name) || [])
60
- to_skip[:will_fix].merge(AXE_RULES_TO_SKIP.dig(:will_fix, :per_component, component, scenario_name) || [])
64
+ if scenario_key
65
+ to_skip[:wont_fix].merge(AXE_RULES_TO_SKIP.dig(:wont_fix, :per_component, component, scenario_key) || [])
66
+ to_skip[:will_fix].merge(AXE_RULES_TO_SKIP.dig(:will_fix, :per_component, component, scenario_key) || [])
61
67
  end
62
68
  end
63
69
 
@@ -48,10 +48,7 @@ module Primer
48
48
 
49
49
  initializer "primer.forms.helpers" do
50
50
  ActiveSupport.on_load :action_controller_base do
51
- begin
52
- require "primer/form_helper"
53
- rescue LoadError
54
- end
51
+ require_relative "../../../app/helpers/primer/form_helper"
55
52
 
56
53
  helper Primer::FormHelper
57
54
 
@@ -5,7 +5,7 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 49
8
+ MINOR = 51
9
9
  PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
@@ -8,10 +8,12 @@
8
8
 
9
9
  <br>
10
10
 
11
+ <% field_id = "bar-#{SecureRandom.hex}" %>
12
+
11
13
  <%= form_with(url: "/foo") do |f| %>
12
- <%= render(Primer::Alpha::FormControl.new(**system_arguments, label_arguments: { for: "bar" })) do |component| %>
14
+ <%= render(Primer::Alpha::FormControl.new(**system_arguments, label_arguments: { for: field_id })) do |component| %>
13
15
  <% component.with_input do |input_arguments| %>
14
- <%= f.text_field(:bar, **input_arguments) %>
16
+ <%= f.text_field(:bar, id: field_id, **input_arguments) %>
15
17
  <% end %>
16
18
  <% end %>
17
19
  <% end %>
@@ -1,7 +1,7 @@
1
1
  <p style="max-width: 500px">
2
2
  Below is an SVG image containing the chosen octicon surrounded by a green circle. The octicon has been emitted
3
3
  onto the page as an SVG &lt;symbol&gt; element and included into the SVG you see below with the &lt;use&gt; element.
4
- See the <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol" target="_blank">MDN docs</a> for
4
+ See the <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol" target="_blank" style="text-decoration: underline">MDN docs</a> for
5
5
  more information.
6
6
  </p>
7
7
 
@@ -77,31 +77,6 @@ module Primer
77
77
  end
78
78
  end
79
79
 
80
- # @label Menu No Header
81
- #
82
- # @param size [Symbol] select [auto, small, medium, medium_portrait, large, xlarge]
83
- # @param padding [Symbol] select [normal, condensed, none]
84
- # @param anchor_align [Symbol] select [start, center, end]
85
- # @param anchor_side [Symbol] select [inside_top, inside_bottom, inside_left, inside_right, inside_center, outside_top, outside_bottom, outside_left, outside_right]
86
- # @param allow_out_of_bounds [Boolean] toggle
87
- #
88
- # @param button_text [String] text
89
- # @param body_text [String] text
90
- def menu_no_header(size: :auto, padding: :normal, anchor_align: :center, anchor_side: :outside_bottom, allow_out_of_bounds: false, button_text: "Show Overlay Menu", body_text: "This is a menu")
91
- render(Primer::Alpha::Overlay.new(
92
- title: "Menu",
93
- role: :menu,
94
- size: size,
95
- padding: padding,
96
- anchor_align: anchor_align,
97
- anchor_side: anchor_side,
98
- allow_out_of_bounds: allow_out_of_bounds
99
- )) do |d|
100
- d.with_show_button { button_text }
101
- d.with_body { body_text }
102
- end
103
- end
104
-
105
80
  # @label Middle Of Page
106
81
  #
107
82
  # @param title [String] text
@@ -50,7 +50,7 @@ module Primer
50
50
  # @label Default
51
51
  # @snapshot
52
52
  def default
53
- render(Primer::Alpha::TextArea.new(name: "my-text-area", label: "Tell me about yourself"))
53
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-default", name: "my-text-area-default", label: "Tell me about yourself"))
54
54
  end
55
55
 
56
56
  # @!group Options
@@ -58,61 +58,61 @@ module Primer
58
58
  # @label With caption
59
59
  # @snapshot
60
60
  def with_caption
61
- render(Primer::Alpha::TextArea.new(caption: "With a caption", name: "my-text-area", label: "Tell me about yourself"))
61
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-with-caption", name: "my-text-area-with-caption", caption: "With a caption", label: "Tell me about yourself"))
62
62
  end
63
63
 
64
64
  # @label Visually hidden label
65
65
  # @snapshot
66
66
  def visually_hide_label
67
- render(Primer::Alpha::TextArea.new(visually_hide_label: true, name: "my-text-area", label: "Tell me about yourself"))
67
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-visually-hide-label", name: "my-text-area-visually-hide-label", visually_hide_label: true, label: "Tell me about yourself"))
68
68
  end
69
69
 
70
70
  # @label Full width
71
71
  # @snapshot
72
72
  def full_width
73
- render(Primer::Alpha::TextArea.new(full_width: true, name: "my-text-area", label: "Tell me about yourself"))
73
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-full-width", name: "my-text-area-full-width", full_width: true, label: "Tell me about yourself"))
74
74
  end
75
75
 
76
76
  # @label Not full width
77
77
  # @snapshot
78
78
  def not_full_width
79
- render(Primer::Alpha::TextArea.new(full_width: false, name: "my-text-area", label: "Tell me about yourself"))
79
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-not-full-width", name: "my-text-area-not-full-width", full_width: false, label: "Tell me about yourself"))
80
80
  end
81
81
 
82
82
  # @label Disabled
83
83
  # @snapshot
84
84
  def disabled
85
- render(Primer::Alpha::TextArea.new(disabled: true, name: "my-text-area", label: "Tell me about yourself"))
85
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-disabled", name: "my-text-area-disabled", disabled: true, label: "Tell me about yourself"))
86
86
  end
87
87
 
88
88
  # @label Invalid
89
89
  # @snapshot
90
90
  def invalid
91
- render(Primer::Alpha::TextArea.new(invalid: true, name: "my-text-area", label: "Tell me about yourself"))
91
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-invalid", name: "my-text-area-invalid", invalid: true, label: "Tell me about yourself"))
92
92
  end
93
93
 
94
94
  # @label With validation message
95
95
  # @snapshot
96
96
  def with_validation_message
97
- render(Primer::Alpha::TextArea.new(validation_message: "An error occurred!", name: "my-text-area", label: "Tell me about yourself"))
97
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-with-validation-message", name: "my-text-area-with-validation-message", validation_message: "An error occurred!", label: "Tell me about yourself"))
98
98
  end
99
99
 
100
100
  # @label With character limit
101
101
  # @snapshot interactive
102
102
  def with_character_limit
103
- render(Primer::Alpha::TextArea.new(character_limit: 10, name: "my-text-area", label: "Tell me about yourself"))
103
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit", name: "my-text-area-with-character-limit", character_limit: 10, label: "Tell me about yourself"))
104
104
  end
105
105
 
106
106
  # @label With character limit, over limit
107
107
  # @snapshot interactive
108
108
  def with_character_limit_over_limit
109
- render(Primer::Alpha::TextArea.new(character_limit: 10, name: "my-text-area", label: "Tell me about yourself", value: "This text is definitely over the limit."))
109
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit-over-limit", name: "my-text-area-with-character-limit-over-limit", character_limit: 10, label: "Tell me about yourself", value: "This text is definitely over the limit."))
110
110
  end
111
111
 
112
112
  # @label With character limit and caption
113
113
  # @snapshot
114
114
  def with_character_limit_and_caption
115
- render(Primer::Alpha::TextArea.new(character_limit: 100, caption: "With a caption.", name: "my-text-area", label: "Tell me about yourself"))
115
+ render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit-and-caption", name: "my-text-area-with-character-limit-and-caption", character_limit: 100, caption: "With a caption.", label: "Tell me about yourself"))
116
116
  end
117
117
  #
118
118
  # @!endgroup
@@ -15,6 +15,7 @@ module Primer
15
15
  # @param size [Symbol] select [small, medium, large]
16
16
  # @param show_clear_button toggle
17
17
  # @param clear_button_id text
18
+ # @param clear_button_label text
18
19
  # @param full_width toggle
19
20
  # @param disabled toggle
20
21
  # @param invalid toggle
@@ -35,6 +36,7 @@ module Primer
35
36
  size: Primer::Forms::Dsl::Input::DEFAULT_SIZE.to_s,
36
37
  show_clear_button: false,
37
38
  clear_button_id: "my-text-field-clear-button",
39
+ clear_button_label: nil,
38
40
  full_width: true,
39
41
  disabled: false,
40
42
  invalid: false,
@@ -56,6 +58,7 @@ module Primer
56
58
  size: size,
57
59
  show_clear_button: show_clear_button,
58
60
  clear_button_id: clear_button_id,
61
+ clear_button_label: clear_button_label,
59
62
  full_width: full_width,
60
63
  disabled: disabled,
61
64
  invalid: invalid,
@@ -133,6 +136,12 @@ module Primer
133
136
  render(Primer::Alpha::TextField.new(show_clear_button: true, name: "my-text-field-3", label: "My text field"))
134
137
  end
135
138
 
139
+ # @label Show clear button with custom label
140
+ # @snapshot
141
+ def show_clear_button_with_custom_label
142
+ render(Primer::Alpha::TextField.new(show_clear_button: true, clear_button_label: "Effacer", name: "my-text-field-3-custom", label: "Mon champ de texte"))
143
+ end
144
+
136
145
  # @label Full width
137
146
  # @snapshot
138
147
  def full_width