primer_view_components 0.0.83 → 0.0.86

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +50 -0
  3. data/app/assets/javascripts/primer_view_components.js +1 -1
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  5. data/app/components/primer/alpha/auto_complete/auto_complete.html.erb +24 -0
  6. data/app/components/primer/alpha/auto_complete/item.rb +46 -0
  7. data/app/components/primer/alpha/auto_complete.rb +158 -0
  8. data/app/components/primer/alpha/button_marketing.rb +1 -1
  9. data/app/components/primer/alpha/text_field.rb +105 -0
  10. data/app/components/primer/alpha/tool-tip-element.d.ts +3 -1
  11. data/app/components/primer/alpha/tool-tip-element.js +20 -13
  12. data/app/components/primer/alpha/tool-tip-element.ts +23 -14
  13. data/app/components/primer/alpha/tooltip.rb +1 -1
  14. data/app/components/primer/beta/auto_complete/auto_complete.html.erb +21 -17
  15. data/app/components/primer/beta/auto_complete/item.html.erb +21 -0
  16. data/app/components/primer/beta/auto_complete/item.rb +42 -6
  17. data/app/components/primer/beta/auto_complete.rb +93 -55
  18. data/app/components/primer/beta/base_button.rb +47 -0
  19. data/app/components/primer/{alpha → beta}/border_box/header.html.erb +0 -0
  20. data/app/components/primer/{alpha → beta}/border_box/header.rb +6 -6
  21. data/app/components/primer/{border_box_component.html.erb → beta/border_box.html.erb} +0 -0
  22. data/app/components/primer/beta/border_box.rb +147 -0
  23. data/app/components/primer/blankslate_component.rb +2 -150
  24. data/app/components/primer/border_box_component.rb +2 -140
  25. data/app/components/primer/button_component.html.erb +12 -4
  26. data/app/components/primer/button_component.rb +2 -2
  27. data/app/components/primer/clipboard_copy.rb +6 -2
  28. data/app/components/primer/close_button.rb +1 -1
  29. data/app/components/primer/conditional_wrapper.rb +36 -0
  30. data/app/components/primer/hellip_button.rb +1 -1
  31. data/app/components/primer/icon_button.html.erb +6 -0
  32. data/app/components/primer/icon_button.rb +46 -10
  33. data/app/components/primer/link_component.html.erb +12 -0
  34. data/app/components/primer/link_component.rb +2 -9
  35. data/app/lib/primer/join_style_arguments_helper.rb +1 -1
  36. data/lib/primer/classify/utilities.rb +3 -6
  37. data/lib/primer/form_components.rb +36 -0
  38. data/lib/primer/forms/acts_as_component.rb +118 -0
  39. data/lib/primer/forms/base.html.erb +8 -0
  40. data/lib/primer/forms/base.rb +137 -0
  41. data/lib/primer/forms/base_component.rb +58 -0
  42. data/lib/primer/forms/buffer_rewriter.rb +50 -0
  43. data/lib/primer/forms/caption.html.erb +10 -0
  44. data/lib/primer/forms/caption.rb +29 -0
  45. data/lib/primer/forms/check_box.html.erb +9 -0
  46. data/lib/primer/forms/check_box.rb +16 -0
  47. data/lib/primer/forms/check_box_group.html.erb +12 -0
  48. data/lib/primer/forms/check_box_group.rb +14 -0
  49. data/lib/primer/forms/dsl/check_box_group_input.rb +41 -0
  50. data/lib/primer/forms/dsl/check_box_input.rb +27 -0
  51. data/lib/primer/forms/dsl/form_object.rb +25 -0
  52. data/lib/primer/forms/dsl/form_reference_input.rb +36 -0
  53. data/lib/primer/forms/dsl/hidden_input.rb +29 -0
  54. data/lib/primer/forms/dsl/input.rb +259 -0
  55. data/lib/primer/forms/dsl/input_group.rb +41 -0
  56. data/lib/primer/forms/dsl/input_methods.rb +86 -0
  57. data/lib/primer/forms/dsl/multi_input.rb +58 -0
  58. data/lib/primer/forms/dsl/radio_button_group_input.rb +38 -0
  59. data/lib/primer/forms/dsl/radio_button_input.rb +37 -0
  60. data/lib/primer/forms/dsl/select_list_input.rb +53 -0
  61. data/lib/primer/forms/dsl/submit_button_input.rb +28 -0
  62. data/lib/primer/forms/dsl/text_area_input.rb +33 -0
  63. data/lib/primer/forms/dsl/text_field_input.rb +65 -0
  64. data/lib/primer/forms/form_control.html.erb +18 -0
  65. data/lib/primer/forms/form_control.rb +23 -0
  66. data/lib/primer/forms/form_list.html.erb +5 -0
  67. data/lib/primer/forms/form_list.rb +21 -0
  68. data/lib/primer/forms/form_reference.html.erb +3 -0
  69. data/lib/primer/forms/form_reference.rb +14 -0
  70. data/lib/primer/forms/group.html.erb +5 -0
  71. data/lib/primer/forms/group.rb +27 -0
  72. data/lib/primer/forms/hidden_field.html.erb +1 -0
  73. data/lib/primer/forms/hidden_field.rb +15 -0
  74. data/lib/primer/forms/multi.html.erb +3 -0
  75. data/lib/primer/forms/multi.rb +14 -0
  76. data/lib/primer/forms/radio_button.html.erb +14 -0
  77. data/lib/primer/forms/radio_button.rb +29 -0
  78. data/lib/primer/forms/radio_button_group.html.erb +12 -0
  79. data/lib/primer/forms/radio_button_group.rb +14 -0
  80. data/lib/primer/forms/select_list.html.erb +5 -0
  81. data/lib/primer/forms/select_list.rb +26 -0
  82. data/lib/primer/forms/separator.html.erb +1 -0
  83. data/lib/primer/forms/separator.rb +8 -0
  84. data/lib/primer/forms/spacing_wrapper.html.erb +3 -0
  85. data/lib/primer/forms/spacing_wrapper.rb +8 -0
  86. data/lib/primer/forms/submit_button.html.erb +4 -0
  87. data/lib/primer/forms/submit_button.rb +50 -0
  88. data/lib/primer/forms/text_area.html.erb +5 -0
  89. data/lib/primer/forms/text_area.rb +16 -0
  90. data/lib/primer/forms/text_field.html.erb +19 -0
  91. data/lib/primer/forms/text_field.rb +14 -0
  92. data/lib/primer/view_components/engine.rb +23 -0
  93. data/lib/primer/view_components/linters/argument_mappers/button.rb +2 -2
  94. data/lib/primer/view_components/linters/button_component_migration_counter.rb +1 -1
  95. data/lib/primer/view_components/linters/helpers/deprecated_components_helpers.rb +4 -8
  96. data/lib/primer/view_components/version.rb +1 -1
  97. data/lib/rubocop/cop/primer/component_name_migration.rb +3 -0
  98. data/lib/tasks/deprecated.rake +22 -0
  99. data/lib/tasks/docs.rake +8 -6
  100. data/static/arguments.yml +188 -52
  101. data/static/audited_at.json +7 -2
  102. data/static/classes.yml +25 -8
  103. data/static/constants.json +66 -39
  104. data/static/statuses.json +8 -3
  105. metadata +71 -7
  106. data/app/components/primer/base_button.rb +0 -43
  107. data/app/components/primer/blankslate_component.html.erb +0 -30
@@ -0,0 +1,24 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <label for="<%= @input_id %>" class="<%= @label_classes %>">
3
+ <% if @is_label_visible %>
4
+ <%= @label_text %>
5
+ <% else %>
6
+ <span class="sr-only"><%= @label_text %></span>
7
+ <% end %>
8
+ </label>
9
+ <span class="autocomplete-body">
10
+ <% if @with_icon %>
11
+ <div class="form-control autocomplete-embedded-icon-wrap">
12
+ <%= render Primer::OcticonComponent.new(:search) %>
13
+ <% end %>
14
+ <%= input %>
15
+ <% if @is_clearable %>
16
+ <button id="<%= @input_id %>-clear" class="btn-octicon" aria-label="Clear"><%= primer_octicon "x" %></button>
17
+ <% end %>
18
+ <% if @with_icon %>
19
+ </div>
20
+ <% end %>
21
+ <%= results %>
22
+ </span>
23
+ <div id="<%= @list_id %>-feedback" class="sr-only"></div>
24
+ <% end %>
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ class AutoComplete
6
+ # Use `AutoCompleteItem` to list results of an auto-completed search.
7
+ class Item < Primer::Component
8
+ status :deprecated
9
+
10
+ # @example Default
11
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--custom-results", list_id: "fruits-popup--custom-results")) do |c| %>
12
+ # <% c.results(classes: "custom-class") do %>
13
+ # <%= render(Primer::Alpha::AutoComplete::Item.new(selected: true, value: "apple")) do |c| %>
14
+ # Apple
15
+ # <% end %>
16
+ # <%= render(Primer::Alpha::AutoComplete::Item.new(value: "orange")) do |c| %>
17
+ # Orange
18
+ # <% end %>
19
+ # <% end %>
20
+ # <% end %>
21
+ #
22
+ # @param value [String] Value of the item.
23
+ # @param selected [Boolean] Whether the item is selected.
24
+ # @param disabled [Boolean] Whether the item is disabled.
25
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
26
+ def initialize(value:, selected: false, disabled: false, **system_arguments)
27
+ @system_arguments = deny_tag_argument(**system_arguments)
28
+ @system_arguments[:tag] = :li
29
+ @system_arguments[:role] = :option
30
+ @system_arguments[:"data-autocomplete-value"] = value
31
+ @system_arguments[:"aria-selected"] = true if selected
32
+ @system_arguments[:"aria-disabled"] = true if disabled
33
+ @system_arguments[:classes] = class_names(
34
+ "autocomplete-item",
35
+ system_arguments[:classes],
36
+ "disabled" => disabled
37
+ )
38
+ end
39
+
40
+ def call
41
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ # Use `AutoComplete` to provide a user with a list of selectable suggestions that appear when they type into the
6
+ # input field. This list is populated by server search results.
7
+ # @accessibility
8
+ # Always set an accessible label to help the user interact with the component.
9
+ #
10
+ # * `label_text` is required and visible by default.
11
+ # * If you must use a non-visible label, set `is_label_visible` to `false`.
12
+ # However, please note that a visible label should almost always
13
+ # be used unless there is compelling reason not to. A placeholder is not a label.
14
+ class AutoComplete < Primer::Component
15
+ status :deprecated
16
+
17
+ # Customizable results list.
18
+ #
19
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
20
+ renders_one :results, lambda { |**system_arguments|
21
+ deny_tag_argument(**system_arguments)
22
+ system_arguments[:tag] = :ul
23
+ system_arguments[:id] = @list_id
24
+ system_arguments[:classes] = class_names(
25
+ "autocomplete-results",
26
+ system_arguments[:classes]
27
+ )
28
+ Primer::BaseComponent.new(**system_arguments)
29
+ }
30
+
31
+ # Customizable input used to search for results.
32
+ # It is preferred to use this slot sparingly - it will be created by default if not explicity added.
33
+ #
34
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
35
+ renders_one :input, lambda { |**system_arguments|
36
+ sanitized_args = deny_tag_argument(**system_arguments)
37
+ sanitized_args = deny_single_argument(:autofocus, "autofocus is not allowed for accessibility reasons. See https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus#accessibility_considerations for more information.", **sanitized_args)
38
+ deny_aria_key(
39
+ :label,
40
+ "instead of `aria-label`, include `label_text` and set `is_label_visible` to `false` on the component initializer.",
41
+ **sanitized_args
42
+ )
43
+ deny_single_argument(
44
+ :id,
45
+ "`id` will always be set to @input_id.",
46
+ **sanitized_args
47
+ )
48
+ deny_single_argument(
49
+ :name,
50
+ "Set @input_name on the component initializer instead with `input_name`.",
51
+ **sanitized_args
52
+ )
53
+ sanitized_args[:id] = @input_id
54
+ sanitized_args[:name] = @input_name
55
+ sanitized_args[:tag] = :input
56
+ sanitized_args[:autocomplete] = "off"
57
+ sanitized_args[:type] = :text
58
+ sanitized_args[:classes] = class_names(
59
+ "form-control",
60
+ sanitized_args[:classes]
61
+ )
62
+ Primer::BaseComponent.new(**sanitized_args)
63
+ }
64
+
65
+ # @example Default
66
+ # @description
67
+ # Labels are stacked by default.
68
+ # @code
69
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--default", list_id: "fruits-popup--default")) %>
70
+ #
71
+ # @example With inline label
72
+ # @description
73
+ # Labels can be inline by setting `is_label_inline: true`. However, labels will always become stacked on smaller screen sizes.
74
+ # @code
75
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", is_label_inline: true, input_id: "fruits-input--inline-label", list_id: "fruits-popup--inline-label")) %>
76
+ #
77
+ # @example With non-visible label
78
+ # @description
79
+ # A non-visible label may be rendered with `is_label_visible: false`, but it is highly discouraged. See <%= link_to_accessibility %>.
80
+ # @code
81
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--non-visible-label", list_id: "fruits-popup--non-visible-label", is_label_visible: false)) %>
82
+ #
83
+ # @example With icon
84
+ # @description
85
+ # To display a search icon, set `with_icon` to `true`.
86
+ # @code
87
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", list_id: "fruits-popup--icon", input_id: "fruits-input--icon", with_icon: true)) %>
88
+ #
89
+ # @example With icon and non-visible label
90
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", list_id: "fruits-popup--icon-no-label", input_id: "fruits-input--icon-no-label", with_icon: true, is_label_visible: false)) %>
91
+ #
92
+ # @example With clear button
93
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--clear", list_id: "fruits-popup--clear", is_clearable: true)) %>
94
+ #
95
+ # @example With custom classes for the input
96
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--custom-input", list_id: "fruits-popup--custom-input")) do |c| %>
97
+ # <% c.input(classes: "custom-class") %>
98
+ # <% end %>
99
+ #
100
+ # @example With custom classes for the results
101
+ # <%= render(Primer::Alpha::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--custom-results", list_id: "fruits-popup--custom-results")) do |c| %>
102
+ # <% c.results(classes: "custom-class") do %>
103
+ # <%= render(Primer::Alpha::AutoComplete::Item.new(selected: true, value: "apple")) do |c| %>
104
+ # Apple
105
+ # <% end %>
106
+ # <%= render(Primer::Alpha::AutoComplete::Item.new(value: "orange")) do |c| %>
107
+ # Orange
108
+ # <% end %>
109
+ # <% end %>
110
+ # <% end %>
111
+ #
112
+ # @param label_text [String] The label of the input.
113
+ # @param src [String] The route to query.
114
+ # @param input_id [String] Id of the input element.
115
+ # @param input_name [String] Optional name of the input element, defaults to `input_id` when not set.
116
+ # @param list_id [String] Id of the list element.
117
+ # @param with_icon [Boolean] Controls if a search icon is visible, defaults to `false`.
118
+ # @param is_label_visible [Boolean] Controls if the label is visible. If `false`, screen reader only text will be added.
119
+ # @param is_clearable [Boolean] Adds optional clear button.
120
+ # @param is_label_inline [Boolean] Controls if the label is inline. On smaller screens, label will always become stacked.
121
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
122
+ def initialize(label_text:, src:, list_id:, input_id:, input_name: nil, is_label_visible: true, is_label_inline: false, with_icon: false, is_clearable: false, **system_arguments)
123
+ @label_text = label_text
124
+ @list_id = list_id
125
+ @input_id = input_id
126
+ @input_name = input_name || input_id
127
+ @is_label_visible = is_label_visible
128
+ @with_icon = with_icon
129
+ @is_clearable = is_clearable
130
+ @label_classes = label_classes(is_label_visible: is_label_visible, is_label_inline: is_label_inline)
131
+ @system_arguments = deny_tag_argument(**system_arguments)
132
+ @system_arguments[:tag] = "auto-complete"
133
+ @system_arguments[:src] = src
134
+ @system_arguments[:for] = list_id
135
+ end
136
+
137
+ # add `input` and `results` without needing to explicitly call them in the view
138
+ def before_render
139
+ results(classes: "") unless results
140
+ input(classes: "") unless input
141
+ end
142
+
143
+ private
144
+
145
+ # Private: determines the label classes based on component configration.
146
+ #
147
+ # If the label is not visible, return an empty string.
148
+ #
149
+ # @param args [Hash] The component configuration.
150
+ # @return [String] The label classes.
151
+ def label_classes(**args)
152
+ return "" if args[:is_label_visible] == false
153
+
154
+ args[:is_label_inline] ? "autocomplete-label-inline" : "autocomplete-label-stacked"
155
+ end
156
+ end
157
+ end
158
+ end
@@ -63,7 +63,7 @@ module Primer
63
63
  end
64
64
 
65
65
  def call
66
- render(Primer::BaseButton.new(**@system_arguments)) { content }
66
+ render(Primer::Beta::BaseButton.new(**@system_arguments)) { content }
67
67
  end
68
68
  end
69
69
  end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ TextField = Primer::FormComponents.from_input(Primer::Forms::Dsl::TextFieldInput)
6
+
7
+ # A text field suitable for use outside a form. For a text field input suitable for use
8
+ # within an HTML form, see the `Primer::Forms` namespace.
9
+ class TextField
10
+ status :alpha
11
+
12
+ # @!method initialize
13
+ #
14
+ # @example Default
15
+ # <%= render(Primer::Alpha::TextField.new(name: :first_name, label: "First name")) %>
16
+ #
17
+ # @example With a clear button
18
+ # <%= render(
19
+ # Primer::Alpha::TextField.new(
20
+ # name: :first_name,
21
+ # label: "First name",
22
+ # show_clear_button: true
23
+ # )
24
+ # ) %>
25
+ #
26
+ # @example Full width
27
+ # <%= render(
28
+ # Primer::Alpha::TextField.new(
29
+ # name: :first_name,
30
+ # label: "First name",
31
+ # full_width: true
32
+ # )
33
+ # ) %>
34
+ #
35
+ # @example Disabled
36
+ # <%= render(
37
+ # Primer::Alpha::TextField.new(
38
+ # name: :first_name,
39
+ # label: "First name",
40
+ # disabled: true
41
+ # )
42
+ # ) %>
43
+ #
44
+ # @example Invalid
45
+ # <%= render(
46
+ # Primer::Alpha::TextField.new(
47
+ # name: :first_name,
48
+ # label: "First name",
49
+ # invalid: true
50
+ # )
51
+ # ) %>
52
+ #
53
+ # @example With a leading visual
54
+ # <%= render(
55
+ # Primer::Alpha::TextField.new(
56
+ # name: :first_name,
57
+ # label: "First name",
58
+ # leading_visual: {
59
+ # icon: :person
60
+ # }
61
+ # )
62
+ # ) %>
63
+ #
64
+ # @example With a caption
65
+ # <%= render(
66
+ # Primer::Alpha::TextField.new(
67
+ # name: :first_name,
68
+ # label: "First name",
69
+ # caption: "What your friends call you"
70
+ # )
71
+ # ) %>
72
+ #
73
+ # @example With a validation message
74
+ # <%= render(
75
+ # Primer::Alpha::TextField.new(
76
+ # name: :first_name,
77
+ # label: "First name",
78
+ # validation_message: "Hmm, that doesn't look right"
79
+ # )
80
+ # ) %>
81
+ #
82
+ # @param name [String] Value for the HTML name attribute.
83
+ # @param id [String] Value for the HTML id attribute.
84
+ # @param class [String] A list of CSS classes to add to the input. Exists for compatibility with Rails form builders.
85
+ # @param classes [String] A list of CSS classes to add to the input. Combined with the `:class` argument.
86
+ # @param caption [String] Caption text to render below the input.
87
+ # @param label [String] Label text displayed above the input.
88
+ # @param visually_hide_label [Boolean] Whether or not to visually hide the label. If `true` the label will be hidden visually but still available to screen readers.
89
+ # @param size [Symbol] The size of the field. <%= one_of(Primer::Forms::Dsl::Input::SIZE_OPTIONS) %>
90
+ # @param show_clear_button [Boolean] Whether or not to include a clear button inside the input that clears the input's contents when clicked.
91
+ # @param clear_button_id [String] The HTML id attribute of the clear button.
92
+ # @param full_width [Boolean] Controls whether or not the input takes the full width of its container.
93
+ # @param disabled [Boolean] Whether or not the input should accept keyboard and mouse input.
94
+ # @param invalid [Boolean] If `true`, renders the input in a visually invalid state.
95
+ # @param placeholder [String] Placeholder text.
96
+ # @param inset [Boolean] If `true`, renders the input in a visually inset state.
97
+ # @param monospace [Boolean] If `true`, uses a monospace font for the input field.
98
+ # @param leading_visual [Hash] Renders a leading visual icon before the text field's cursor. The hash will be passed to Primer's [Octicon component](https://primer.style/view-components/components/octicon).
99
+ # @param validation_message [String] A validation message to display beneath the input. Implicitly sets `invalid` to `true`.
100
+ # @param label_arguments [Hash] System arugments passed to the Rails builder's `#label` method. These arguments will appear as HTML attributes on the `<label>` tag.
101
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
102
+ # @param block [Proc] Unused.
103
+ end
104
+ end
105
+ end
@@ -9,11 +9,13 @@ declare class ToolTipElement extends HTMLElement {
9
9
  get direction(): Direction;
10
10
  set direction(value: Direction);
11
11
  get control(): HTMLElement | null;
12
+ set visibilityHidden(value: true | false);
13
+ get visibilityHidden(): true | false;
12
14
  connectedCallback(): void;
13
15
  disconnectedCallback(): void;
14
16
  handleEvent(event: Event): void;
15
17
  static observedAttributes: string[];
16
- attributeChangedCallback(name: string): void;
18
+ attributeChangedCallback(name: string, oldValue: string, newValue: string): void;
17
19
  }
18
20
  declare global {
19
21
  interface Window {
@@ -176,6 +176,12 @@ class ToolTipElement extends HTMLElement {
176
176
  get control() {
177
177
  return this.ownerDocument.getElementById(this.htmlFor);
178
178
  }
179
+ set visibilityHidden(value) {
180
+ this.style.visibility = value ? 'hidden' : '';
181
+ }
182
+ get visibilityHidden() {
183
+ return this.style.visibility === 'hidden';
184
+ }
179
185
  connectedCallback() {
180
186
  var _a;
181
187
  if (!this.shadowRoot) {
@@ -188,7 +194,7 @@ class ToolTipElement extends HTMLElement {
188
194
  <slot></slot>
189
195
  `;
190
196
  }
191
- this.hidden = true;
197
+ this.visibilityHidden = true;
192
198
  __classPrivateFieldSet(this, _ToolTipElement_allowUpdatePosition, true, "f");
193
199
  if (!this.id) {
194
200
  this.id = `tooltip-${Date.now()}-${(Math.random() * 10000).toFixed(0)}`;
@@ -216,27 +222,28 @@ class ToolTipElement extends HTMLElement {
216
222
  return;
217
223
  // Ensures that tooltip stays open when hovering between tooltip and element
218
224
  // WCAG Success Criterion 1.4.13 Hoverable
219
- if ((event.type === 'mouseenter' || event.type === 'focus') && this.hidden) {
220
- this.hidden = false;
225
+ if ((event.type === 'mouseenter' || event.type === 'focus') && this.visibilityHidden) {
226
+ this.visibilityHidden = false;
221
227
  }
222
228
  else if (event.type === 'blur') {
223
- this.hidden = true;
229
+ this.visibilityHidden = true;
224
230
  }
225
231
  else if (event.type === 'mouseleave' &&
226
232
  event.relatedTarget !== this.control &&
227
233
  event.relatedTarget !== this) {
228
- this.hidden = true;
234
+ this.visibilityHidden = true;
229
235
  }
230
- else if (event.type === 'keydown' && event.key === 'Escape' && !this.hidden) {
231
- this.hidden = true;
236
+ else if (event.type === 'keydown' && event.key === 'Escape' && !this.visibilityHidden) {
237
+ this.visibilityHidden = true;
232
238
  }
233
239
  }
234
- attributeChangedCallback(name) {
240
+ attributeChangedCallback(name, oldValue, newValue) {
235
241
  if (name === 'id' || name === 'data-type') {
236
242
  if (!this.id || !this.control)
237
243
  return;
238
244
  if (this.type === 'label') {
239
245
  this.control.setAttribute('aria-labelledby', this.id);
246
+ this.setAttribute('aria-hidden', 'true');
240
247
  }
241
248
  else {
242
249
  let describedBy = this.control.getAttribute('aria-describedby');
@@ -244,7 +251,7 @@ class ToolTipElement extends HTMLElement {
244
251
  this.control.setAttribute('aria-describedby', describedBy);
245
252
  }
246
253
  }
247
- else if (this.isConnected && name === 'hidden') {
254
+ else if (this.isConnected && name === 'style' && (oldValue && oldValue.includes('visibility')) || (newValue && newValue.includes('visibility'))) {
248
255
  __classPrivateFieldGet(this, _ToolTipElement_instances, "m", _ToolTipElement_update).call(this);
249
256
  }
250
257
  else if (name === 'data-direction') {
@@ -286,21 +293,21 @@ class ToolTipElement extends HTMLElement {
286
293
  }
287
294
  }
288
295
  _ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new WeakMap(), _ToolTipElement_side = new WeakMap(), _ToolTipElement_allowUpdatePosition = new WeakMap(), _ToolTipElement_instances = new WeakSet(), _ToolTipElement_update = function _ToolTipElement_update() {
289
- if (this.hidden) {
296
+ if (this.visibilityHidden) {
290
297
  this.classList.remove(TOOLTIP_OPEN_CLASS, ...DIRECTION_CLASSES);
291
298
  }
292
299
  else {
293
300
  this.classList.add(TOOLTIP_OPEN_CLASS);
294
301
  for (const tooltip of this.ownerDocument.querySelectorAll(this.tagName)) {
295
302
  if (tooltip !== this)
296
- tooltip.hidden = true;
303
+ tooltip.visibilityHidden = true;
297
304
  }
298
305
  __classPrivateFieldGet(this, _ToolTipElement_instances, "m", _ToolTipElement_updatePosition).call(this);
299
306
  }
300
307
  }, _ToolTipElement_updatePosition = function _ToolTipElement_updatePosition() {
301
308
  if (!this.control)
302
309
  return;
303
- if (!__classPrivateFieldGet(this, _ToolTipElement_allowUpdatePosition, "f") || this.hidden)
310
+ if (!__classPrivateFieldGet(this, _ToolTipElement_allowUpdatePosition, "f") || this.visibilityHidden)
304
311
  return;
305
312
  const TOOLTIP_OFFSET = 10;
306
313
  this.style.left = `0px`; // Ensures we have reliable tooltip width in `getAnchoredPosition`
@@ -344,7 +351,7 @@ _ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new Wea
344
351
  }
345
352
  this.classList.add(`tooltip-${direction}`);
346
353
  };
347
- ToolTipElement.observedAttributes = ['data-type', 'data-direction', 'id', 'hidden'];
354
+ ToolTipElement.observedAttributes = ['data-type', 'data-direction', 'id', 'style'];
348
355
  if (!window.customElements.get('tool-tip')) {
349
356
  window.ToolTipElement = ToolTipElement;
350
357
  window.customElements.define('tool-tip', ToolTipElement);
@@ -176,6 +176,14 @@ class ToolTipElement extends HTMLElement {
176
176
  return this.ownerDocument.getElementById(this.htmlFor)
177
177
  }
178
178
 
179
+ set visibilityHidden(value: true | false) {
180
+ this.style.visibility = value ? 'hidden' : ''
181
+ }
182
+
183
+ get visibilityHidden() {
184
+ return this.style.visibility === 'hidden'
185
+ }
186
+
179
187
  connectedCallback() {
180
188
  if (!this.shadowRoot) {
181
189
  const shadow = this.attachShadow({mode: 'open'})
@@ -187,7 +195,7 @@ class ToolTipElement extends HTMLElement {
187
195
  <slot></slot>
188
196
  `
189
197
  }
190
- this.hidden = true
198
+ this.visibilityHidden = true
191
199
  this.#allowUpdatePosition = true
192
200
 
193
201
  if (!this.id) {
@@ -220,46 +228,47 @@ class ToolTipElement extends HTMLElement {
220
228
 
221
229
  // Ensures that tooltip stays open when hovering between tooltip and element
222
230
  // WCAG Success Criterion 1.4.13 Hoverable
223
- if ((event.type === 'mouseenter' || event.type === 'focus') && this.hidden) {
224
- this.hidden = false
231
+ if ((event.type === 'mouseenter' || event.type === 'focus') && this.visibilityHidden) {
232
+ this.visibilityHidden = false
225
233
  } else if (event.type === 'blur') {
226
- this.hidden = true
234
+ this.visibilityHidden = true
227
235
  } else if (
228
236
  event.type === 'mouseleave' &&
229
237
  (event as MouseEvent).relatedTarget !== this.control &&
230
238
  (event as MouseEvent).relatedTarget !== this
231
239
  ) {
232
- this.hidden = true
233
- } else if (event.type === 'keydown' && (event as KeyboardEvent).key === 'Escape' && !this.hidden) {
234
- this.hidden = true
240
+ this.visibilityHidden = true
241
+ } else if (event.type === 'keydown' && (event as KeyboardEvent).key === 'Escape' && !this.visibilityHidden) {
242
+ this.visibilityHidden = true
235
243
  }
236
244
  }
237
245
 
238
- static observedAttributes = ['data-type', 'data-direction', 'id', 'hidden']
246
+ static observedAttributes = ['data-type', 'data-direction', 'id', 'style']
239
247
 
240
248
  #update() {
241
- if (this.hidden) {
249
+ if (this.visibilityHidden) {
242
250
  this.classList.remove(TOOLTIP_OPEN_CLASS, ...DIRECTION_CLASSES)
243
251
  } else {
244
252
  this.classList.add(TOOLTIP_OPEN_CLASS)
245
- for (const tooltip of this.ownerDocument.querySelectorAll<HTMLElement>(this.tagName)) {
246
- if (tooltip !== this) tooltip.hidden = true
253
+ for (const tooltip of this.ownerDocument.querySelectorAll<ToolTipElement>(this.tagName)) {
254
+ if (tooltip !== this) tooltip.visibilityHidden = true
247
255
  }
248
256
  this.#updatePosition()
249
257
  }
250
258
  }
251
259
 
252
- attributeChangedCallback(name: string) {
260
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
253
261
  if (name === 'id' || name === 'data-type') {
254
262
  if (!this.id || !this.control) return
255
263
  if (this.type === 'label') {
256
264
  this.control.setAttribute('aria-labelledby', this.id)
265
+ this.setAttribute('aria-hidden', 'true')
257
266
  } else {
258
267
  let describedBy = this.control.getAttribute('aria-describedby')
259
268
  describedBy ? (describedBy = `${describedBy} ${this.id}`) : (describedBy = this.id)
260
269
  this.control.setAttribute('aria-describedby', describedBy)
261
270
  }
262
- } else if (this.isConnected && name === 'hidden') {
271
+ } else if (this.isConnected && name === 'style' && (oldValue && oldValue.includes('visibility')) || (newValue && newValue.includes('visibility'))) {
263
272
  this.#update()
264
273
  } else if (name === 'data-direction') {
265
274
  this.classList.remove(...DIRECTION_CLASSES)
@@ -294,7 +303,7 @@ class ToolTipElement extends HTMLElement {
294
303
 
295
304
  #updatePosition() {
296
305
  if (!this.control) return
297
- if (!this.#allowUpdatePosition || this.hidden) return
306
+ if (!this.#allowUpdatePosition || this.visibilityHidden) return
298
307
 
299
308
  const TOOLTIP_OFFSET = 10
300
309
 
@@ -88,8 +88,8 @@ module Primer
88
88
 
89
89
  @text = text
90
90
  @system_arguments = system_arguments
91
- @system_arguments[:hidden] = true
92
91
  @system_arguments[:tag] = :"tool-tip"
92
+ @system_arguments[:style] = join_style_arguments(@system_arguments[:style], "visibility: hidden")
93
93
  @system_arguments[:for] = for_id
94
94
  @system_arguments[:"data-direction"] = fetch_or_fallback(DIRECTION_OPTIONS, direction, DIRECTION_DEFAULT).to_s
95
95
  @system_arguments[:"data-type"] = fetch_or_fallback(TYPE_OPTIONS, type, TYPE_FALLBACK).to_s
@@ -1,24 +1,28 @@
1
1
  <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
- <label for="<%= @input_id %>" class="<%= @label_classes %>">
3
- <% if @is_label_visible %>
2
+ <div class="<%= @form_group_classes %>">
3
+ <label for="<%= @input_id %>" class="FormControl-label <% if @visually_hide_label %>sr-only<% end %>">
4
4
  <%= @label_text %>
5
+ </label>
6
+ <% if leading_visual || @show_clear_button %>
7
+ <div class="<%= @field_wrap_classes %> <% if leading_visual %>FormControl-input-wrap--leadingVisual<% end %>">
8
+ <span class="FormControl-input-leadingVisualWrap">
9
+ <%= leading_visual %>
10
+ </span>
11
+ <%= input %>
12
+ <% if @show_clear_button %>
13
+ <button id="<%= @input_id %>-clear" class="FormControl-input-trailingAction" aria-label="Clear"><%= primer_octicon "x-circle-fill" %></button>
14
+ <% end %>
15
+ </div>
5
16
  <% else %>
6
- <span class="sr-only"><%= @label_text %></span>
17
+ <%= input %>
7
18
  <% end %>
8
- </label>
9
- <span class="autocomplete-body">
10
- <% if @with_icon %>
11
- <div class="form-control autocomplete-embedded-icon-wrap">
12
- <%= render Primer::OcticonComponent.new(:search) %>
13
- <% end %>
14
- <%= input %>
15
- <% if @is_clearable %>
16
- <button id="<%= @input_id %>-clear" class="btn-octicon" aria-label="Clear"><%= primer_octicon "x" %></button>
17
- <% end %>
18
- <% if @with_icon %>
19
+ </div>
20
+ <div class="Overlay-backdrop--anchor">
21
+ <div class="Overlay Overlay--height-auto Overlay--width-auto">
22
+ <div class="Overlay-body Overlay-body--paddingNone">
23
+ <%= results %>
19
24
  </div>
20
- <% end %>
21
- <%= results %>
22
- </span>
25
+ </div>
26
+ </div>
23
27
  <div id="<%= @list_id %>-feedback" class="sr-only"></div>
24
28
  <% end %>
@@ -0,0 +1,21 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <span class="ActionList-content">
3
+ <% if leading_visual %>
4
+ <span class="ActionList-item-visual ActionList-item-visual--leading">
5
+ <%= leading_visual %>
6
+ </span>
7
+ <% end %>
8
+ <% if description %>
9
+ <span class="ActionList-item-descriptionWrap <%= description_variant_class %>">
10
+ <span class="ActionList-item-label"><%= content %></span>
11
+ <span class="ActionList-item-description"><%= description %></span>
12
+ </span>
13
+ <% else %>
14
+ <span class="ActionList-item-label"><%= content %></span>
15
+ <% end %>
16
+ <% if trailing_visual %>
17
+ <span class="ActionList-item-visual ActionList-item-visual--trailing">
18
+ <%= trailing_visual %>
19
+ </span>
20
+ <% end %>
21
+ <% end %>