openproject-primer_view_components 0.80.2 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +36 -22
- data/README.md +20 -1
- data/app/assets/javascripts/components/primer/primer.d.ts +1 -0
- data/app/assets/javascripts/lib/primer/forms/character_counter.d.ts +41 -0
- data/app/assets/javascripts/lib/primer/forms/primer_text_area.d.ts +13 -0
- data/app/assets/javascripts/lib/primer/forms/primer_text_field.d.ts +2 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/action_list/item.rb +2 -1
- data/app/components/primer/alpha/auto_complete/auto_complete.html.erb +8 -6
- data/app/components/primer/alpha/select_panel.rb +1 -1
- data/app/components/primer/alpha/select_panel_element.js +1 -1
- data/app/components/primer/alpha/select_panel_element.ts +1 -1
- data/app/components/primer/alpha/stack.rb +1 -0
- data/app/components/primer/alpha/tab_nav.css +1 -1
- data/app/components/primer/alpha/tab_nav.css.json +1 -0
- data/app/components/primer/alpha/tab_nav.css.map +1 -1
- data/app/components/primer/alpha/tab_nav.pcss +7 -1
- data/app/components/primer/alpha/text_area.rb +1 -0
- data/app/components/primer/alpha/text_field.rb +1 -0
- data/app/components/primer/alpha/toggle_switch.html.erb +2 -2
- data/app/components/primer/alpha/tool_tip.js +12 -5
- data/app/components/primer/alpha/tool_tip.ts +14 -5
- data/app/components/primer/beta/auto_complete/item.html.erb +5 -4
- data/app/components/primer/beta/avatar.rb +4 -0
- data/app/components/primer/beta/avatar_stack.rb +6 -0
- data/app/components/primer/beta/blankslate.css +1 -1
- data/app/components/primer/beta/blankslate.css.map +1 -1
- data/app/components/primer/beta/blankslate.pcss +2 -0
- data/app/components/primer/beta/spinner.html.erb +2 -2
- data/app/components/primer/primer.d.ts +1 -0
- data/app/components/primer/primer.js +1 -0
- data/app/components/primer/primer.ts +1 -0
- data/app/controllers/primer/view_components/toggle_switch_controller.rb +2 -2
- data/app/forms/check_box_with_nested_form.rb +9 -5
- data/app/forms/text_area_with_character_limit_form.rb +13 -0
- data/app/forms/text_field_with_character_limit_form.rb +13 -0
- data/app/lib/primer/forms/caption.html.erb +16 -9
- data/app/lib/primer/forms/character_counter.d.ts +41 -0
- data/app/lib/primer/forms/character_counter.js +114 -0
- data/app/lib/primer/forms/character_counter.ts +129 -0
- data/app/lib/primer/forms/check_box.rb +28 -0
- data/app/lib/primer/forms/dsl/input.rb +23 -0
- data/app/lib/primer/forms/dsl/multi_input.rb +3 -1
- data/app/lib/primer/forms/dsl/text_area_input.rb +12 -1
- data/app/lib/primer/forms/dsl/text_field_input.rb +11 -1
- data/app/lib/primer/forms/form_control.html.erb +2 -1
- data/app/lib/primer/forms/primer_text_area.d.ts +13 -0
- data/app/lib/primer/forms/primer_text_area.js +53 -0
- data/app/lib/primer/forms/primer_text_area.ts +37 -0
- data/app/lib/primer/forms/primer_text_field.d.ts +2 -0
- data/app/lib/primer/forms/primer_text_field.js +16 -2
- data/app/lib/primer/forms/primer_text_field.ts +16 -3
- data/app/lib/primer/forms/text_area.html.erb +6 -4
- data/app/lib/primer/forms/text_field.html.erb +1 -1
- data/app/lib/primer/forms/text_field.rb +8 -0
- data/lib/primer/accessibility.rb +9 -3
- data/lib/primer/view_components/engine.rb +1 -4
- data/lib/primer/view_components/version.rb +2 -2
- data/previews/primer/alpha/action_menu_preview/submitting_forms.html.erb +1 -1
- data/previews/primer/alpha/form_control_preview/playground.html.erb +4 -2
- data/previews/primer/alpha/octicon_symbols_preview/playground.html.erb +1 -1
- data/previews/primer/alpha/overlay_preview.rb +0 -25
- data/previews/primer/alpha/text_area_preview.rb +29 -8
- data/previews/primer/alpha/text_field_preview.rb +34 -4
- data/previews/primer/alpha/toggle_switch_preview.rb +14 -14
- data/previews/primer/alpha/tree_view_preview/loading_failure.html.erb +53 -1
- data/previews/primer/alpha/tree_view_preview/stress_test.html.erb +43 -0
- data/previews/primer/beta/button_preview/all_schemes.html.erb +1 -1
- data/previews/primer/beta/button_preview/invisible_all_visuals.html.erb +1 -1
- data/previews/primer/beta/button_preview/summary_as_button.html.erb +10 -1
- data/previews/primer/forms_preview/text_area_with_character_limit_form.html.erb +3 -0
- data/previews/primer/forms_preview/text_field_with_character_limit_form.html.erb +3 -0
- data/previews/primer/forms_preview.rb +6 -0
- data/static/arguments.json +13 -1
- data/static/form_previews.json +10 -0
- data/static/info_arch.json +106 -15
- data/static/previews.json +93 -14
- metadata +15 -2
|
@@ -80,6 +80,14 @@ module Primer
|
|
|
80
80
|
Primer::Beta::Truncate.new(**truncate_arguments).with_content(text)
|
|
81
81
|
end
|
|
82
82
|
end
|
|
83
|
+
|
|
84
|
+
def character_limit_validation_arguments
|
|
85
|
+
{
|
|
86
|
+
class: "FormControl-inlineValidation",
|
|
87
|
+
id: @input.character_limit_validation_id,
|
|
88
|
+
hidden: true
|
|
89
|
+
}
|
|
90
|
+
end
|
|
83
91
|
end
|
|
84
92
|
end
|
|
85
93
|
end
|
data/lib/primer/accessibility.rb
CHANGED
|
@@ -32,6 +32,10 @@ module Primer
|
|
|
32
32
|
per_component: {
|
|
33
33
|
Primer::Alpha::ToggleSwitch => {
|
|
34
34
|
all_scenarios: %i[button-name]
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
Primer::Alpha::MultiInput => {
|
|
38
|
+
visually_hide_label: %i[label-title-only]
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
}
|
|
@@ -46,6 +50,8 @@ module Primer
|
|
|
46
50
|
end
|
|
47
51
|
|
|
48
52
|
def axe_rules_to_skip(component: nil, scenario_name: nil, flatten: false)
|
|
53
|
+
scenario_key = scenario_name.is_a?(String) ? scenario_name.to_sym : scenario_name
|
|
54
|
+
|
|
49
55
|
to_skip = {
|
|
50
56
|
wont_fix: Set.new(AXE_RULES_TO_SKIP.dig(:wont_fix, :global) || []),
|
|
51
57
|
will_fix: Set.new(AXE_RULES_TO_SKIP.dig(:will_fix, :global) || [])
|
|
@@ -55,9 +61,9 @@ module Primer
|
|
|
55
61
|
to_skip[:wont_fix].merge(AXE_RULES_TO_SKIP.dig(:wont_fix, :per_component, component, :all_scenarios) || [])
|
|
56
62
|
to_skip[:will_fix].merge(AXE_RULES_TO_SKIP.dig(:will_fix, :per_component, component, :all_scenarios) || [])
|
|
57
63
|
|
|
58
|
-
if
|
|
59
|
-
to_skip[:wont_fix].merge(AXE_RULES_TO_SKIP.dig(:wont_fix, :per_component, component,
|
|
60
|
-
to_skip[:will_fix].merge(AXE_RULES_TO_SKIP.dig(:will_fix, :per_component, component,
|
|
64
|
+
if scenario_key
|
|
65
|
+
to_skip[:wont_fix].merge(AXE_RULES_TO_SKIP.dig(:wont_fix, :per_component, component, scenario_key) || [])
|
|
66
|
+
to_skip[:will_fix].merge(AXE_RULES_TO_SKIP.dig(:will_fix, :per_component, component, scenario_key) || [])
|
|
61
67
|
end
|
|
62
68
|
end
|
|
63
69
|
|
|
@@ -48,10 +48,7 @@ module Primer
|
|
|
48
48
|
|
|
49
49
|
initializer "primer.forms.helpers" do
|
|
50
50
|
ActiveSupport.on_load :action_controller_base do
|
|
51
|
-
|
|
52
|
-
require "primer/form_helper"
|
|
53
|
-
rescue LoadError
|
|
54
|
-
end
|
|
51
|
+
require_relative "../../../app/helpers/primer/form_helper"
|
|
55
52
|
|
|
56
53
|
helper Primer::FormHelper
|
|
57
54
|
|
|
@@ -8,10 +8,12 @@
|
|
|
8
8
|
|
|
9
9
|
<br>
|
|
10
10
|
|
|
11
|
+
<% field_id = "bar-#{SecureRandom.hex}" %>
|
|
12
|
+
|
|
11
13
|
<%= form_with(url: "/foo") do |f| %>
|
|
12
|
-
<%= render(Primer::Alpha::FormControl.new(**system_arguments, label_arguments: { for:
|
|
14
|
+
<%= render(Primer::Alpha::FormControl.new(**system_arguments, label_arguments: { for: field_id })) do |component| %>
|
|
13
15
|
<% component.with_input do |input_arguments| %>
|
|
14
|
-
<%= f.text_field(:bar, **input_arguments) %>
|
|
16
|
+
<%= f.text_field(:bar, id: field_id, **input_arguments) %>
|
|
15
17
|
<% end %>
|
|
16
18
|
<% end %>
|
|
17
19
|
<% end %>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<p style="max-width: 500px">
|
|
2
2
|
Below is an SVG image containing the chosen octicon surrounded by a green circle. The octicon has been emitted
|
|
3
3
|
onto the page as an SVG <symbol> element and included into the SVG you see below with the <use> element.
|
|
4
|
-
See the <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol" target="_blank">MDN docs</a> for
|
|
4
|
+
See the <a href="https://developer.mozilla.org/en-US/docs/Web/SVG/Element/symbol" target="_blank" style="text-decoration: underline">MDN docs</a> for
|
|
5
5
|
more information.
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -77,31 +77,6 @@ module Primer
|
|
|
77
77
|
end
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
# @label Menu No Header
|
|
81
|
-
#
|
|
82
|
-
# @param size [Symbol] select [auto, small, medium, medium_portrait, large, xlarge]
|
|
83
|
-
# @param padding [Symbol] select [normal, condensed, none]
|
|
84
|
-
# @param anchor_align [Symbol] select [start, center, end]
|
|
85
|
-
# @param anchor_side [Symbol] select [inside_top, inside_bottom, inside_left, inside_right, inside_center, outside_top, outside_bottom, outside_left, outside_right]
|
|
86
|
-
# @param allow_out_of_bounds [Boolean] toggle
|
|
87
|
-
#
|
|
88
|
-
# @param button_text [String] text
|
|
89
|
-
# @param body_text [String] text
|
|
90
|
-
def menu_no_header(size: :auto, padding: :normal, anchor_align: :center, anchor_side: :outside_bottom, allow_out_of_bounds: false, button_text: "Show Overlay Menu", body_text: "This is a menu")
|
|
91
|
-
render(Primer::Alpha::Overlay.new(
|
|
92
|
-
title: "Menu",
|
|
93
|
-
role: :menu,
|
|
94
|
-
size: size,
|
|
95
|
-
padding: padding,
|
|
96
|
-
anchor_align: anchor_align,
|
|
97
|
-
anchor_side: anchor_side,
|
|
98
|
-
allow_out_of_bounds: allow_out_of_bounds
|
|
99
|
-
)) do |d|
|
|
100
|
-
d.with_show_button { button_text }
|
|
101
|
-
d.with_body { body_text }
|
|
102
|
-
end
|
|
103
|
-
end
|
|
104
|
-
|
|
105
80
|
# @label Middle Of Page
|
|
106
81
|
#
|
|
107
82
|
# @param title [String] text
|
|
@@ -16,6 +16,7 @@ module Primer
|
|
|
16
16
|
# @param disabled toggle
|
|
17
17
|
# @param invalid toggle
|
|
18
18
|
# @param validation_message text
|
|
19
|
+
# @param character_limit number
|
|
19
20
|
# @param input_width [Symbol] select [auto, xsmall, small, medium, large, xlarge, xxlarge]
|
|
20
21
|
def playground(
|
|
21
22
|
name: "my-text-area",
|
|
@@ -28,6 +29,7 @@ module Primer
|
|
|
28
29
|
disabled: false,
|
|
29
30
|
invalid: false,
|
|
30
31
|
validation_message: nil,
|
|
32
|
+
character_limit: nil,
|
|
31
33
|
input_width: nil
|
|
32
34
|
)
|
|
33
35
|
system_arguments = {
|
|
@@ -41,6 +43,7 @@ module Primer
|
|
|
41
43
|
disabled: disabled,
|
|
42
44
|
invalid: invalid,
|
|
43
45
|
validation_message: validation_message,
|
|
46
|
+
character_limit: character_limit,
|
|
44
47
|
input_width: input_width
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -50,7 +53,7 @@ module Primer
|
|
|
50
53
|
# @label Default
|
|
51
54
|
# @snapshot
|
|
52
55
|
def default
|
|
53
|
-
render(Primer::Alpha::TextArea.new(name: "my-text-area", label: "Tell me about yourself"))
|
|
56
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-default", name: "my-text-area-default", label: "Tell me about yourself"))
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
# @!group Options
|
|
@@ -58,43 +61,61 @@ module Primer
|
|
|
58
61
|
# @label With caption
|
|
59
62
|
# @snapshot
|
|
60
63
|
def with_caption
|
|
61
|
-
render(Primer::Alpha::TextArea.new(
|
|
64
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-caption", name: "my-text-area-with-caption", caption: "With a caption", label: "Tell me about yourself"))
|
|
62
65
|
end
|
|
63
66
|
|
|
64
67
|
# @label Visually hidden label
|
|
65
68
|
# @snapshot
|
|
66
69
|
def visually_hide_label
|
|
67
|
-
render(Primer::Alpha::TextArea.new(
|
|
70
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-visually-hide-label", name: "my-text-area-visually-hide-label", visually_hide_label: true, label: "Tell me about yourself"))
|
|
68
71
|
end
|
|
69
72
|
|
|
70
73
|
# @label Full width
|
|
71
74
|
# @snapshot
|
|
72
75
|
def full_width
|
|
73
|
-
render(Primer::Alpha::TextArea.new(
|
|
76
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-full-width", name: "my-text-area-full-width", full_width: true, label: "Tell me about yourself"))
|
|
74
77
|
end
|
|
75
78
|
|
|
76
79
|
# @label Not full width
|
|
77
80
|
# @snapshot
|
|
78
81
|
def not_full_width
|
|
79
|
-
render(Primer::Alpha::TextArea.new(
|
|
82
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-not-full-width", name: "my-text-area-not-full-width", full_width: false, label: "Tell me about yourself"))
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
# @label Disabled
|
|
83
86
|
# @snapshot
|
|
84
87
|
def disabled
|
|
85
|
-
render(Primer::Alpha::TextArea.new(
|
|
88
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-disabled", name: "my-text-area-disabled", disabled: true, label: "Tell me about yourself"))
|
|
86
89
|
end
|
|
87
90
|
|
|
88
91
|
# @label Invalid
|
|
89
92
|
# @snapshot
|
|
90
93
|
def invalid
|
|
91
|
-
render(Primer::Alpha::TextArea.new(
|
|
94
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-invalid", name: "my-text-area-invalid", invalid: true, label: "Tell me about yourself"))
|
|
92
95
|
end
|
|
93
96
|
|
|
94
97
|
# @label With validation message
|
|
95
98
|
# @snapshot
|
|
96
99
|
def with_validation_message
|
|
97
|
-
render(Primer::Alpha::TextArea.new(
|
|
100
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-validation-message", name: "my-text-area-with-validation-message", validation_message: "An error occurred!", label: "Tell me about yourself"))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# @label With character limit
|
|
104
|
+
# @snapshot interactive
|
|
105
|
+
def with_character_limit
|
|
106
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit", name: "my-text-area-with-character-limit", character_limit: 10, label: "Tell me about yourself"))
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# @label With character limit, over limit
|
|
110
|
+
# @snapshot interactive
|
|
111
|
+
def with_character_limit_over_limit
|
|
112
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit-over-limit", name: "my-text-area-with-character-limit-over-limit", character_limit: 10, label: "Tell me about yourself", value: "This text is definitely over the limit."))
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# @label With character limit and caption
|
|
116
|
+
# @snapshot
|
|
117
|
+
def with_character_limit_and_caption
|
|
118
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit-and-caption", name: "my-text-area-with-character-limit-and-caption", character_limit: 100, caption: "With a caption.", label: "Tell me about yourself"))
|
|
98
119
|
end
|
|
99
120
|
#
|
|
100
121
|
# @!endgroup
|
|
@@ -15,6 +15,7 @@ module Primer
|
|
|
15
15
|
# @param size [Symbol] select [small, medium, large]
|
|
16
16
|
# @param show_clear_button toggle
|
|
17
17
|
# @param clear_button_id text
|
|
18
|
+
# @param clear_button_label text
|
|
18
19
|
# @param full_width toggle
|
|
19
20
|
# @param disabled toggle
|
|
20
21
|
# @param invalid toggle
|
|
@@ -24,6 +25,7 @@ module Primer
|
|
|
24
25
|
# @param monospace toggle
|
|
25
26
|
# @param leading_visual_icon octicon
|
|
26
27
|
# @param leading_spinner toggle
|
|
28
|
+
# @param character_limit number
|
|
27
29
|
# @param input_width [Symbol] select [auto, xsmall, small, medium, large, xlarge, xxlarge]
|
|
28
30
|
def playground(
|
|
29
31
|
name: "my-text-field",
|
|
@@ -35,6 +37,7 @@ module Primer
|
|
|
35
37
|
size: Primer::Forms::Dsl::Input::DEFAULT_SIZE.to_s,
|
|
36
38
|
show_clear_button: false,
|
|
37
39
|
clear_button_id: "my-text-field-clear-button",
|
|
40
|
+
clear_button_label: nil,
|
|
38
41
|
full_width: true,
|
|
39
42
|
disabled: false,
|
|
40
43
|
invalid: false,
|
|
@@ -44,6 +47,7 @@ module Primer
|
|
|
44
47
|
monospace: false,
|
|
45
48
|
leading_visual_icon: nil,
|
|
46
49
|
leading_spinner: false,
|
|
50
|
+
character_limit: nil,
|
|
47
51
|
input_width: nil
|
|
48
52
|
)
|
|
49
53
|
system_arguments = {
|
|
@@ -56,6 +60,7 @@ module Primer
|
|
|
56
60
|
size: size,
|
|
57
61
|
show_clear_button: show_clear_button,
|
|
58
62
|
clear_button_id: clear_button_id,
|
|
63
|
+
clear_button_label: clear_button_label,
|
|
59
64
|
full_width: full_width,
|
|
60
65
|
disabled: disabled,
|
|
61
66
|
invalid: invalid,
|
|
@@ -64,6 +69,7 @@ module Primer
|
|
|
64
69
|
inset: inset,
|
|
65
70
|
monospace: monospace,
|
|
66
71
|
leading_spinner: leading_spinner,
|
|
72
|
+
character_limit: character_limit,
|
|
67
73
|
input_width: input_width
|
|
68
74
|
}
|
|
69
75
|
|
|
@@ -133,6 +139,12 @@ module Primer
|
|
|
133
139
|
render(Primer::Alpha::TextField.new(show_clear_button: true, name: "my-text-field-3", label: "My text field"))
|
|
134
140
|
end
|
|
135
141
|
|
|
142
|
+
# @label Show clear button with custom label
|
|
143
|
+
# @snapshot
|
|
144
|
+
def show_clear_button_with_custom_label
|
|
145
|
+
render(Primer::Alpha::TextField.new(show_clear_button: true, clear_button_label: "Effacer", name: "my-text-field-3-custom", label: "Mon champ de texte"))
|
|
146
|
+
end
|
|
147
|
+
|
|
136
148
|
# @label Full width
|
|
137
149
|
# @snapshot
|
|
138
150
|
def full_width
|
|
@@ -216,6 +228,24 @@ module Primer
|
|
|
216
228
|
def with_validation_message
|
|
217
229
|
render(Primer::Alpha::TextField.new(validation_message: "An error occurred!", name: "my-text-field-17", label: "My text field"))
|
|
218
230
|
end
|
|
231
|
+
|
|
232
|
+
# @label With character limit
|
|
233
|
+
# @snapshot interactive
|
|
234
|
+
def with_character_limit
|
|
235
|
+
render(Primer::Alpha::TextField.new(character_limit: 10, name: "my-text-field-18", label: "Username"))
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
# @label With character limit, over limit
|
|
239
|
+
# @snapshot interactive
|
|
240
|
+
def with_character_limit_over_limit
|
|
241
|
+
render(Primer::Alpha::TextField.new(character_limit: 10, name: "my-text-field-19", label: "Tell me about yourself", value: "This text is definitely over the limit."))
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
# @label With character limit and caption
|
|
245
|
+
# @snapshot
|
|
246
|
+
def with_character_limit_and_caption
|
|
247
|
+
render(Primer::Alpha::TextField.new(character_limit: 20, caption: "Choose a unique username.", name: "my-text-field-20", label: "Username"))
|
|
248
|
+
end
|
|
219
249
|
#
|
|
220
250
|
# @!endgroup
|
|
221
251
|
|
|
@@ -223,24 +253,24 @@ module Primer
|
|
|
223
253
|
#
|
|
224
254
|
# @label Auto check request ok
|
|
225
255
|
def with_auto_check_ok
|
|
226
|
-
render(Primer::Alpha::TextField.new(auto_check_src: UrlHelpers.primer_view_components.example_check_ok_path, name: "my-text-field-
|
|
256
|
+
render(Primer::Alpha::TextField.new(auto_check_src: UrlHelpers.primer_view_components.example_check_ok_path, name: "my-text-field-21", label: "My text field"))
|
|
227
257
|
end
|
|
228
258
|
|
|
229
259
|
# @label Auto check request accepted
|
|
230
260
|
def with_auto_check_accepted
|
|
231
|
-
render(Primer::Alpha::TextField.new(auto_check_src: UrlHelpers.primer_view_components.example_check_accepted_path, name: "my-text-field-
|
|
261
|
+
render(Primer::Alpha::TextField.new(auto_check_src: UrlHelpers.primer_view_components.example_check_accepted_path, name: "my-text-field-22", label: "My text field"))
|
|
232
262
|
end
|
|
233
263
|
|
|
234
264
|
# @label Auto check request error
|
|
235
265
|
def with_auto_check_error
|
|
236
|
-
render(Primer::Alpha::TextField.new(auto_check_src: UrlHelpers.primer_view_components.example_check_error_path, name: "my-text-field-
|
|
266
|
+
render(Primer::Alpha::TextField.new(auto_check_src: UrlHelpers.primer_view_components.example_check_error_path, name: "my-text-field-23", label: "My text field"))
|
|
237
267
|
end
|
|
238
268
|
#
|
|
239
269
|
# @!endgroup
|
|
240
270
|
|
|
241
271
|
# @label With data target attribute
|
|
242
272
|
def with_data_target
|
|
243
|
-
render(Primer::Alpha::TextField.new(name: "my-text-field", label: "My text field", data: { target: "custom-component.inputElement" }))
|
|
273
|
+
render(Primer::Alpha::TextField.new(name: "my-text-field-24", label: "My text field", data: { target: "custom-component.inputElement" }))
|
|
244
274
|
end
|
|
245
275
|
#
|
|
246
276
|
# @!endgroup
|
|
@@ -9,67 +9,67 @@ module Primer
|
|
|
9
9
|
include ActionView::Helpers::FormTagHelper
|
|
10
10
|
|
|
11
11
|
def playground
|
|
12
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path))
|
|
12
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, "aria-label": "Toggle Switch"))
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
# @snapshot
|
|
16
16
|
def default
|
|
17
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path))
|
|
17
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, "aria-label": "Default Toggle Switch"))
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
# @snapshot
|
|
21
21
|
def checked
|
|
22
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, checked: true))
|
|
22
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, checked: true, "aria-label": "Checked Toggle Switch"))
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
# @snapshot
|
|
26
26
|
def disabled
|
|
27
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, enabled: false))
|
|
27
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, enabled: false, "aria-label": "Disabled Toggle Switch"))
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
# @snapshot
|
|
31
31
|
def checked_disabled
|
|
32
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, checked: true, enabled: false))
|
|
32
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, checked: true, enabled: false, "aria-label": "Checked Disabled Toggle Switch"))
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
# @snapshot
|
|
36
36
|
def small
|
|
37
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, size: :small))
|
|
37
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, size: :small, "aria-label": "Small Toggle Switch"))
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
# @snapshot
|
|
41
41
|
def with_status_label_position_end
|
|
42
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, status_label_position: :end))
|
|
42
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, status_label_position: :end, "aria-label": "Toggle Switch with Status"))
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
# @snapshot
|
|
46
46
|
def with_a_bad_src
|
|
47
|
-
render(Primer::Alpha::ToggleSwitch.new(src: "/foo"))
|
|
47
|
+
render(Primer::Alpha::ToggleSwitch.new(src: "/foo", "aria-label": "Toggle Switch"))
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def with_no_src
|
|
51
|
-
render(Primer::Alpha::ToggleSwitch.new)
|
|
51
|
+
render(Primer::Alpha::ToggleSwitch.new("aria-label": "Toggle Switch"))
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def with_csrf_token
|
|
55
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path))
|
|
55
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, "aria-label": "Toggle Switch"))
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def with_bad_csrf_token
|
|
59
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, csrf_token: "i_am_a_criminal"))
|
|
59
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, csrf_token: "i_am_a_criminal", "aria-label": "Toggle Switch"))
|
|
60
60
|
end
|
|
61
61
|
|
|
62
62
|
def with_turbo
|
|
63
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, turbo: true))
|
|
63
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, turbo: true, "aria-label": "Toggle Switch"))
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def with_autofocus
|
|
67
|
-
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, autofocus: true))
|
|
67
|
+
render(Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, autofocus: true, "aria-label": "Toggle Switch"))
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
def with_custom_status_label
|
|
72
|
-
render Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, on_label: "Enabled", off_label: "Disabled")
|
|
72
|
+
render Primer::Alpha::ToggleSwitch.new(src: UrlHelpers.primer_view_components.toggle_switch_index_path, on_label: "Enabled", off_label: "Disabled", "aria-label": "Toggle Switch")
|
|
73
73
|
end
|
|
74
74
|
end
|
|
75
75
|
end
|
|
@@ -29,8 +29,60 @@
|
|
|
29
29
|
const includeFragment = subject.querySelector('tree-view-include-fragment')
|
|
30
30
|
if (!includeFragment) return
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
function retryButton() {
|
|
33
|
+
return subject.querySelector("[data-target='tree-view-sub-tree-node.retryButton']")
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function focusTreeItem() {
|
|
37
|
+
const treeItem = subject.querySelector("[role='treeitem']")
|
|
38
|
+
if (treeItem) treeItem.focus()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function makeRetryTabbable() {
|
|
42
|
+
const retry = retryButton()
|
|
43
|
+
if (!retry) return
|
|
44
|
+
// Remove tabindex="-1" so the button can be reached by keyboard.
|
|
45
|
+
retry.removeAttribute('tabindex')
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function addRetryFocusHandler() {
|
|
49
|
+
const retry = retryButton()
|
|
50
|
+
if (!retry) return
|
|
51
|
+
|
|
52
|
+
if (retry.dataset.focusHandlerAttached === "true") return
|
|
53
|
+
retry.dataset.focusHandlerAttached = "true"
|
|
54
|
+
|
|
55
|
+
retry.addEventListener('click', () => {
|
|
56
|
+
focusTreeItem()
|
|
57
|
+
})
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// When the failure UI loads, ensure Retry is tabbable
|
|
61
|
+
includeFragment.addEventListener('loadend', (_event) => {
|
|
62
|
+
makeRetryTabbable()
|
|
63
|
+
addRetryFocusHandler()
|
|
33
64
|
subject.setAttribute('data-ready', 'true')
|
|
34
65
|
})
|
|
66
|
+
|
|
67
|
+
// If include-fragment swaps in new markup on re-render, re-apply tabindex removal.
|
|
68
|
+
includeFragment.addEventListener('include-fragment-replaced', () => {
|
|
69
|
+
makeRetryTabbable()
|
|
70
|
+
addRetryFocusHandler()
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
// If Retry exists and the user presses Tab while focused inside this TreeView,
|
|
74
|
+
// redirect focus to Retry so it is reachable without requiring a mouse click.
|
|
75
|
+
subject.addEventListener('keydown', (event) => {
|
|
76
|
+
if (event.key !== 'Tab' || event.shiftKey) return
|
|
77
|
+
const active = document.activeElement
|
|
78
|
+
if (!(active instanceof HTMLElement)) return
|
|
79
|
+
if (!subject.contains(active)) return
|
|
80
|
+
if (active.getAttribute('role') !== 'treeitem') return
|
|
81
|
+
const retry = retryButton()
|
|
82
|
+
if (!retry) return
|
|
83
|
+
makeRetryTabbable()
|
|
84
|
+
event.preventDefault()
|
|
85
|
+
retry.focus()
|
|
86
|
+
})
|
|
35
87
|
})
|
|
36
88
|
</script>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<div style="max-width: 400px">
|
|
2
|
+
<%= render(Primer::Alpha::TreeView.new) do |tree_view| %>
|
|
3
|
+
<% (1..100).each do %>
|
|
4
|
+
<% tree_view.with_sub_tree(label: "src", expanded: expanded, disabled: disabled, select_variant: select_variant, select_strategy: select_strategy) do |sub_tree| %>
|
|
5
|
+
<% sub_tree.with_leading_visual_icons(label: "Foobar") do |icons| %>
|
|
6
|
+
<% icons.with_expanded_icon(icon: :"file-directory-open-fill", color: :accent) %>
|
|
7
|
+
<% icons.with_collapsed_icon(icon: :"file-directory-fill", color: :accent) %>
|
|
8
|
+
<% end %>
|
|
9
|
+
|
|
10
|
+
<% sub_tree.with_sub_tree(label: "src", expanded: expanded, disabled: disabled, select_variant: select_variant, select_strategy: select_strategy) do |sub_tree2| %>
|
|
11
|
+
<% sub_tree2.with_leading_visual_icons(label: "Foobar") do |icons| %>
|
|
12
|
+
<% icons.with_expanded_icon(icon: :"file-directory-open-fill", color: :accent) %>
|
|
13
|
+
<% icons.with_collapsed_icon(icon: :"file-directory-fill", color: :accent) %>
|
|
14
|
+
<% end %>
|
|
15
|
+
|
|
16
|
+
<% sub_tree2.with_trailing_visual_icon(icon: :"diff-modified") unless select_variant == :single %>
|
|
17
|
+
|
|
18
|
+
<% sub_tree2.with_leaf(label: "button.rb", disabled: disabled, select_variant: select_variant) do |item| %>
|
|
19
|
+
<% item.with_leading_visual_icon(icon: :file) %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
22
|
+
|
|
23
|
+
<% tree_view.with_leaf(label: "action_menu.rb", disabled: disabled, select_variant: select_variant) do |item| %>
|
|
24
|
+
<% item.with_leading_visual_icon(icon: :file) %>
|
|
25
|
+
<% end %>
|
|
26
|
+
|
|
27
|
+
<% sub_tree.with_trailing_visual_icon(icon: :"diff-modified") unless select_variant == :single %>
|
|
28
|
+
|
|
29
|
+
<% sub_tree.with_leaf(label: "button.rb", disabled: disabled, select_variant: select_variant) do |item| %>
|
|
30
|
+
<% item.with_leading_visual_icon(icon: :file) %>
|
|
31
|
+
<% end %>
|
|
32
|
+
|
|
33
|
+
<% sub_tree.with_leaf(label: "icon_button.rb", current: true, disabled: disabled, select_variant: select_variant) do |item| %>
|
|
34
|
+
<% item.with_leading_visual_icon(icon: :file) %>
|
|
35
|
+
<% end %>
|
|
36
|
+
<% end %>
|
|
37
|
+
|
|
38
|
+
<% tree_view.with_leaf(label: "action_menu.rb", disabled: disabled, select_variant: select_variant) do |item| %>
|
|
39
|
+
<% item.with_leading_visual_icon(icon: :file) %>
|
|
40
|
+
<% end %>
|
|
41
|
+
<% end %>
|
|
42
|
+
<% end %>
|
|
43
|
+
</div>
|
|
@@ -1,4 +1,12 @@
|
|
|
1
|
-
<
|
|
1
|
+
<span
|
|
2
|
+
id="button-summary-live"
|
|
3
|
+
class="sr-only"
|
|
4
|
+
role="status"
|
|
5
|
+
aria-live="polite"
|
|
6
|
+
aria-atomic="true"></span>
|
|
7
|
+
|
|
8
|
+
<details
|
|
9
|
+
ontoggle="document.getElementById('button-summary-live').textContent = this.open ? 'A wrapping `details` tag is required when using the button with the `:summary` tag' : ''">
|
|
2
10
|
<%= render(Primer::Beta::Button.new(
|
|
3
11
|
scheme: scheme,
|
|
4
12
|
size: size,
|
|
@@ -9,5 +17,6 @@
|
|
|
9
17
|
)) do %>
|
|
10
18
|
Button
|
|
11
19
|
<% end %>
|
|
20
|
+
|
|
12
21
|
<p>A wrapping `details` tag is required when using the button with the `:summary` tag</p>
|
|
13
22
|
</details>
|
data/static/arguments.json
CHANGED
|
@@ -2721,7 +2721,7 @@
|
|
|
2721
2721
|
"name": "gap",
|
|
2722
2722
|
"type": "Symbol",
|
|
2723
2723
|
"default": "`GapArg::DEFAULT`",
|
|
2724
|
-
"description": "Specify the gap between children elements in the stack. One of `nil`, `:condensed`, `:normal`, or `:spacious`."
|
|
2724
|
+
"description": "Specify the gap between children elements in the stack. One of `nil`, `:condensed`, `:none`, `:normal`, or `:spacious`."
|
|
2725
2725
|
},
|
|
2726
2726
|
{
|
|
2727
2727
|
"name": "direction",
|
|
@@ -2951,6 +2951,12 @@
|
|
|
2951
2951
|
"default": "N/A",
|
|
2952
2952
|
"description": "When set to `true`, the field will take up all the horizontal space allowed by its container. Defaults to `true`."
|
|
2953
2953
|
},
|
|
2954
|
+
{
|
|
2955
|
+
"name": "character_limit",
|
|
2956
|
+
"type": "Number",
|
|
2957
|
+
"default": "N/A",
|
|
2958
|
+
"description": "Optional character limit for the input. If provided, a character counter will be displayed below the input."
|
|
2959
|
+
},
|
|
2954
2960
|
{
|
|
2955
2961
|
"name": "name",
|
|
2956
2962
|
"type": "String",
|
|
@@ -3087,6 +3093,12 @@
|
|
|
3087
3093
|
"default": "N/A",
|
|
3088
3094
|
"description": "When set to `true`, the field will take up all the horizontal space allowed by its container. Defaults to `true`."
|
|
3089
3095
|
},
|
|
3096
|
+
{
|
|
3097
|
+
"name": "character_limit",
|
|
3098
|
+
"type": "Number",
|
|
3099
|
+
"default": "N/A",
|
|
3100
|
+
"description": "Optional character limit for the input. If provided, a character counter will be displayed below the input."
|
|
3101
|
+
},
|
|
3090
3102
|
{
|
|
3091
3103
|
"name": "name",
|
|
3092
3104
|
"type": "String",
|
data/static/form_previews.json
CHANGED
|
@@ -117,6 +117,16 @@
|
|
|
117
117
|
"preview_path": "primer/forms/auto_complete_form",
|
|
118
118
|
"name": "auto_complete_form",
|
|
119
119
|
"snapshot": "true"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"preview_path": "primer/forms/text_area_with_character_limit_form",
|
|
123
|
+
"name": "text_area_with_character_limit_form",
|
|
124
|
+
"snapshot": "true"
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"preview_path": "primer/forms/text_field_with_character_limit_form",
|
|
128
|
+
"name": "text_field_with_character_limit_form",
|
|
129
|
+
"snapshot": "true"
|
|
120
130
|
}
|
|
121
131
|
]
|
|
122
132
|
}
|