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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +38 -0
- data/README.md +1 -1
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/components/primer/alpha/auto_complete/auto_complete.html.erb +24 -0
- data/app/components/primer/alpha/auto_complete/item.rb +46 -0
- data/app/components/primer/alpha/auto_complete.rb +158 -0
- data/app/components/primer/alpha/tool-tip-element.js +1 -0
- data/app/components/primer/alpha/tool-tip-element.ts +1 -0
- data/app/components/primer/beta/auto_complete/auto_complete.html.erb +21 -17
- data/app/components/primer/beta/auto_complete/item.html.erb +21 -0
- data/app/components/primer/beta/auto_complete/item.rb +42 -6
- data/app/components/primer/beta/auto_complete.rb +93 -55
- data/app/components/primer/component.rb +1 -1
- data/app/components/primer/conditional_wrapper.rb +36 -0
- data/app/components/primer/layout_component.html.erb +1 -0
- data/lib/primer/view_components/linters/deprecated_components_counter.rb +49 -0
- data/lib/primer/view_components/linters/helpers/deprecated_components_helpers.rb +46 -0
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/rubocop/config/default.yml +2 -26
- data/lib/rubocop/cop/primer/deprecated_arguments.rb +10 -0
- data/lib/rubocop/cop/primer/deprecated_components.rb +2 -33
- data/lib/tasks/docs.rake +3 -3
- data/static/arguments.yml +40 -13
- data/static/audited_at.json +3 -0
- data/static/classes.yml +23 -7
- data/static/constants.json +23 -1
- data/static/statuses.json +3 -0
- 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
|
@@ -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
|
-
<
|
3
|
-
<% if @
|
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
|
-
|
17
|
+
<%= input %>
|
7
18
|
<% end %>
|
8
|
-
</
|
9
|
-
<
|
10
|
-
|
11
|
-
<div class="
|
12
|
-
<%=
|
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
|
-
|
21
|
-
|
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
|
-
"
|
33
|
-
system_arguments[:classes]
|
34
|
-
"disabled" => disabled
|
63
|
+
"ActionList-item",
|
64
|
+
system_arguments[:classes]
|
35
65
|
)
|
36
66
|
end
|
37
67
|
|
38
|
-
|
39
|
-
|
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
|
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
|
-
"
|
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 `
|
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
|
-
"
|
62
|
-
|
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
|
93
|
+
# @example Leading visual
|
69
94
|
# @description
|
70
|
-
#
|
95
|
+
# Display any Octicon as a leading visual within the field
|
71
96
|
# @code
|
72
|
-
# <%= render(Primer::Beta::AutoComplete.new(label_text: "
|
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
|
101
|
+
# @example Trailing action
|
75
102
|
# @description
|
76
|
-
#
|
103
|
+
# Show a clear button
|
77
104
|
# @code
|
78
|
-
# <%= render(Primer::Beta::AutoComplete.new(label_text: "
|
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
|
107
|
+
# @example Visually hidden label
|
81
108
|
# @description
|
82
|
-
# A non-visible label may be rendered with `
|
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: "
|
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
|
115
|
+
# @example Full width field
|
87
116
|
# @description
|
88
|
-
# To
|
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: "
|
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
|
93
|
-
#
|
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
|
96
|
-
#
|
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")
|
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
|
121
|
-
# @param
|
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
|
-
|
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
|
-
@
|
131
|
-
@
|
132
|
-
@
|
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
|