primer_view_components 0.49.0 → 0.50.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 +34 -0
- data/README.md +20 -1
- 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/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/controllers/primer/view_components/toggle_switch_controller.rb +2 -2
- data/app/forms/check_box_with_nested_form.rb +9 -5
- data/app/lib/primer/forms/check_box.rb +28 -0
- data/app/lib/primer/forms/dsl/multi_input.rb +3 -1
- data/app/lib/primer/forms/dsl/text_field_input.rb +2 -1
- data/app/lib/primer/forms/form_control.html.erb +2 -1
- data/app/lib/primer/forms/text_field.html.erb +1 -1
- data/lib/primer/accessibility.rb +9 -3
- data/lib/primer/view_components/engine.rb +1 -4
- data/lib/primer/view_components/version.rb +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 +11 -11
- data/previews/primer/alpha/text_field_preview.rb +9 -0
- data/previews/primer/alpha/toggle_switch_preview.rb +14 -14
- 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/static/arguments.json +1 -1
- data/static/info_arch.json +16 -15
- data/static/previews.json +15 -14
- metadata +2 -2
|
@@ -302,7 +302,8 @@ module Primer
|
|
|
302
302
|
if @list.allows_selection?
|
|
303
303
|
@content_arguments[:aria] = merge_aria(
|
|
304
304
|
@content_arguments,
|
|
305
|
-
|
|
305
|
+
# Always use aria-selected for listbox (role="option" requires aria-selected per WAI-ARIA 1.2)
|
|
306
|
+
{ aria: @list.acts_as_listbox? || @list.aria_selection_variant == :selected ? { selected: active? } : { checked: active? } }
|
|
306
307
|
)
|
|
307
308
|
end
|
|
308
309
|
|
|
@@ -256,7 +256,7 @@ module Primer
|
|
|
256
256
|
super(
|
|
257
257
|
p: 2,
|
|
258
258
|
role: "listbox",
|
|
259
|
-
aria_selection_variant:
|
|
259
|
+
aria_selection_variant: :selected,
|
|
260
260
|
select_variant: select_variant == :multiple ? :multiple_checkbox : :single,
|
|
261
261
|
**system_arguments
|
|
262
262
|
)
|
|
@@ -84,7 +84,7 @@ let SelectPanelElement = class SelectPanelElement extends HTMLElement {
|
|
|
84
84
|
return this.getAttribute('data-select-variant');
|
|
85
85
|
}
|
|
86
86
|
get ariaSelectionType() {
|
|
87
|
-
return
|
|
87
|
+
return 'aria-selected';
|
|
88
88
|
}
|
|
89
89
|
set selectVariant(variant) {
|
|
90
90
|
if (variant) {
|
|
@@ -97,7 +97,7 @@ export class SelectPanelElement extends HTMLElement {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
get ariaSelectionType(): string {
|
|
100
|
-
return
|
|
100
|
+
return 'aria-selected'
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
set selectVariant(variant: SelectVariant) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.tabnav{border-bottom:var(--borderWidth-thin) solid var(--borderColor-default);margin-bottom:var(--stack-gap-normal);margin-top:0}.tabnav-tabs{display:flex;margin-bottom:calc(var(--borderWidth-thin)*-1);overflow:hidden}.tabnav-tab{background-color:initial;border:var(--borderWidth-thin) solid #0000;border-bottom:0;color:var(--fgColor-muted);display:inline-block;
|
|
1
|
+
.tabnav{border-bottom:var(--borderWidth-thin) solid var(--borderColor-default);margin-bottom:var(--stack-gap-normal);margin-top:0}.tabnav-tabs{display:flex;margin-bottom:calc(var(--borderWidth-thin)*-1);overflow-x:auto;overflow-y:hidden}.tabnav-tab,.tabnav-tabs>li{flex-shrink:0}.tabnav-tab{background-color:initial;border:var(--borderWidth-thin) solid #0000;border-bottom:0;color:var(--fgColor-muted);display:inline-block;font-size:var(--text-body-size-medium);line-height:23px;padding:var(--base-size-8) var(--control-medium-paddingInline-spacious);-webkit-text-decoration:none;text-decoration:none;transition:color .2s cubic-bezier(.3,0,.5,1)}.tabnav-tab.selected,.tabnav-tab[aria-current]:not([aria-current=false]),.tabnav-tab[aria-selected=true]{background-color:var(--bgColor-default);border-color:var(--borderColor-default);border-radius:var(--borderRadius-medium) var(--borderRadius-medium) 0 0;color:var(--fgColor-default)}:is(.tabnav-tab.selected,.tabnav-tab[aria-selected=true],.tabnav-tab[aria-current]:not([aria-current=false])) .octicon{color:inherit}.tabnav-tab:hover{color:var(--fgColor-default);-webkit-text-decoration:none;text-decoration:none;transition-duration:.1s}.tabnav-tab:focus,.tabnav-tab:focus-visible{border-radius:var(--borderRadius-medium) var(--borderRadius-medium) 0 0!important;outline-offset:-6px}.tabnav-tab .octicon,.tabnav-tab:active{color:var(--fgColor-muted)}.tabnav-tab .octicon{margin-right:var(--control-small-gap)}.tabnav-tab .Counter{color:inherit;margin-left:var(--control-small-gap)}.tabnav-extra{color:var(--fgColor-muted);display:inline-block;font-size:var(--text-body-size-small);margin-left:10px;padding-top:10px}.tabnav-extra>.octicon{margin-right:var(--base-size-2)}a.tabnav-extra:hover{color:var(--fgColor-accent);-webkit-text-decoration:none;text-decoration:none}.tabnav-btn{margin-left:var(--controlStack-medium-gap-condensed)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["tab_nav.pcss"],"names":[],"mappings":"AAGA,QAIE,sEAAuE,CADvE,qCAAsC,CAFtC,YAIF,CAEA,aACE,YAAa,CAEb,8CAAiD,CACjD,
|
|
1
|
+
{"version":3,"sources":["tab_nav.pcss"],"names":[],"mappings":"AAGA,QAIE,sEAAuE,CADvE,qCAAsC,CAFtC,YAIF,CAEA,aACE,YAAa,CAEb,8CAAiD,CACjD,eAAgB,CAChB,iBAMF,CAEA,4BAJI,aA2DJ,CAvDA,YAUE,wBAA6B,CAE7B,0CAAgB,CAAhB,eAAgB,CAJhB,0BAA2B,CAP3B,oBAAqB,CAIrB,sCAAuC,CAEvC,gBAAiB,CAHjB,uEAAwE,CAKxE,4BAAqB,CAArB,oBAAqB,CAIrB,4CA0CF,CAxCE,yGAIE,uCAAwC,CACxC,uCAAwC,CACxC,uEAAwE,CAHxE,4BAQF,CAHE,uHACE,aACF,CAGF,kBACE,4BAA6B,CAC7B,4BAAqB,CAArB,oBAAqB,CACrB,uBACF,CAEA,4CAEE,iFAAmF,CACnF,mBACF,CAMA,wCAHE,0BAOF,CAJA,qBAEE,qCAEF,CAEA,qBAGE,aAAc,CADd,oCAEF,CAQF,cAOE,0BAA2B,CAN3B,oBAAqB,CAKrB,qCAAsC,CADtC,gBAAiB,CAFjB,gBASF,CAHE,uBACE,+BACF,CAKF,qBACE,2BAA4B,CAC5B,4BAAqB,CAArB,oBACF,CAOA,YAEE,oDACF","file":"tab_nav.css","sourcesContent":["/* tabnav */\n\n/* Outer wrapper */\n.tabnav {\n margin-top: 0;\n /* stylelint-disable-next-line primer/spacing */\n margin-bottom: var(--stack-gap-normal);\n border-bottom: var(--borderWidth-thin) solid var(--borderColor-default);\n}\n\n.tabnav-tabs {\n display: flex;\n /* stylelint-disable-next-line primer/spacing */\n margin-bottom: calc(var(--borderWidth-thin) * -1);\n overflow-x: auto;\n overflow-y: hidden;\n\n /* stylelint-disable-next-line selector-max-type */\n & > li {\n flex-shrink: 0;\n }\n}\n\n.tabnav-tab {\n display: inline-block;\n flex-shrink: 0;\n /* stylelint-disable-next-line primer/spacing */\n padding: var(--base-size-8) var(--control-medium-paddingInline-spacious);\n font-size: var(--text-body-size-medium);\n /* stylelint-disable-next-line primer/typography */\n line-height: 23px;\n color: var(--fgColor-muted);\n text-decoration: none;\n background-color: transparent;\n border: var(--borderWidth-thin) solid transparent;\n border-bottom: 0;\n transition: color 0.2s cubic-bezier(0.3, 0, 0.5, 1);\n\n &.selected,\n &[aria-selected='true'],\n &[aria-current]:not([aria-current='false']) {\n color: var(--fgColor-default);\n background-color: var(--bgColor-default); /* cover bottom border */\n border-color: var(--borderColor-default);\n border-radius: var(--borderRadius-medium) var(--borderRadius-medium) 0 0;\n\n & .octicon {\n color: inherit;\n }\n }\n\n &:hover {\n color: var(--fgColor-default);\n text-decoration: none;\n transition-duration: 0.1s;\n }\n\n &:focus,\n &:focus-visible {\n border-radius: var(--borderRadius-medium) var(--borderRadius-medium) 0 0 !important;\n outline-offset: -6px;\n }\n\n &:active {\n color: var(--fgColor-muted);\n }\n\n & .octicon {\n /* stylelint-disable-next-line primer/spacing */\n margin-right: var(--control-small-gap);\n color: var(--fgColor-muted);\n }\n\n & .Counter {\n /* stylelint-disable-next-line primer/spacing */\n margin-left: var(--control-small-gap);\n color: inherit;\n }\n}\n\n/* Tabnav extras\n**\n** Tabnav extras are non-tab elements that sit in the tabnav. Usually they're\n** inline text or links. */\n\n.tabnav-extra {\n display: inline-block;\n /* stylelint-disable-next-line primer/spacing */\n padding-top: 10px;\n /* stylelint-disable-next-line primer/spacing */\n margin-left: 10px;\n font-size: var(--text-body-size-small);\n color: var(--fgColor-muted);\n\n & > .octicon {\n margin-right: var(--base-size-2);\n }\n}\n\n/* When tabnav-extra are anchors */\n/* stylelint-disable-next-line selector-no-qualifying-type, selector-max-type */\na.tabnav-extra:hover {\n color: var(--fgColor-accent);\n text-decoration: none;\n}\n\n/* Tabnav buttons\n**\n** For when there are multiple buttons, space them out appropriately. Requires\n** the buttons to be floated or inline-block. */\n\n.tabnav-btn {\n /* stylelint-disable-next-line primer/spacing */\n margin-left: var(--controlStack-medium-gap-condensed);\n}\n"]}
|
|
@@ -12,7 +12,13 @@
|
|
|
12
12
|
display: flex;
|
|
13
13
|
/* stylelint-disable-next-line primer/spacing */
|
|
14
14
|
margin-bottom: calc(var(--borderWidth-thin) * -1);
|
|
15
|
-
overflow:
|
|
15
|
+
overflow-x: auto;
|
|
16
|
+
overflow-y: hidden;
|
|
17
|
+
|
|
18
|
+
/* stylelint-disable-next-line selector-max-type */
|
|
19
|
+
& > li {
|
|
20
|
+
flex-shrink: 0;
|
|
21
|
+
}
|
|
16
22
|
}
|
|
17
23
|
|
|
18
24
|
.tabnav-tab {
|
|
@@ -9,7 +9,7 @@ module Primer
|
|
|
9
9
|
attr_accessor :last_request
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
rescue_from ActionController::
|
|
12
|
+
rescue_from ActionController::InvalidCrossOriginRequest, with: :handle_invalid_cross_origin_request
|
|
13
13
|
|
|
14
14
|
before_action :reject_non_ajax_request
|
|
15
15
|
|
|
@@ -29,7 +29,7 @@ module Primer
|
|
|
29
29
|
|
|
30
30
|
private
|
|
31
31
|
|
|
32
|
-
def
|
|
32
|
+
def handle_invalid_cross_origin_request
|
|
33
33
|
render status: :unauthorized, plain: "Bad CSRF token."
|
|
34
34
|
end
|
|
35
35
|
|
|
@@ -8,27 +8,31 @@ class CheckBoxWithNestedForm < ApplicationForm
|
|
|
8
8
|
custom_cities_form.text_field(
|
|
9
9
|
name: :custom_cities,
|
|
10
10
|
label: "Custom cities",
|
|
11
|
-
|
|
11
|
+
caption: "A space-separated list of cities"
|
|
12
12
|
)
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
form do |check_form|
|
|
17
|
-
check_form.check_box_group(
|
|
17
|
+
check_form.check_box_group(
|
|
18
|
+
name: :city_categories,
|
|
19
|
+
label: "City categories",
|
|
20
|
+
caption: "Select all that apply."
|
|
21
|
+
) do |check_group|
|
|
18
22
|
check_group.check_box(
|
|
19
23
|
value: "capital",
|
|
20
24
|
label: "Capital",
|
|
21
|
-
|
|
25
|
+
caption: "The capital city"
|
|
22
26
|
)
|
|
23
27
|
check_group.check_box(
|
|
24
28
|
value: "populous",
|
|
25
29
|
label: "Most-populous",
|
|
26
|
-
|
|
30
|
+
caption: "The five most-populous cities"
|
|
27
31
|
)
|
|
28
32
|
check_group.check_box(
|
|
29
33
|
value: "custom",
|
|
30
34
|
label: "Custom",
|
|
31
|
-
|
|
35
|
+
caption: "A custom list of cities"
|
|
32
36
|
) do |custom_check_box|
|
|
33
37
|
custom_check_box.nested_form do |builder|
|
|
34
38
|
CustomCitiesForm.new(builder)
|
|
@@ -11,6 +11,13 @@ module Primer
|
|
|
11
11
|
@input.add_label_classes("FormControl-label")
|
|
12
12
|
@input.add_input_classes("FormControl-checkbox")
|
|
13
13
|
|
|
14
|
+
# Generate custom ID that preserves brackets from the name
|
|
15
|
+
unless @input.input_arguments[:id].present?
|
|
16
|
+
generate_custom_id
|
|
17
|
+
# Update the label's for attribute to match the new ID
|
|
18
|
+
@input.label_arguments[:for] = @input.input_arguments[:id]
|
|
19
|
+
end
|
|
20
|
+
|
|
14
21
|
return unless @input.scheme == :array
|
|
15
22
|
|
|
16
23
|
@input.input_arguments[:multiple] = true
|
|
@@ -32,6 +39,27 @@ module Primer
|
|
|
32
39
|
|
|
33
40
|
private
|
|
34
41
|
|
|
42
|
+
def generate_custom_id
|
|
43
|
+
# Generate an ID from the name that preserves special characters like brackets
|
|
44
|
+
# For array scheme: name + "_" + value (e.g., "permissions[3]_foo")
|
|
45
|
+
# For boolean scheme: just the name (e.g., "long_o")
|
|
46
|
+
base_name = @input.name.to_s
|
|
47
|
+
|
|
48
|
+
# For array scheme, Rails appends [] to the name, so we remove it for ID generation
|
|
49
|
+
# but only the trailing [] that Rails adds, not brackets that are part of the original name
|
|
50
|
+
# Regex /\[\]$/ matches literal "[]" at the end of the string
|
|
51
|
+
base_name = base_name.sub(/\[\]$/, "")
|
|
52
|
+
|
|
53
|
+
# For array scheme, append the value to make IDs unique
|
|
54
|
+
# For boolean scheme, just use the base name
|
|
55
|
+
# Note: Rails automatically escapes HTML attributes, so special characters are safe
|
|
56
|
+
if @input.scheme == :array && @input.value.present?
|
|
57
|
+
@input.input_arguments[:id] = "#{base_name}_#{@input.value}"
|
|
58
|
+
else
|
|
59
|
+
@input.input_arguments[:id] = base_name
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
35
63
|
def checked_value
|
|
36
64
|
@input.value || "1"
|
|
37
65
|
end
|
|
@@ -39,7 +39,9 @@ module Primer
|
|
|
39
39
|
new_options[:data] ||= {}
|
|
40
40
|
new_options[:data][:name] = name
|
|
41
41
|
new_options[:data][:targets] = "primer-multi-input.fields"
|
|
42
|
-
new_options[:id] =
|
|
42
|
+
new_options[:id] = "#{@name}_#{name}"
|
|
43
|
+
new_options[:aria] ||= {}
|
|
44
|
+
new_options[:aria][:labelledby] = "label-#{base_id}"
|
|
43
45
|
new_options[:disabled] = true if options[:hidden] # disable to avoid submitting to server
|
|
44
46
|
new_options
|
|
45
47
|
end
|
|
@@ -6,7 +6,7 @@ module Primer
|
|
|
6
6
|
attr_reader(
|
|
7
7
|
*%i[
|
|
8
8
|
name label show_clear_button leading_visual leading_spinner trailing_visual clear_button_id
|
|
9
|
-
visually_hide_label inset monospace field_wrap_classes auto_check_src character_limit
|
|
9
|
+
clear_button_label visually_hide_label inset monospace field_wrap_classes auto_check_src character_limit
|
|
10
10
|
]
|
|
11
11
|
)
|
|
12
12
|
|
|
@@ -21,6 +21,7 @@ module Primer
|
|
|
21
21
|
@trailing_visual = system_arguments.delete(:trailing_visual)
|
|
22
22
|
@leading_spinner = !!system_arguments.delete(:leading_spinner)
|
|
23
23
|
@clear_button_id = system_arguments.delete(:clear_button_id) || SecureRandom.uuid
|
|
24
|
+
@clear_button_label = system_arguments.delete(:clear_button_label)
|
|
24
25
|
@inset = system_arguments.delete(:inset)
|
|
25
26
|
@monospace = system_arguments.delete(:monospace)
|
|
26
27
|
@auto_check_src = system_arguments.delete(:auto_check_src)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
<% if @input.form_control? %>
|
|
2
2
|
<%= content_tag(@tag, **@form_group_arguments) do %>
|
|
3
3
|
<% if @input.label %>
|
|
4
|
-
|
|
4
|
+
<% label_id = @input.label_arguments[:id] || "label-#{@input.base_id}" %>
|
|
5
|
+
<%= builder.label(@input.name, **@input.label_arguments.merge(id: label_id)) do %>
|
|
5
6
|
<%= @input.label %>
|
|
6
7
|
<% if @input.required? %>
|
|
7
8
|
<span aria-hidden="true">*</span>
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<%= builder.text_field(@input.name, **@input.input_arguments) %>
|
|
14
14
|
<% end %>
|
|
15
15
|
<% if @input.show_clear_button? %>
|
|
16
|
-
<button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="Clear" data-action="click:primer-text-field#clearContents">
|
|
16
|
+
<button type="button" id="<%= @input.clear_button_id %>" class="FormControl-input-trailingAction" aria-label="<%= @input.clear_button_label || 'Clear' %>" data-action="click:primer-text-field#clearContents">
|
|
17
17
|
<%= render(Primer::Beta::Octicon.new(icon: :"x-circle-fill")) %>
|
|
18
18
|
</button>
|
|
19
19
|
<% end %>
|
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
|
|
@@ -50,7 +50,7 @@ module Primer
|
|
|
50
50
|
# @label Default
|
|
51
51
|
# @snapshot
|
|
52
52
|
def default
|
|
53
|
-
render(Primer::Alpha::TextArea.new(name: "my-text-area", label: "Tell me about yourself"))
|
|
53
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-default", name: "my-text-area-default", label: "Tell me about yourself"))
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# @!group Options
|
|
@@ -58,61 +58,61 @@ module Primer
|
|
|
58
58
|
# @label With caption
|
|
59
59
|
# @snapshot
|
|
60
60
|
def with_caption
|
|
61
|
-
render(Primer::Alpha::TextArea.new(
|
|
61
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-caption", name: "my-text-area-with-caption", caption: "With a caption", label: "Tell me about yourself"))
|
|
62
62
|
end
|
|
63
63
|
|
|
64
64
|
# @label Visually hidden label
|
|
65
65
|
# @snapshot
|
|
66
66
|
def visually_hide_label
|
|
67
|
-
render(Primer::Alpha::TextArea.new(
|
|
67
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-visually-hide-label", name: "my-text-area-visually-hide-label", visually_hide_label: true, label: "Tell me about yourself"))
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
# @label Full width
|
|
71
71
|
# @snapshot
|
|
72
72
|
def full_width
|
|
73
|
-
render(Primer::Alpha::TextArea.new(
|
|
73
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-full-width", name: "my-text-area-full-width", full_width: true, label: "Tell me about yourself"))
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
# @label Not full width
|
|
77
77
|
# @snapshot
|
|
78
78
|
def not_full_width
|
|
79
|
-
render(Primer::Alpha::TextArea.new(
|
|
79
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-not-full-width", name: "my-text-area-not-full-width", full_width: false, label: "Tell me about yourself"))
|
|
80
80
|
end
|
|
81
81
|
|
|
82
82
|
# @label Disabled
|
|
83
83
|
# @snapshot
|
|
84
84
|
def disabled
|
|
85
|
-
render(Primer::Alpha::TextArea.new(
|
|
85
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-disabled", name: "my-text-area-disabled", disabled: true, label: "Tell me about yourself"))
|
|
86
86
|
end
|
|
87
87
|
|
|
88
88
|
# @label Invalid
|
|
89
89
|
# @snapshot
|
|
90
90
|
def invalid
|
|
91
|
-
render(Primer::Alpha::TextArea.new(
|
|
91
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-invalid", name: "my-text-area-invalid", invalid: true, label: "Tell me about yourself"))
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
# @label With validation message
|
|
95
95
|
# @snapshot
|
|
96
96
|
def with_validation_message
|
|
97
|
-
render(Primer::Alpha::TextArea.new(
|
|
97
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-validation-message", name: "my-text-area-with-validation-message", validation_message: "An error occurred!", label: "Tell me about yourself"))
|
|
98
98
|
end
|
|
99
99
|
|
|
100
100
|
# @label With character limit
|
|
101
101
|
# @snapshot interactive
|
|
102
102
|
def with_character_limit
|
|
103
|
-
render(Primer::Alpha::TextArea.new(
|
|
103
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit", name: "my-text-area-with-character-limit", character_limit: 10, label: "Tell me about yourself"))
|
|
104
104
|
end
|
|
105
105
|
|
|
106
106
|
# @label With character limit, over limit
|
|
107
107
|
# @snapshot interactive
|
|
108
108
|
def with_character_limit_over_limit
|
|
109
|
-
render(Primer::Alpha::TextArea.new(
|
|
109
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit-over-limit", name: "my-text-area-with-character-limit-over-limit", character_limit: 10, label: "Tell me about yourself", value: "This text is definitely over the limit."))
|
|
110
110
|
end
|
|
111
111
|
|
|
112
112
|
# @label With character limit and caption
|
|
113
113
|
# @snapshot
|
|
114
114
|
def with_character_limit_and_caption
|
|
115
|
-
render(Primer::Alpha::TextArea.new(character_limit: 100, caption: "With a caption.",
|
|
115
|
+
render(Primer::Alpha::TextArea.new(id: "my-text-area-with-character-limit-and-caption", name: "my-text-area-with-character-limit-and-caption", character_limit: 100, caption: "With a caption.", label: "Tell me about yourself"))
|
|
116
116
|
end
|
|
117
117
|
#
|
|
118
118
|
# @!endgroup
|
|
@@ -15,6 +15,7 @@ module Primer
|
|
|
15
15
|
# @param size [Symbol] select [small, medium, large]
|
|
16
16
|
# @param show_clear_button toggle
|
|
17
17
|
# @param clear_button_id text
|
|
18
|
+
# @param clear_button_label text
|
|
18
19
|
# @param full_width toggle
|
|
19
20
|
# @param disabled toggle
|
|
20
21
|
# @param invalid toggle
|
|
@@ -35,6 +36,7 @@ module Primer
|
|
|
35
36
|
size: Primer::Forms::Dsl::Input::DEFAULT_SIZE.to_s,
|
|
36
37
|
show_clear_button: false,
|
|
37
38
|
clear_button_id: "my-text-field-clear-button",
|
|
39
|
+
clear_button_label: nil,
|
|
38
40
|
full_width: true,
|
|
39
41
|
disabled: false,
|
|
40
42
|
invalid: false,
|
|
@@ -56,6 +58,7 @@ module Primer
|
|
|
56
58
|
size: size,
|
|
57
59
|
show_clear_button: show_clear_button,
|
|
58
60
|
clear_button_id: clear_button_id,
|
|
61
|
+
clear_button_label: clear_button_label,
|
|
59
62
|
full_width: full_width,
|
|
60
63
|
disabled: disabled,
|
|
61
64
|
invalid: invalid,
|
|
@@ -133,6 +136,12 @@ module Primer
|
|
|
133
136
|
render(Primer::Alpha::TextField.new(show_clear_button: true, name: "my-text-field-3", label: "My text field"))
|
|
134
137
|
end
|
|
135
138
|
|
|
139
|
+
# @label Show clear button with custom label
|
|
140
|
+
# @snapshot
|
|
141
|
+
def show_clear_button_with_custom_label
|
|
142
|
+
render(Primer::Alpha::TextField.new(show_clear_button: true, clear_button_label: "Effacer", name: "my-text-field-3-custom", label: "Mon champ de texte"))
|
|
143
|
+
end
|
|
144
|
+
|
|
136
145
|
# @label Full width
|
|
137
146
|
# @snapshot
|
|
138
147
|
def full_width
|
|
@@ -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
|
|
@@ -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
|
@@ -2616,7 +2616,7 @@
|
|
|
2616
2616
|
"name": "gap",
|
|
2617
2617
|
"type": "Symbol",
|
|
2618
2618
|
"default": "`GapArg::DEFAULT`",
|
|
2619
|
-
"description": "Specify the gap between children elements in the stack. One of `nil`, `:condensed`, `:normal`, or `:spacious`."
|
|
2619
|
+
"description": "Specify the gap between children elements in the stack. One of `nil`, `:condensed`, `:none`, `:normal`, or `:spacious`."
|
|
2620
2620
|
},
|
|
2621
2621
|
{
|
|
2622
2622
|
"name": "direction",
|