primer_view_components 0.1.0 → 0.1.2
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 +40 -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/divider.rb +2 -2
- data/app/components/primer/alpha/action_list/heading.html.erb +1 -1
- data/app/components/primer/alpha/action_list/heading.rb +11 -5
- data/app/components/primer/alpha/action_list/item.rb +19 -15
- data/app/components/primer/alpha/action_list.html.erb +7 -8
- data/app/components/primer/alpha/action_list.rb +16 -11
- data/app/components/primer/alpha/nav_list/{section.rb → group.rb} +5 -5
- data/app/components/primer/alpha/nav_list/item.html.erb +1 -1
- data/app/components/primer/alpha/nav_list/item.rb +15 -1
- data/app/components/primer/alpha/nav_list.d.ts +1 -0
- data/app/components/primer/alpha/nav_list.html.erb +8 -8
- data/app/components/primer/alpha/nav_list.js +21 -0
- data/app/components/primer/alpha/nav_list.rb +30 -34
- data/app/components/primer/alpha/nav_list.ts +23 -0
- data/app/components/primer/alpha/navigation/tab.rb +168 -0
- data/app/components/primer/alpha/overlay/header.html.erb +2 -2
- data/app/components/primer/alpha/overlay.rb +29 -9
- data/app/components/primer/alpha/tab_nav.rb +10 -3
- data/app/components/primer/alpha/tab_panels.rb +2 -2
- data/app/components/primer/alpha/underline_nav.css +1 -1
- data/app/components/primer/alpha/underline_nav.css.map +1 -1
- data/app/components/primer/alpha/underline_nav.pcss +1 -0
- data/app/components/primer/alpha/underline_nav.rb +2 -2
- data/app/components/primer/alpha/underline_panels.rb +2 -2
- data/app/components/primer/beta/button.html.erb +1 -1
- data/app/components/primer/beta/button.rb +2 -1
- data/app/components/primer/component.rb +34 -0
- data/app/components/primer/navigation/tab_component.rb +3 -157
- data/app/components/primer/truncate.rb +1 -1
- data/lib/primer/deprecations.yml +9 -0
- data/lib/primer/forms/dsl/text_field_input.rb +1 -1
- data/lib/primer/forms/primer_text_field.js +17 -6
- data/lib/primer/forms/primer_text_field.ts +15 -7
- data/lib/primer/forms/text_field.html.erb +3 -3
- data/lib/primer/view_components/version.rb +1 -1
- data/lib/primer/yard/component_manifest.rb +2 -1
- data/lib/tasks/docs.rake +1 -1
- data/previews/primer/alpha/action_list_preview.rb +41 -29
- data/previews/primer/alpha/nav_list_preview/trailing_action.html.erb +19 -0
- data/previews/primer/alpha/nav_list_preview.rb +19 -30
- data/previews/primer/alpha/overlay_preview.rb +34 -4
- data/previews/primer/alpha/tab_nav_preview/with_extra.html.erb +8 -0
- data/previews/primer/alpha/tab_nav_preview.rb +5 -0
- data/previews/primer/alpha/tab_panels_preview/with_extra.html.erb +17 -0
- data/previews/primer/alpha/tab_panels_preview.rb +5 -0
- data/static/arguments.json +64 -8
- data/static/audited_at.json +2 -1
- data/static/constants.json +20 -8
- data/static/previews.json +20 -5
- data/static/statuses.json +4 -3
- metadata +10 -8
- data/app/components/primer/alpha/nav_list/section.html.erb +0 -3
- data/previews/primer/alpha/action_list_preview/heading.html.erb +0 -4
- /data/app/components/primer/{navigation/tab_component.html.erb → alpha/navigation/tab.html.erb} +0 -0
@@ -3,7 +3,7 @@
|
|
3
3
|
module Primer
|
4
4
|
module Alpha
|
5
5
|
class ActionList
|
6
|
-
#
|
6
|
+
# Group heading rendered above the group contents.
|
7
7
|
class Divider < Primer::Component
|
8
8
|
DEFAULT_SCHEME = :subtle
|
9
9
|
SCHEME_MAPPINGS = {
|
@@ -17,7 +17,7 @@ module Primer
|
|
17
17
|
def initialize(scheme: DEFAULT_SCHEME, **system_arguments)
|
18
18
|
@system_arguments = system_arguments
|
19
19
|
@system_arguments[:tag] = :li
|
20
|
-
@system_arguments[:role] = :
|
20
|
+
@system_arguments[:role] = :presentation
|
21
21
|
@system_arguments[:'aria-hidden'] = true
|
22
22
|
@scheme = fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)
|
23
23
|
@system_arguments[:classes] = class_names(
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<%= render(Primer::BaseComponent.new(**@system_arguments)) do %>
|
1
|
+
<%= render(Primer::BaseComponent.new(tag: :div, **@system_arguments)) do %>
|
2
2
|
<%= render(Primer::BaseComponent.new(tag: @tag, classes: "ActionList-sectionDivider-title", id: @list_id)) do %>
|
3
3
|
<%= @title %>
|
4
4
|
<% end %>
|
@@ -11,21 +11,27 @@ module Primer
|
|
11
11
|
:filled => "ActionList-sectionDivider--filled"
|
12
12
|
}.freeze
|
13
13
|
SCHEME_OPTIONS = SCHEME_MAPPINGS.keys.freeze
|
14
|
+
HEADING_MIN = 1
|
15
|
+
HEADING_MAX = 6
|
16
|
+
HEADING_LEVELS = (HEADING_MIN..HEADING_MAX).to_a.freeze
|
14
17
|
|
15
18
|
# @param list_id [String] The unique identifier of the sub list the heading belongs to. Used internally.
|
16
19
|
# @param title [String] Sub list title.
|
20
|
+
# @param heading_level [Integer] Heading level. Level 2 results in an `<h2>` tag, level 3 an `<h3>` tag, etc.
|
17
21
|
# @param subtitle [String] Optional sub list description.
|
18
22
|
# @param scheme [Symbol] Display a background color if scheme is `filled`.
|
19
|
-
# @param tag [
|
23
|
+
# @param tag [Integer] Semantic tag for the heading.
|
20
24
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
21
|
-
def initialize(list_id:, title:,
|
22
|
-
|
23
|
-
|
25
|
+
def initialize(list_id:, title:, heading_level: 3, scheme: DEFAULT_SCHEME, subtitle: nil, **system_arguments)
|
26
|
+
raise "Heading level must be between #{HEADING_MIN} and #{HEADING_MAX}" unless HEADING_LEVELS.include?(heading_level)
|
27
|
+
|
28
|
+
@heading_level = heading_level
|
29
|
+
@tag = :"h#{heading_level}"
|
30
|
+
@system_arguments = deny_tag_argument(**system_arguments)
|
24
31
|
@list_id = list_id
|
25
32
|
@title = title
|
26
33
|
@subtitle = subtitle
|
27
34
|
@scheme = fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)
|
28
|
-
@system_arguments[:tag] = :li
|
29
35
|
@system_arguments[:classes] = class_names(
|
30
36
|
"ActionList-sectionDivider",
|
31
37
|
SCHEME_MAPPINGS[@scheme],
|
@@ -84,12 +84,16 @@ module Primer
|
|
84
84
|
# A button rendered after the trailing icon that can be used to show a menu, activate
|
85
85
|
# a dialog, etc.
|
86
86
|
#
|
87
|
-
# @param show_on_hover [Boolean] Whether or not to show the button when the list item is hovered. If `true`, the button will be invisible until hovered. If `false`, the button will always be visible. Defaults to `false`.
|
88
87
|
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::IconButton) %>.
|
89
|
-
renders_one :trailing_action, lambda {
|
90
|
-
|
88
|
+
renders_one :trailing_action, lambda { |**system_arguments|
|
89
|
+
Primer::Beta::IconButton.new(
|
90
|
+
classes: class_names(
|
91
|
+
system_arguments[:classes],
|
92
|
+
"ActionListItem-trailingAction"
|
93
|
+
),
|
91
94
|
|
92
|
-
|
95
|
+
**system_arguments
|
96
|
+
)
|
93
97
|
}
|
94
98
|
|
95
99
|
# `Tooltip` that appears on mouse hover or keyboard focus over the trailing action button. Use tooltips sparingly and as
|
@@ -112,7 +116,7 @@ module Primer
|
|
112
116
|
# @private
|
113
117
|
renders_one :private_content
|
114
118
|
|
115
|
-
attr_reader :list, :href, :active, :disabled, :parent
|
119
|
+
attr_reader :id, :list, :href, :active, :disabled, :parent
|
116
120
|
|
117
121
|
# Whether or not this item is active.
|
118
122
|
#
|
@@ -150,7 +154,7 @@ module Primer
|
|
150
154
|
parent: nil,
|
151
155
|
truncate_label: false,
|
152
156
|
href: nil,
|
153
|
-
role:
|
157
|
+
role: nil,
|
154
158
|
size: DEFAULT_SIZE,
|
155
159
|
scheme: DEFAULT_SCHEME,
|
156
160
|
disabled: false,
|
@@ -167,7 +171,6 @@ module Primer
|
|
167
171
|
@truncate_label = truncate_label
|
168
172
|
@disabled = disabled
|
169
173
|
@active = active
|
170
|
-
@trailing_action_on_hover = false
|
171
174
|
@id = id
|
172
175
|
@system_arguments = system_arguments
|
173
176
|
@content_arguments = content_arguments
|
@@ -184,7 +187,7 @@ module Primer
|
|
184
187
|
"ActionListItem"
|
185
188
|
)
|
186
189
|
|
187
|
-
@system_arguments[:role] = role
|
190
|
+
@system_arguments[:role] = role if role
|
188
191
|
|
189
192
|
@system_arguments[:aria] ||= {}
|
190
193
|
@system_arguments[:aria][:disabled] = "true" if @disabled
|
@@ -209,12 +212,14 @@ module Primer
|
|
209
212
|
SIZE_MAPPINGS[@size]
|
210
213
|
)
|
211
214
|
|
212
|
-
|
213
|
-
@
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
215
|
+
unless @content_arguments[:tag]
|
216
|
+
if @href && !@disabled
|
217
|
+
@content_arguments[:tag] = :a
|
218
|
+
@content_arguments[:href] = @href
|
219
|
+
else
|
220
|
+
@content_arguments[:tag] = :button
|
221
|
+
@content_arguments[:onclick] = on_click if on_click
|
222
|
+
end
|
218
223
|
end
|
219
224
|
|
220
225
|
@description_wrapper_arguments = {
|
@@ -231,7 +236,6 @@ module Primer
|
|
231
236
|
@system_arguments[:classes] = class_names(
|
232
237
|
@system_arguments[:classes],
|
233
238
|
"ActionListItem--withActions" => trailing_action.present?,
|
234
|
-
"ActionListItem--trailingActionHover" => @trailing_action_on_hover,
|
235
239
|
"ActionListItem--navActive" => active?
|
236
240
|
)
|
237
241
|
|
@@ -1,15 +1,14 @@
|
|
1
|
-
<%= render(Primer::BaseComponent.new(tag: :
|
1
|
+
<%= render(Primer::BaseComponent.new(tag: :div)) do %>
|
2
2
|
<% if heading %>
|
3
3
|
<%= heading %>
|
4
4
|
<% end %>
|
5
|
-
<%= render(Primer::BaseComponent.new(tag: :
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
<% end %>
|
11
|
-
<%= item %>
|
5
|
+
<%= render(Primer::BaseComponent.new(tag: :ul, **@system_arguments)) do %>
|
6
|
+
<% items.each_with_index do |item, index| %>
|
7
|
+
<%# the conditions here make sure two dividers are never rendered one after the other %>
|
8
|
+
<% if index > 0 && @show_dividers && !item.is_a?(Divider) && !items[index - 1].is_a?(Divider) %>
|
9
|
+
<%= render(Primer::Alpha::ActionList::Divider.new) %>
|
12
10
|
<% end %>
|
11
|
+
<%= item %>
|
13
12
|
<% end %>
|
14
13
|
<% end %>
|
15
14
|
<% end %>
|
@@ -48,6 +48,15 @@ module Primer
|
|
48
48
|
end
|
49
49
|
}
|
50
50
|
|
51
|
+
# Adds a divider to the list of items.
|
52
|
+
#
|
53
|
+
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::ActionList::Divider) %>.
|
54
|
+
def with_divider(**system_arguments, &block)
|
55
|
+
# This is a giant hack that should be removed when :items can be converted into a polymorphic slot.
|
56
|
+
# This feature needs to land in view_component first: https://github.com/ViewComponent/view_component/pull/1652
|
57
|
+
set_slot(:items, { renderable: Divider, collection: true }, **system_arguments, &block)
|
58
|
+
end
|
59
|
+
|
51
60
|
# @param role [Boolean] ARIA role describing the function of the list. listbox and menu are a common values.
|
52
61
|
# @param item_classes [String] Additional CSS classes to attach to items.
|
53
62
|
# @param scheme [Symbol] <%= one_of(Primer::Alpha::ActionList::SCHEME_OPTIONS) %>. `inset` children are offset (vertically and horizontally) from list edges. `full` (default) children are flush (vertically and horizontally) with list edges.
|
@@ -61,10 +70,10 @@ module Primer
|
|
61
70
|
**system_arguments
|
62
71
|
)
|
63
72
|
@id = self.class.generate_id
|
64
|
-
@role = role
|
65
73
|
|
66
74
|
@system_arguments = system_arguments
|
67
75
|
@system_arguments[:tag] = :ul
|
76
|
+
@system_arguments[:role] = role
|
68
77
|
@item_classes = item_classes
|
69
78
|
@scheme = fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)
|
70
79
|
@show_dividers = show_dividers
|
@@ -72,7 +81,6 @@ module Primer
|
|
72
81
|
SCHEME_MAPPINGS[@scheme],
|
73
82
|
system_arguments[:classes],
|
74
83
|
"ActionListWrap",
|
75
|
-
"ActionListWrap--subGroup",
|
76
84
|
"ActionListWrap--divided" => @show_dividers
|
77
85
|
)
|
78
86
|
|
@@ -81,18 +89,15 @@ module Primer
|
|
81
89
|
|
82
90
|
# @private
|
83
91
|
def before_render
|
92
|
+
aria_label = aria(:label, @system_arguments)
|
93
|
+
aria_labelledby = aria(:labelledby, @system_arguments)
|
94
|
+
|
84
95
|
if heading.present?
|
85
96
|
@system_arguments[:"aria-labelledby"] = @id
|
86
|
-
|
87
|
-
|
97
|
+
raise ArgumentError, "An aria-label should not be provided if a heading is present" if aria_label.present?
|
98
|
+
elsif aria_label.blank? && aria_labelledby.blank?
|
99
|
+
raise ArgumentError, "An aria-label, aria-labelledby, or heading must be provided"
|
88
100
|
end
|
89
|
-
|
90
|
-
return if items.blank?
|
91
|
-
|
92
|
-
@list_wrapper_arguments[:classes] = class_names(
|
93
|
-
@list_wrapper_arguments[:classes],
|
94
|
-
"ActionListItem--hasSubItem"
|
95
|
-
)
|
96
101
|
end
|
97
102
|
|
98
103
|
# @private
|
@@ -6,10 +6,10 @@ module Primer
|
|
6
6
|
# A logical grouping of navigation links with an optional heading.
|
7
7
|
#
|
8
8
|
# See <%= link_to_component(Primer::Alpha::NavList) %> for usage examples.
|
9
|
-
class
|
10
|
-
# A special "show more" list item that appears at the bottom of the
|
9
|
+
class Group < ActionList
|
10
|
+
# A special "show more" list item that appears at the bottom of the group. Clicking
|
11
11
|
# the item will fetch the next page of results from the URL passed in the `src` argument
|
12
|
-
# and append the resulting chunk of HTML to the
|
12
|
+
# and append the resulting chunk of HTML to the group.
|
13
13
|
#
|
14
14
|
# @param src [String] The URL to query for additional pages of list items.
|
15
15
|
# @param pages [Integer] The total number of pages in the result set.
|
@@ -51,14 +51,14 @@ module Primer
|
|
51
51
|
super(**@system_arguments)
|
52
52
|
end
|
53
53
|
|
54
|
-
# Cause this
|
54
|
+
# Cause this group to show its list of sub items when rendered.
|
55
55
|
# :nocov:
|
56
56
|
def expand!
|
57
57
|
@expanded = true
|
58
58
|
end
|
59
59
|
# :nocov:
|
60
60
|
|
61
|
-
# The items contained within this
|
61
|
+
# The items contained within this group.
|
62
62
|
#
|
63
63
|
# @return [Array<Primer::Alpha::ActionList::Item>]
|
64
64
|
def items
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% with_private_content do %>
|
2
2
|
<% unless items.empty? %>
|
3
3
|
<% capture do %>
|
4
|
-
<%= render(Primer::BaseComponent.new(tag: :ul, **@sub_list_arguments)) do %>
|
4
|
+
<%= render(Primer::BaseComponent.new(tag: :ul, role: :list, **@sub_list_arguments)) do %>
|
5
5
|
<% items.each do |item| %>
|
6
6
|
<%= item %>
|
7
7
|
<% end %>
|
@@ -47,6 +47,10 @@ module Primer
|
|
47
47
|
)
|
48
48
|
}
|
49
49
|
|
50
|
+
@list = system_arguments[:list]
|
51
|
+
|
52
|
+
@sub_list_arguments["data-action"] = "keydown:#{@list.custom_element_name}#handleItemWithSubItemKeydown" if @list
|
53
|
+
|
50
54
|
overrides = { "data-item-id": @selected_by_ids.join(" ") }
|
51
55
|
|
52
56
|
super(**system_arguments, **overrides)
|
@@ -79,9 +83,19 @@ module Primer
|
|
79
83
|
|
80
84
|
return if items.blank?
|
81
85
|
|
86
|
+
@sub_list_arguments[:aria] = merge_aria(
|
87
|
+
@sub_list_arguments,
|
88
|
+
{ aria: { labelledby: id } }
|
89
|
+
)
|
90
|
+
|
91
|
+
raise ArgumentError, "Items with sub-items cannot have hrefs" if href.present?
|
92
|
+
|
82
93
|
@content_arguments[:tag] = :button
|
83
94
|
@content_arguments[:"aria-expanded"] = @expanded.to_s
|
84
|
-
@content_arguments[:"data-action"] = "
|
95
|
+
@content_arguments[:"data-action"] = "
|
96
|
+
click:#{@list.custom_element_name}#handleItemWithSubItemClick
|
97
|
+
keydown:#{@list.custom_element_name}#handleItemWithSubItemKeydown
|
98
|
+
"
|
85
99
|
|
86
100
|
with_private_trailing_action_icon(:"chevron-down", classes: "ActionListItem-collapseIcon")
|
87
101
|
|
@@ -18,6 +18,7 @@ export declare class NavListElement extends HTMLElement {
|
|
18
18
|
collapseItem(item: HTMLElement): void;
|
19
19
|
itemIsExpanded(item: HTMLElement | null): boolean;
|
20
20
|
handleItemWithSubItemClick(e: Event): void;
|
21
|
+
handleItemWithSubItemKeydown(e: KeyboardEvent): void;
|
21
22
|
private showMore;
|
22
23
|
private setShowMoreItemState;
|
23
24
|
}
|
@@ -1,10 +1,10 @@
|
|
1
|
-
<%= render(Primer::BaseComponent.new(tag: :
|
2
|
-
|
3
|
-
<%
|
4
|
-
|
1
|
+
<%= render(Primer::BaseComponent.new(tag: :nav, **@system_arguments)) do %>
|
2
|
+
<nav-list>
|
3
|
+
<% groups.each_with_index do |group, index| %>
|
4
|
+
<% if index > 0 %>
|
5
|
+
<%= render(Primer::Alpha::ActionList::Divider.new) %>
|
6
|
+
<% end %>
|
7
|
+
<%= group %>
|
5
8
|
<% end %>
|
6
|
-
|
7
|
-
<%= section %>
|
8
|
-
</li>
|
9
|
-
<% end %>
|
9
|
+
</nav-list>
|
10
10
|
<% end %>
|
@@ -82,6 +82,7 @@ let NavListElement = class NavListElement extends HTMLElement {
|
|
82
82
|
var _a;
|
83
83
|
(_a = item.nextElementSibling) === null || _a === void 0 ? void 0 : _a.setAttribute('data-hidden', '');
|
84
84
|
item.setAttribute('aria-expanded', 'false');
|
85
|
+
item.focus();
|
85
86
|
}
|
86
87
|
itemIsExpanded(item) {
|
87
88
|
if ((item === null || item === void 0 ? void 0 : item.tagName) === 'A') {
|
@@ -105,6 +106,26 @@ let NavListElement = class NavListElement extends HTMLElement {
|
|
105
106
|
}
|
106
107
|
e.stopPropagation();
|
107
108
|
}
|
109
|
+
// collapse item
|
110
|
+
handleItemWithSubItemKeydown(e) {
|
111
|
+
const el = e.currentTarget;
|
112
|
+
if (!(el instanceof HTMLElement))
|
113
|
+
return;
|
114
|
+
let button = el.closest('button');
|
115
|
+
if (!button) {
|
116
|
+
const button_id = el.getAttribute('aria-labelledby');
|
117
|
+
if (button_id) {
|
118
|
+
button = document.getElementById(button_id);
|
119
|
+
}
|
120
|
+
else {
|
121
|
+
return;
|
122
|
+
}
|
123
|
+
}
|
124
|
+
if (this.itemIsExpanded(button) && e.key === 'Escape') {
|
125
|
+
this.collapseItem(button);
|
126
|
+
}
|
127
|
+
e.stopPropagation();
|
128
|
+
}
|
108
129
|
async showMore(e) {
|
109
130
|
var _a, _b;
|
110
131
|
e.preventDefault();
|
@@ -3,13 +3,13 @@
|
|
3
3
|
module Primer
|
4
4
|
module Alpha
|
5
5
|
# `NavList` provides a simple way to render side navigation, i.e. navigation
|
6
|
-
# that appears to the left or right side of some main content. Each
|
6
|
+
# that appears to the left or right side of some main content. Each group in a
|
7
7
|
# nav list is a list of links.
|
8
8
|
#
|
9
|
-
# Nav list
|
9
|
+
# Nav list groups can contain sub items. Rather than navigating to a URL, groups
|
10
10
|
# with sub items expand and collapse on click. To indicate this functionality, the
|
11
|
-
#
|
12
|
-
# when the
|
11
|
+
# group will automatically render with a trailing chevron icon that changes direction
|
12
|
+
# when the group expands and collapses.
|
13
13
|
#
|
14
14
|
# Nav list items appear visually active when selected. Each nav item must have one
|
15
15
|
# or more ID values that determine which item will appear selected. Use the
|
@@ -22,40 +22,40 @@ module Primer
|
|
22
22
|
"nav-list"
|
23
23
|
end
|
24
24
|
|
25
|
-
#
|
25
|
+
# Groups. Each group is a list of links and an optional heading.
|
26
26
|
#
|
27
|
-
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::
|
28
|
-
renders_many :
|
29
|
-
Primer::Alpha::NavList::
|
27
|
+
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Group) %>.
|
28
|
+
renders_many :groups, lambda { |**system_arguments|
|
29
|
+
Primer::Alpha::NavList::Group.new(selected_item_id: @selected_item_id, **system_arguments)
|
30
30
|
}
|
31
31
|
|
32
32
|
# @example Items and headings
|
33
33
|
#
|
34
34
|
# <%= render(Primer::Alpha::NavList.new(selected_item_id: :personal_info)) do |component| %>
|
35
|
-
# <% component.
|
36
|
-
# <%
|
35
|
+
# <% component.with_group(aria: { label: "Settings" }) do |group| %>
|
36
|
+
# <% group.with_item(label: "General", selected_by_ids: :general, href: "/settings/general") %>
|
37
37
|
# <% end %>
|
38
|
-
# <% component.
|
39
|
-
# <%
|
40
|
-
# <%
|
41
|
-
# <%
|
42
|
-
# <%
|
38
|
+
# <% component.with_group do |group| %>
|
39
|
+
# <% group.with_heading(title: "Account Settings") %>
|
40
|
+
# <% group.with_item(label: "Personal Information", selected_by_ids: :personal_info, href: "/account/info") %>
|
41
|
+
# <% group.with_item(label: "Password", selected_by_ids: :password, href: "/account/password") %>
|
42
|
+
# <% group.with_item(label: "Billing info", selected_by_ids: :billing, href: "/account/billing") %>
|
43
43
|
# <% end %>
|
44
44
|
# <% end %>
|
45
45
|
#
|
46
46
|
# @example Leading and trailing visuals
|
47
47
|
#
|
48
48
|
# <%= render(Primer::Alpha::NavList.new(selected_item_id: :personal_info)) do |component| %>
|
49
|
-
# <% component.
|
50
|
-
# <%
|
51
|
-
# <%
|
49
|
+
# <% component.with_group do |group| %>
|
50
|
+
# <% group.with_heading(title: "Account Settings") %>
|
51
|
+
# <% group.with_item(label: "Personal Information", selected_by_ids: :personal_info, href: "/account/info") do |item| %>
|
52
52
|
# <% item.with_leading_visual_avatar(src: "https://github.com/github.png", alt: "GitHub") %>
|
53
53
|
# <% end %>
|
54
|
-
# <%
|
54
|
+
# <% group.with_item(label: "Notifications", selected_by_ids: :notifications, href: "/account/notifications") do |item| %>
|
55
55
|
# <% item.with_leading_visual_icon(icon: :bell) %>
|
56
56
|
# <% item.with_trailing_visual_counter(count: 15) %>
|
57
57
|
# <% end %>
|
58
|
-
# <%
|
58
|
+
# <% group.with_item(label: "Billing info", selected_by_ids: :billing, href: "/account/billing") do |item| %>
|
59
59
|
# <% item.with_leading_visual_icon(icon: :package) %>
|
60
60
|
# <% item.with_trailing_visual_icon(icon: :"dot-fill", color: :attention) %>
|
61
61
|
# <% end %>
|
@@ -65,9 +65,9 @@ module Primer
|
|
65
65
|
# @example Expandable sub items
|
66
66
|
#
|
67
67
|
# <%= render(Primer::Alpha::NavList.new(selected_item_id: :email_notifications)) do |component| %>
|
68
|
-
# <% component.
|
69
|
-
# <%
|
70
|
-
# <%
|
68
|
+
# <% component.with_group do |group| %>
|
69
|
+
# <% group.with_heading(title: "Account Settings") %>
|
70
|
+
# <% group.with_item(label: "Notification settings") do |item| %>
|
71
71
|
# <% item.with_leading_visual_icon(icon: :bell) %>
|
72
72
|
# <% item.with_item(label: "Email", selected_by_ids: :email_notifications, href: "/account/notifications/email") do |subitem| %>
|
73
73
|
# <% subitem.with_trailing_visual_icon(icon: :mail) %>
|
@@ -76,7 +76,7 @@ module Primer
|
|
76
76
|
# <% subitem.with_trailing_visual_icon(icon: :"device-mobile") %>
|
77
77
|
# <% end %>
|
78
78
|
# <% end %>
|
79
|
-
# <%
|
79
|
+
# <% group.with_item(label: "Messages") do |item| %>
|
80
80
|
# <% item.with_leading_visual_icon(icon: :bookmark) %>
|
81
81
|
# <% item.with_item(label: "Inbox", href: "/account/messages/inbox") do |subitem| %>
|
82
82
|
# <% subitem.with_trailing_visual_counter(count: 10) %>
|
@@ -91,13 +91,13 @@ module Primer
|
|
91
91
|
# @example Trailing action
|
92
92
|
#
|
93
93
|
# <%= render(Primer::Alpha::NavList.new) do |component| %>
|
94
|
-
# <% component.
|
95
|
-
# <%
|
96
|
-
# <%
|
97
|
-
# <% item.with_trailing_action(
|
94
|
+
# <% component.with_group do |group| %>
|
95
|
+
# <% group.with_heading(title: "My Favorite Foods") %>
|
96
|
+
# <% group.with_item(label: "Popplers", selected_by_ids: :popplers, href: "/foods/popplers") do |item| %>
|
97
|
+
# <% item.with_trailing_action(icon: "plus", "aria-label": "Add new food", size: :medium) %>
|
98
98
|
# <% end %>
|
99
|
-
# <%
|
100
|
-
# <% item.with_trailing_action(
|
99
|
+
# <% group.with_item(label: "Slurm", selected_by_ids: :slurm, href: "/foods/slurm") do |item| %>
|
100
|
+
# <% item.with_trailing_action(icon: "plus", "aria-label": "Add new food", size: :medium) %>
|
101
101
|
# <% end %>
|
102
102
|
# <% end %>
|
103
103
|
# <% end %>
|
@@ -106,10 +106,6 @@ module Primer
|
|
106
106
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
107
107
|
def initialize(selected_item_id: nil, **system_arguments)
|
108
108
|
@system_arguments = system_arguments
|
109
|
-
@system_arguments[:classes] = class_names(
|
110
|
-
@system_arguments[:classes],
|
111
|
-
"ActionListWrap"
|
112
|
-
)
|
113
109
|
@selected_item_id = selected_item_id
|
114
110
|
end
|
115
111
|
end
|
@@ -87,6 +87,7 @@ export class NavListElement extends HTMLElement {
|
|
87
87
|
collapseItem(item: HTMLElement) {
|
88
88
|
item.nextElementSibling?.setAttribute('data-hidden', '')
|
89
89
|
item.setAttribute('aria-expanded', 'false')
|
90
|
+
item.focus()
|
90
91
|
}
|
91
92
|
|
92
93
|
itemIsExpanded(item: HTMLElement | null) {
|
@@ -112,6 +113,28 @@ export class NavListElement extends HTMLElement {
|
|
112
113
|
e.stopPropagation()
|
113
114
|
}
|
114
115
|
|
116
|
+
// collapse item
|
117
|
+
handleItemWithSubItemKeydown(e: KeyboardEvent) {
|
118
|
+
const el = e.currentTarget
|
119
|
+
if (!(el instanceof HTMLElement)) return
|
120
|
+
|
121
|
+
let button = el.closest<HTMLButtonElement>('button')
|
122
|
+
if (!button) {
|
123
|
+
const button_id = el.getAttribute('aria-labelledby')
|
124
|
+
if (button_id) {
|
125
|
+
button = document.getElementById(button_id) as HTMLButtonElement
|
126
|
+
} else {
|
127
|
+
return
|
128
|
+
}
|
129
|
+
}
|
130
|
+
|
131
|
+
if (this.itemIsExpanded(button) && e.key === 'Escape') {
|
132
|
+
this.collapseItem(button)
|
133
|
+
}
|
134
|
+
|
135
|
+
e.stopPropagation()
|
136
|
+
}
|
137
|
+
|
115
138
|
private async showMore(e: Event) {
|
116
139
|
e.preventDefault()
|
117
140
|
if (this.showMoreDisabled) return
|