primer_view_components 0.0.81 → 0.0.84

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 (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +38 -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/components/primer/alpha/auto_complete/auto_complete.html.erb +24 -0
  7. data/app/components/primer/alpha/auto_complete/item.rb +46 -0
  8. data/app/components/primer/alpha/auto_complete.rb +158 -0
  9. data/app/components/primer/alpha/tool-tip-element.js +1 -0
  10. data/app/components/primer/alpha/tool-tip-element.ts +1 -0
  11. data/app/components/primer/beta/auto_complete/auto_complete.html.erb +21 -17
  12. data/app/components/primer/beta/auto_complete/item.html.erb +21 -0
  13. data/app/components/primer/beta/auto_complete/item.rb +42 -6
  14. data/app/components/primer/beta/auto_complete.rb +93 -55
  15. data/app/components/primer/component.rb +1 -1
  16. data/app/components/primer/conditional_wrapper.rb +36 -0
  17. data/app/components/primer/layout_component.html.erb +1 -0
  18. data/lib/primer/view_components/linters/deprecated_components_counter.rb +49 -0
  19. data/lib/primer/view_components/linters/helpers/deprecated_components_helpers.rb +46 -0
  20. data/lib/primer/view_components/version.rb +1 -1
  21. data/lib/rubocop/config/default.yml +2 -26
  22. data/lib/rubocop/cop/primer/deprecated_arguments.rb +10 -0
  23. data/lib/rubocop/cop/primer/deprecated_components.rb +2 -33
  24. data/lib/tasks/docs.rake +3 -3
  25. data/static/arguments.yml +40 -13
  26. data/static/audited_at.json +3 -0
  27. data/static/classes.yml +23 -7
  28. data/static/constants.json +23 -1
  29. data/static/statuses.json +3 -0
  30. metadata +43 -8
@@ -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 :alpha
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 :alpha
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
@@ -180,6 +180,7 @@ class ToolTipElement extends HTMLElement {
180
180
  var _a;
181
181
  if (!this.shadowRoot) {
182
182
  const shadow = this.attachShadow({ mode: 'open' });
183
+ // eslint-disable-next-line github/no-inner-html
183
184
  shadow.innerHTML = `
184
185
  <style>
185
186
  ${this.styles()}
@@ -179,6 +179,7 @@ class ToolTipElement extends HTMLElement {
179
179
  connectedCallback() {
180
180
  if (!this.shadowRoot) {
181
181
  const shadow = this.attachShadow({mode: 'open'})
182
+ // eslint-disable-next-line github/no-inner-html
182
183
  shadow.innerHTML = `
183
184
  <style>
184
185
  ${this.styles()}
@@ -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 %>
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # TODO: use generic ActionList item for Autocomplete
3
4
  module Primer
4
5
  module Beta
5
6
  class AutoComplete
@@ -7,6 +8,32 @@ module Primer
7
8
  class Item < Primer::Component
8
9
  status :beta
9
10
 
11
+ ALLOWED_DESCRIPTION_VARIANTS = [:inline, :block].freeze
12
+
13
+ # The leading visual rendered before the link.
14
+ #
15
+ # @param kwargs [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Avatar) %> or <%= link_to_component(Primer::OcticonComponent) %>
16
+ renders_one :leading_visual, types: {
17
+ icon: Primer::OcticonComponent,
18
+ avatar: lambda { |**kwargs|
19
+ Primer::Beta::Avatar.new(**{ **kwargs, size: 16 })
20
+ }
21
+ }
22
+
23
+ # The trailing visual rendered after the link.
24
+ #
25
+ # @param kwargs [Hash] The arguments accepted by <%= link_to_component(Primer::OcticonComponent) %>, <%= link_to_component(Primer::LabelComponent) %>, or <%= link_to_component(Primer::CounterComponent) %>
26
+ renders_one :trailing_visual, types: {
27
+ icon: Primer::OcticonComponent,
28
+ label: Primer::LabelComponent,
29
+ counter: Primer::CounterComponent
30
+ }
31
+
32
+ # Optional description
33
+ #
34
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
35
+ renders_one :description
36
+
10
37
  # @example Default
11
38
  # <%= render(Primer::Beta::AutoComplete::Item.new(selected: true, value: "value")) do |c| %>
12
39
  # Selected
@@ -18,8 +45,12 @@ module Primer
18
45
  # @param value [String] Value of the item.
19
46
  # @param selected [Boolean] Whether the item is selected.
20
47
  # @param disabled [Boolean] Whether the item is disabled.
48
+ # @param description_variant [Hash] Changes the description style. Allowed values are :inline, :block
49
+ # @param description [String] Display description text below label
21
50
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
22
- def initialize(value:, selected: false, disabled: false, **system_arguments)
51
+ def initialize(value:, selected: false, disabled: false, description_variant: :block, **system_arguments)
52
+ @description_variant = ALLOWED_DESCRIPTION_VARIANTS.include?(description_variant) ? description_variant : :block
53
+
23
54
  @system_arguments = deny_tag_argument(**system_arguments)
24
55
  @system_arguments[:tag] = :li
25
56
  @system_arguments[:role] = :option
@@ -29,14 +60,19 @@ module Primer
29
60
  @system_arguments[:"aria-disabled"] = true if disabled
30
61
 
31
62
  @system_arguments[:classes] = class_names(
32
- "autocomplete-item",
33
- system_arguments[:classes],
34
- "disabled" => disabled
63
+ "ActionList-item",
64
+ system_arguments[:classes]
35
65
  )
36
66
  end
37
67
 
38
- def call
39
- render(Primer::BaseComponent.new(**@system_arguments)) { content }
68
+ # Description variant class.
69
+ def description_variant_class
70
+ case @description_variant
71
+ when :block
72
+ "ActionList-item-blockDescription"
73
+ when :inline
74
+ "ActionList-item-descriptionWrap--inline"
75
+ end
40
76
  end
41
77
  end
42
78
  end
@@ -8,12 +8,20 @@ module Primer
8
8
  # Always set an accessible label to help the user interact with the component.
9
9
  #
10
10
  # * `label_text` is required and visible by default.
11
- # * If you must use a non-visible label, set `is_label_visible` to `false`.
11
+ # * If you must hide the label, set `visually_hide_label` to `true`.
12
12
  # However, please note that a visible label should almost always
13
13
  # be used unless there is compelling reason not to. A placeholder is not a label.
14
14
  class AutoComplete < Primer::Component
15
15
  status :beta
16
- #
16
+
17
+ DEFAULT_SIZE = :medium
18
+ SIZE_MAPPINGS = {
19
+ :small => "FormControl-small",
20
+ DEFAULT_SIZE => "FormControl-medium",
21
+ :large => "FormControl-large"
22
+ }.freeze
23
+ SIZE_OPTIONS = SIZE_MAPPINGS.keys
24
+
17
25
  # Customizable results list.
18
26
  #
19
27
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
@@ -22,13 +30,25 @@ module Primer
22
30
  system_arguments[:tag] = :ul
23
31
  system_arguments[:id] = @list_id
24
32
  system_arguments[:classes] = class_names(
25
- "autocomplete-results",
33
+ "ActionList",
26
34
  system_arguments[:classes]
27
35
  )
28
36
 
29
37
  Primer::BaseComponent.new(**system_arguments)
30
38
  }
31
39
 
40
+ # Leading visual.
41
+ #
42
+ # - `leading_visual_icon` for a <%= link_to_component(Primer::OcticonComponent) %>.
43
+ #
44
+ # @param system_arguments [Hash] Same arguments as <%= link_to_component(Primer::OcticonComponent) %>.
45
+ renders_one :leading_visual, types: {
46
+ icon: lambda { |**system_arguments|
47
+ system_arguments[:classes] = class_names("FormControl-input-leadingVisual")
48
+ Primer::OcticonComponent.new(**system_arguments)
49
+ }
50
+ }
51
+
32
52
  # Customizable input used to search for results.
33
53
  # It is preferred to use this slot sparingly - it will be created by default if not explicity added.
34
54
  #
@@ -38,7 +58,7 @@ module Primer
38
58
  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)
39
59
  deny_aria_key(
40
60
  :label,
41
- "instead of `aria-label`, include `label_text` and set `is_label_visible` to `false` on the component initializer.",
61
+ "instead of `aria-label`, include `label_text` and set `visually_hide_label` to `true` on the component initializer.",
42
62
  **sanitized_args
43
63
  )
44
64
  deny_single_argument(
@@ -55,45 +75,66 @@ module Primer
55
75
  sanitized_args[:name] = @input_name
56
76
  sanitized_args[:tag] = :input
57
77
  sanitized_args[:autocomplete] = "off"
58
-
78
+ sanitized_args[:disabled] = true if @disabled
79
+ sanitized_args[:invalid] = true if @invalid
59
80
  sanitized_args[:type] = :text
60
81
  sanitized_args[:classes] = class_names(
61
- "form-control",
62
- sanitized_args[:classes]
82
+ "FormControl-input",
83
+ SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, @size, DEFAULT_SIZE)],
84
+ sanitized_args[:classes],
85
+ "FormControl-inset": @inset,
86
+ "FormControl-monospace": @monospace
63
87
  )
88
+ sanitized_args[:placeholder] = @placeholder
64
89
 
65
90
  Primer::BaseComponent.new(**sanitized_args)
66
91
  }
67
92
 
68
- # @example Default
93
+ # @example Leading visual
69
94
  # @description
70
- # Labels are stacked by default.
95
+ # Display any Octicon as a leading visual within the field
71
96
  # @code
72
- # <%= render(Primer::Beta::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--default", list_id: "fruits-popup--default")) %>
97
+ # <%= render(Primer::Beta::AutoComplete.new(label_text: "Select a fruit", src: "/auto_complete", input_id:"input-id-1", list_id: "list-id-1")) do |c| %>
98
+ # <% c.leading_visual_icon(icon: :search) %>
99
+ # <% end %>
73
100
  #
74
- # @example With inline label
101
+ # @example Trailing action
75
102
  # @description
76
- # Labels can be inline by setting `is_label_inline: true`. However, labels will always become stacked on smaller screen sizes.
103
+ # Show a clear button
77
104
  # @code
78
- # <%= render(Primer::Beta::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", is_label_inline: true, input_id: "fruits-input--inline-label", list_id: "fruits-popup--inline-label")) %>
105
+ # <%= render(Primer::Beta::AutoComplete.new(label_text: "Select a fruit", input_id: "input-id-2", list_id: "list-id-2", src: "/auto_complete", show_clear_button: true )) %>
79
106
  #
80
- # @example With non-visible label
107
+ # @example Visually hidden label
81
108
  # @description
82
- # A non-visible label may be rendered with `is_label_visible: false`, but it is highly discouraged. See <%= link_to_accessibility %>.
109
+ # A non-visible label may be rendered with `visually_hide_label: true`, but it is highly discouraged. See <%= link_to_accessibility %>.
83
110
  # @code
84
- # <%= render(Primer::Beta::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)) %>
111
+ # <%= render(Primer::Beta::AutoComplete.new(label_text: "Select a fruit", input_id: "fruits-input--custom-results-1", list_id: "fruits-popup--custom-result-1", src: "/auto_complete", visually_hide_label: true)) do |c| %>
112
+ # <% c.leading_visual_icon(icon: :search) %>
113
+ # <% end %>
85
114
  #
86
- # @example With icon
115
+ # @example Full width field
87
116
  # @description
88
- # To display a search icon, set `with_icon` to `true`.
117
+ # To allow field to span width of its container, set `full_width` to `true`.
89
118
  # @code
90
- # <%= render(Primer::Beta::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", list_id: "fruits-popup--icon", input_id: "fruits-input--icon", with_icon: true)) %>
119
+ # <%= render(Primer::Beta::AutoComplete.new(label_text: "Select a fruit", input_id: "fruits-input--custom-results-2", list_id: "fruits-popup--custom-results-2", src: "/auto_complete", full_width: true)) do |c| %>
120
+ # <% c.leading_visual_icon(icon: :search) %>
121
+ # <% end %>
91
122
  #
92
- # @example With icon and non-visible label
93
- # <%= render(Primer::Beta::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)) %>
123
+ # @example Inset variant
124
+ # @description
125
+ # Use the `inset` variant to change the input background color to be subtle.
126
+ # @code
127
+ # <%= render(Primer::Beta::AutoComplete.new(label_text: "Select a fruit", input_id: "fruits-input--custom-results-2", list_id: "fruits-popup--custom-results-2", src: "/auto_complete", inset: true)) do |c| %>
128
+ # <% c.leading_visual_icon(icon: :search) %>
129
+ # <% end %>
94
130
  #
95
- # @example With clear button
96
- # <%= render(Primer::Beta::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--clear", list_id: "fruits-popup--clear", is_clearable: true)) %>
131
+ # @example Monospace variant
132
+ # @description
133
+ # Use the `monospace` variant to change the input font family.
134
+ # @code
135
+ # <%= render(Primer::Beta::AutoComplete.new(label_text: "Select a fruit", input_id: "fruits-input--custom-results-2", list_id: "fruits-popup--custom-results-2", src: "/auto_complete", monospace: true)) do |c| %>
136
+ # <% c.leading_visual_icon(icon: :search) %>
137
+ # <% end %>
97
138
  #
98
139
  # @example With custom classes for the input
99
140
  # <%= render(Primer::Beta::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--custom-input", list_id: "fruits-popup--custom-input")) do |c| %>
@@ -102,14 +143,7 @@ module Primer
102
143
  #
103
144
  # @example With custom classes for the results
104
145
  # <%= render(Primer::Beta::AutoComplete.new(label_text: "Fruits", src: "/auto_complete", input_id: "fruits-input--custom-results", list_id: "fruits-popup--custom-results")) do |c| %>
105
- # <% c.results(classes: "custom-class") do %>
106
- # <%= render(Primer::Beta::AutoComplete::Item.new(selected: true, value: "apple")) do |c| %>
107
- # Apple
108
- # <% end %>
109
- # <%= render(Primer::Beta::AutoComplete::Item.new(value: "orange")) do |c| %>
110
- # Orange
111
- # <% end %>
112
- # <% end %>
146
+ # <% c.results(classes: "custom-class") %>
113
147
  # <% end %>
114
148
  #
115
149
  # @param label_text [String] The label of the input.
@@ -117,25 +151,43 @@ module Primer
117
151
  # @param input_id [String] Id of the input element.
118
152
  # @param input_name [String] Optional name of the input element, defaults to `input_id` when not set.
119
153
  # @param list_id [String] Id of the list element.
120
- # @param with_icon [Boolean] Controls if a search icon is visible, defaults to `false`.
121
- # @param is_label_visible [Boolean] Controls if the label is visible. If `false`, screen reader only text will be added.
122
- # @param is_clearable [Boolean] Adds optional clear button.
123
- # @param is_label_inline [Boolean] Controls if the label is inline. On smaller screens, label will always become stacked.
154
+ # @param visually_hide_label [Boolean] Controls if the label is visible. If `true`, screen reader only text will be added.
155
+ # @param show_clear_button [Boolean] Adds optional clear button.
124
156
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
125
- 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)
157
+ # @param size [Hash] Input size can be small, medium (default), or large
158
+ # @param full_width [Boolean] Input can be full-width or fit to content
159
+ # @param disabled [Boolean] Disabled input
160
+ # @param invalid [Boolean] Invalid input
161
+ # @param placeholder [String] The placeholder text displayed within the input
162
+ # @param inset [Boolean] subtle input background color
163
+ # @param monospace [Boolean] monospace input font family
164
+ def initialize(label_text:, src:, list_id:, input_id:, input_name: nil, placeholder: nil, show_clear_button: false, visually_hide_label: false, size: DEFAULT_SIZE, full_width: false, disabled: false, invalid: false, inset: false, monospace: false, **system_arguments)
126
165
  @label_text = label_text
127
166
  @list_id = list_id
128
167
  @input_id = input_id
129
168
  @input_name = input_name || input_id
130
- @is_label_visible = is_label_visible
131
- @with_icon = with_icon
132
- @is_clearable = is_clearable
133
-
134
- @label_classes = label_classes(is_label_visible: is_label_visible, is_label_inline: is_label_inline)
169
+ @placeholder = placeholder
170
+ @visually_hide_label = visually_hide_label
171
+ @show_clear_button = show_clear_button
135
172
  @system_arguments = deny_tag_argument(**system_arguments)
136
173
  @system_arguments[:tag] = "auto-complete"
137
174
  @system_arguments[:src] = src
138
175
  @system_arguments[:for] = list_id
176
+ @disabled = disabled
177
+ @invalid = invalid
178
+ @size = size
179
+ @inset = inset
180
+ @monospace = monospace
181
+ @full_width = full_width
182
+ @field_wrap_classes = class_names(
183
+ "FormControl-input-wrap",
184
+ SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, @size, DEFAULT_SIZE)],
185
+ "FormControl-input-wrap--trailingAction": show_clear_button
186
+ )
187
+ @form_group_classes = class_names(
188
+ "FormControl",
189
+ "FormControl--fullWidth": full_width
190
+ )
139
191
  end
140
192
 
141
193
  # add `input` and `results` without needing to explicitly call them in the view
@@ -143,20 +195,6 @@ module Primer
143
195
  results(classes: "") unless results
144
196
  input(classes: "") unless input
145
197
  end
146
-
147
- private
148
-
149
- # Private: determines the label classes based on component configration.
150
- #
151
- # If the label is not visible, return an empty string.
152
- #
153
- # @param args [Hash] The component configuration.
154
- # @return [String] The label classes.
155
- def label_classes(**args)
156
- return "" if args[:is_label_visible] == false
157
-
158
- args[:is_label_inline] ? "autocomplete-label-inline" : "autocomplete-label-stacked"
159
- end
160
198
  end
161
199
  end
162
200
  end
@@ -6,7 +6,7 @@ module Primer
6
6
  # @private
7
7
  class Component < ViewComponent::Base
8
8
  include ViewComponent::SlotableV2 unless ViewComponent::Base < ViewComponent::SlotableV2
9
- include ViewComponent::PolymorphicSlots
9
+ include ViewComponent::PolymorphicSlots unless ViewComponent::Base < ViewComponent::PolymorphicSlots
10
10
  include ClassNameHelper
11
11
  include FetchOrFallbackHelper
12
12
  include TestSelectorHelper