primer_view_components 0.0.123 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/app/assets/javascripts/primer_view_components.js +1 -1
  4. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  5. data/app/assets/styles/primer_view_components.css +2 -2
  6. data/app/assets/styles/primer_view_components.css.map +1 -1
  7. data/app/components/primer/alpha/action_list/divider.rb +2 -2
  8. data/app/components/primer/alpha/action_list/heading.html.erb +1 -1
  9. data/app/components/primer/alpha/action_list/heading.rb +10 -4
  10. data/app/components/primer/alpha/action_list/item.rb +7 -3
  11. data/app/components/primer/alpha/action_list.css.json +41 -0
  12. data/app/components/primer/alpha/action_list.html.erb +6 -8
  13. data/app/components/primer/alpha/action_list.rb +5 -10
  14. data/app/components/primer/alpha/auto_complete.css.json +11 -0
  15. data/app/components/primer/alpha/banner.css.json +14 -0
  16. data/app/components/primer/alpha/button_marketing.css.json +10 -0
  17. data/app/components/primer/alpha/dialog.css.json +63 -0
  18. data/app/components/primer/alpha/dropdown.css.json +21 -0
  19. data/app/components/primer/alpha/layout.css.json +27 -0
  20. data/app/components/primer/alpha/menu.css.json +11 -0
  21. data/app/components/primer/alpha/nav_list/{section.rb → group.rb} +9 -9
  22. data/app/components/primer/alpha/nav_list/item.html.erb +1 -1
  23. data/app/components/primer/alpha/nav_list/item.rb +18 -2
  24. data/app/components/primer/alpha/nav_list.d.ts +1 -0
  25. data/app/components/primer/alpha/nav_list.html.erb +8 -8
  26. data/app/components/primer/alpha/nav_list.js +24 -0
  27. data/app/components/primer/alpha/nav_list.rb +28 -32
  28. data/app/components/primer/alpha/nav_list.ts +27 -0
  29. data/app/components/primer/alpha/navigation/tab.rb +168 -0
  30. data/app/components/primer/alpha/overlay/body.rb +26 -0
  31. data/app/components/primer/alpha/overlay/footer.rb +41 -0
  32. data/app/components/primer/alpha/overlay/header.html.erb +15 -0
  33. data/app/components/primer/alpha/overlay/header.rb +47 -0
  34. data/app/components/primer/alpha/overlay.css +1 -0
  35. data/app/components/primer/alpha/overlay.css.json +11 -0
  36. data/app/components/primer/alpha/overlay.css.map +1 -0
  37. data/app/components/primer/alpha/overlay.html.erb +11 -0
  38. data/app/components/primer/alpha/overlay.pcss +14 -0
  39. data/app/components/primer/alpha/overlay.rb +207 -0
  40. data/app/components/primer/alpha/segmented_control.css.json +15 -0
  41. data/app/components/primer/alpha/tab_nav.css.json +10 -0
  42. data/app/components/primer/alpha/tab_nav.rb +10 -3
  43. data/app/components/primer/alpha/tab_panels.rb +2 -2
  44. data/app/components/primer/alpha/text_field.css.json +38 -0
  45. data/app/components/primer/alpha/toggle_switch.css.json +16 -0
  46. data/app/components/primer/alpha/underline_nav.css +1 -1
  47. data/app/components/primer/alpha/underline_nav.css.json +13 -0
  48. data/app/components/primer/alpha/underline_nav.css.map +1 -1
  49. data/app/components/primer/alpha/underline_nav.pcss +1 -0
  50. data/app/components/primer/alpha/underline_nav.rb +2 -2
  51. data/app/components/primer/alpha/underline_panels.rb +2 -2
  52. data/app/components/primer/anchored_position.d.ts +27 -0
  53. data/app/components/primer/anchored_position.js +149 -0
  54. data/app/components/primer/anchored_position.ts +167 -0
  55. data/app/components/primer/beta/avatar.css.json +14 -0
  56. data/app/components/primer/beta/avatar_stack.css.json +9 -0
  57. data/app/components/primer/beta/blankslate.css.json +12 -0
  58. data/app/components/primer/beta/border_box.css.json +32 -0
  59. data/app/components/primer/beta/breadcrumbs.css.json +4 -0
  60. data/app/components/primer/beta/button.css.json +22 -0
  61. data/app/components/primer/beta/button.html.erb +1 -1
  62. data/app/components/primer/beta/button.rb +2 -1
  63. data/app/components/primer/beta/counter.css.json +6 -0
  64. data/app/components/primer/beta/flash.css.json +15 -0
  65. data/app/components/primer/beta/flash.html.erb +1 -2
  66. data/app/components/primer/beta/label.css.json +20 -0
  67. data/app/components/primer/beta/link.css.json +8 -0
  68. data/app/components/primer/beta/popover.css.json +18 -0
  69. data/app/components/primer/beta/progress_bar.css.json +6 -0
  70. data/app/components/primer/beta/state.css.json +10 -0
  71. data/app/components/primer/beta/subhead.css.json +8 -0
  72. data/app/components/primer/beta/timeline_item.css.json +9 -0
  73. data/app/components/primer/beta/truncate.css.json +6 -0
  74. data/app/components/primer/component.rb +34 -0
  75. data/app/components/primer/navigation/tab_component.rb +3 -157
  76. data/app/components/primer/primer.d.ts +2 -0
  77. data/app/components/primer/primer.js +2 -0
  78. data/app/components/primer/primer.pcss +3 -0
  79. data/app/components/primer/primer.ts +2 -0
  80. data/app/components/primer/truncate.css.json +7 -0
  81. data/app/lib/primer/css/layout.css.json +263 -0
  82. data/app/lib/primer/css/utilities.css.json +1636 -0
  83. data/lib/primer/deprecations.yml +4 -0
  84. data/lib/primer/view_components/linters/base_linter.rb +1 -1
  85. data/lib/primer/view_components/linters/disallow_component_css_counter.rb +30 -0
  86. data/lib/primer/view_components/version.rb +2 -2
  87. data/lib/primer/yard/component_manifest.rb +3 -1
  88. data/lib/tasks/docs.rake +1 -1
  89. data/previews/primer/alpha/action_list_preview.rb +6 -14
  90. data/previews/primer/alpha/nav_list_preview/trailing_action.html.erb +19 -0
  91. data/previews/primer/alpha/nav_list_preview.rb +19 -30
  92. data/previews/primer/alpha/overlay_preview/middle_of_page.html.erb +17 -0
  93. data/previews/primer/alpha/overlay_preview.rb +112 -0
  94. data/previews/primer/alpha/tab_nav_preview/with_extra.html.erb +8 -0
  95. data/previews/primer/alpha/tab_nav_preview.rb +5 -0
  96. data/previews/primer/alpha/tab_panels_preview/with_extra.html.erb +17 -0
  97. data/previews/primer/alpha/tab_panels_preview.rb +5 -0
  98. data/static/arguments.json +167 -7
  99. data/static/audited_at.json +6 -1
  100. data/static/classes.json +311 -0
  101. data/static/constants.json +122 -8
  102. data/static/previews.json +31 -0
  103. data/static/statuses.json +7 -2
  104. metadata +25 -6
  105. data/app/components/primer/alpha/nav_list/section.html.erb +0 -3
  106. data/previews/primer/alpha/action_list_preview/heading.html.erb +0 -4
  107. /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
- # Section heading rendered above the section contents.
6
+ # Group heading rendered above the group contents.
7
7
  class Divider < Primer::Component
8
8
  DEFAULT_SCHEME = :subtle
9
9
  SCHEME_MAPPINGS = {
@@ -16,7 +16,7 @@ module Primer
16
16
  # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
17
17
  def initialize(scheme: DEFAULT_SCHEME, **system_arguments)
18
18
  @system_arguments = system_arguments
19
- @system_arguments[:tag] = :li
19
+ @system_arguments[:tag] = :div
20
20
  @system_arguments[:role] = :separator
21
21
  @system_arguments[:'aria-hidden'] = true
22
22
  @scheme = fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)
@@ -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 [Symbol] Semantic tag for the heading.
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:, tag: :h3, scheme: DEFAULT_SCHEME, subtitle: nil, **system_arguments)
22
- @tag = tag
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}"
23
30
  @system_arguments = 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],
@@ -112,7 +112,7 @@ module Primer
112
112
  # @private
113
113
  renders_one :private_content
114
114
 
115
- attr_reader :list, :href, :active, :disabled, :parent
115
+ attr_reader :id, :list, :href, :active, :disabled, :parent
116
116
 
117
117
  # Whether or not this item is active.
118
118
  #
@@ -128,6 +128,7 @@ module Primer
128
128
  # @param parent [Primer::Alpha::ActionList::Item] This item's parent item. `nil` if this item is at the root. Used internally.
129
129
  # @param label [String] Item label.
130
130
  # @param label_classes [String] CSS classes that will be added to the label.
131
+ # @param label_arguments [Hash] <%= link_to_system_arguments_docs %> used to construct the label.
131
132
  # @param content_arguments [Hash] <%= link_to_system_arguments_docs %> used to construct the item's anchor or button tag.
132
133
  # @param truncate_label [Boolean] Truncate label with ellipsis.
133
134
  # @param href [String] Link URL.
@@ -144,11 +145,12 @@ module Primer
144
145
  list:,
145
146
  label:,
146
147
  label_classes: nil,
148
+ label_arguments: {},
147
149
  content_arguments: {},
148
150
  parent: nil,
149
151
  truncate_label: false,
150
152
  href: nil,
151
- role: :listitem,
153
+ role: nil,
152
154
  size: DEFAULT_SIZE,
153
155
  scheme: DEFAULT_SCHEME,
154
156
  disabled: false,
@@ -182,7 +184,7 @@ module Primer
182
184
  "ActionListItem"
183
185
  )
184
186
 
185
- @system_arguments[:role] = role
187
+ @system_arguments[:role] = role if role
186
188
 
187
189
  @system_arguments[:aria] ||= {}
188
190
  @system_arguments[:aria][:disabled] = "true" if @disabled
@@ -191,8 +193,10 @@ module Primer
191
193
  @system_arguments[:data][:targets] = "#{list_class.custom_element_name}.items"
192
194
 
193
195
  @label_arguments = {
196
+ **label_arguments,
194
197
  classes: class_names(
195
198
  label_classes,
199
+ label_arguments[:classes],
196
200
  "ActionListItem-label",
197
201
  "ActionListItem-label--truncate" => @truncate_label
198
202
  )
@@ -119,5 +119,46 @@
119
119
  ".ActionList-sectionDivider--filled",
120
120
  ".ActionList-sectionDivider--filled:empty",
121
121
  ".ActionList-sectionDivider--filled:first-child"
122
+ ],
123
+ "classes": [
124
+ "ActionListWrap",
125
+ "ActionListWrap--inset",
126
+ "ActionListWrap--divided",
127
+ "ActionListItem-label",
128
+ "ActionListItem-descriptionWrap--inline",
129
+ "ActionList-sectionDivider",
130
+ "ActionListItem",
131
+ "ActionListItem--navActive",
132
+ "ActionListItem--hasSubItem",
133
+ "ActionListContent",
134
+ "ActionListItem-multiSelectCheckmark",
135
+ "ActionListItem-singleSelectCheckmark",
136
+ "ActionListItem-multiSelectIcon",
137
+ "ActionListItem-multiSelectIconRect",
138
+ "ActionListItem-description",
139
+ "ActionListItem-visual",
140
+ "ActionListItem--danger",
141
+ "ActionList--subGroup",
142
+ "ActionListContent--visual16",
143
+ "ActionListContent--visual20",
144
+ "ActionListContent--visual24",
145
+ "ActionListItem-collapseIcon",
146
+ "ActionListContent--hasActiveSubItem",
147
+ "ActionListContent--sizeLarge",
148
+ "ActionListContent--sizeXLarge",
149
+ "ActionListContent--blockDescription",
150
+ "ActionListItem-action--leading",
151
+ "ActionListItem-visual--leading",
152
+ "ActionListItem-visual--trailing",
153
+ "ActionListItem-action--trailing",
154
+ "ActionListItem-descriptionWrap",
155
+ "ActionListItem-action",
156
+ "ActionListItem-label--truncate",
157
+ "ActionListItem--subItem",
158
+ "ActionListItem--withActions",
159
+ "ActionListItem-trailingAction",
160
+ "ActionListItem--trailingActionHover",
161
+ "ActionList-sectionDivider-title",
162
+ "ActionList-sectionDivider--filled"
122
163
  ]
123
164
  }
@@ -1,15 +1,13 @@
1
- <%= render(Primer::BaseComponent.new(tag: :ul, role: @role, classes: "ActionListWrap")) do %>
1
+ <%= render(Primer::BaseComponent.new(tag: :div)) do %>
2
2
  <% if heading %>
3
3
  <%= heading %>
4
4
  <% end %>
5
- <%= render(Primer::BaseComponent.new(tag: :li, **@list_wrapper_arguments)) do %>
6
- <%= render(Primer::BaseComponent.new(tag: :ul, **@system_arguments)) do %>
7
- <% items.each_with_index do |item, index| %>
8
- <% if index > 0 && @show_dividers %>
9
- <%= render(Primer::Alpha::ActionList::Divider.new) %>
10
- <% end %>
11
- <%= item %>
5
+ <%= render(Primer::BaseComponent.new(tag: :ul, **@system_arguments)) do %>
6
+ <% items.each_with_index do |item, index| %>
7
+ <% if index > 0 && @show_dividers %>
8
+ <%= render(Primer::Alpha::ActionList::Divider.new) %>
12
9
  <% end %>
10
+ <%= item %>
13
11
  <% end %>
14
12
  <% end %>
15
13
  <% end %>
@@ -61,10 +61,10 @@ module Primer
61
61
  **system_arguments
62
62
  )
63
63
  @id = self.class.generate_id
64
- @role = role
65
64
 
66
65
  @system_arguments = system_arguments
67
66
  @system_arguments[:tag] = :ul
67
+ @system_arguments[:role] = role
68
68
  @item_classes = item_classes
69
69
  @scheme = fetch_or_fallback(SCHEME_OPTIONS, scheme, DEFAULT_SCHEME)
70
70
  @show_dividers = show_dividers
@@ -72,7 +72,6 @@ module Primer
72
72
  SCHEME_MAPPINGS[@scheme],
73
73
  system_arguments[:classes],
74
74
  "ActionListWrap",
75
- "ActionListWrap--subGroup",
76
75
  "ActionListWrap--divided" => @show_dividers
77
76
  )
78
77
 
@@ -81,18 +80,14 @@ module Primer
81
80
 
82
81
  # @private
83
82
  def before_render
83
+ aria_label = aria(:label, @system_arguments)
84
+
84
85
  if heading.present?
85
86
  @system_arguments[:"aria-labelledby"] = @id
86
- elsif aria(:label, @system_arguments).blank?
87
+ raise ArgumentError, "An aria-label should not be provided if a heading is present" if aria_label.present?
88
+ elsif aria_label.blank?
87
89
  raise ArgumentError, "An aria-label or heading must be provided"
88
90
  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
91
  end
97
92
 
98
93
  # @private
@@ -19,5 +19,16 @@
19
19
  ".autocomplete-item.navigation-focus *",
20
20
  ".autocomplete-item.selected *",
21
21
  ".autocomplete-item[aria-selected=true] *"
22
+ ],
23
+ "classes": [
24
+ "autocomplete-label-stacked",
25
+ "autocomplete-label-inline",
26
+ "autocomplete-body",
27
+ "autocomplete-embedded-icon-wrap",
28
+ "form-control",
29
+ "autocomplete-results",
30
+ "autocomplete-item",
31
+ "navigation-focus",
32
+ "selected"
22
33
  ]
23
34
  }
@@ -20,5 +20,19 @@
20
20
  ".Banner.Banner--success .Banner-visual .octicon",
21
21
  ".Banner.Banner--full",
22
22
  ".Banner.Banner--full-whenNarrow"
23
+ ],
24
+ "classes": [
25
+ "Banner",
26
+ "Banner-actions",
27
+ "Banner-visual",
28
+ "octicon",
29
+ "Banner-message",
30
+ "Banner-title",
31
+ "Banner-close",
32
+ "Banner--warning",
33
+ "Banner--error",
34
+ "Banner--success",
35
+ "Banner--full",
36
+ "Banner--full-whenNarrow"
23
37
  ]
24
38
  }
@@ -29,5 +29,15 @@
29
29
  ".btn-signup-mktg:focus-visible",
30
30
  ".btn-small-mktg",
31
31
  ".btn-large-mktg"
32
+ ],
33
+ "classes": [
34
+ "btn-mktg",
35
+ "focus",
36
+ "disabled",
37
+ "btn-muted-mktg",
38
+ "btn-subtle-mktg",
39
+ "btn-signup-mktg",
40
+ "btn-small-mktg",
41
+ "btn-large-mktg"
32
42
  ]
33
43
  }
@@ -78,5 +78,68 @@
78
78
  ".Overlay-backdrop--side-whenNarrow.Overlay-backdrop--placement-top-whenNarrow>.Overlay-whenNarrow",
79
79
  ".Overlay-backdrop--full-whenNarrow",
80
80
  ".Overlay-backdrop--full-whenNarrow .Overlay"
81
+ ],
82
+ "classes": [
83
+ "Overlay--hidden",
84
+ "Overlay--visibilityHidden",
85
+ "Overlay",
86
+ "Overlay--size-auto",
87
+ "Overlay--size-full",
88
+ "Overlay--size-xsmall",
89
+ "Overlay--size-small",
90
+ "Overlay--size-small-portrait",
91
+ "Overlay--size-medium",
92
+ "Overlay--size-medium-portrait",
93
+ "Overlay--size-large",
94
+ "Overlay--size-xlarge",
95
+ "Overlay--height-auto",
96
+ "Overlay--height-xsmall",
97
+ "Overlay--height-small",
98
+ "Overlay--height-medium",
99
+ "Overlay--height-large",
100
+ "Overlay--height-xlarge",
101
+ "Overlay--width-auto",
102
+ "Overlay--width-small",
103
+ "Overlay--width-medium",
104
+ "Overlay--width-large",
105
+ "Overlay--width-xlarge",
106
+ "Overlay--width-xxlarge",
107
+ "Overlay--motion-scaleFade",
108
+ "Overlay-form",
109
+ "Overlay-header",
110
+ "Overlay-header--divided",
111
+ "Overlay-body",
112
+ "Overlay-header--large",
113
+ "Overlay-headerContentWrap",
114
+ "Overlay-titleWrap",
115
+ "Overlay-title",
116
+ "Overlay-description",
117
+ "Overlay-actionWrap",
118
+ "Overlay-body--paddingCondensed",
119
+ "Overlay-body--paddingNone",
120
+ "Overlay-footer",
121
+ "Overlay-footer--divided",
122
+ "Overlay-footer--alignStart",
123
+ "Overlay-footer--alignCenter",
124
+ "Overlay-footer--alignEnd",
125
+ "Overlay-closeButton",
126
+ "close-button",
127
+ "Overlay-backdrop--center",
128
+ "Overlay-backdrop--anchor",
129
+ "Overlay-backdrop--side",
130
+ "Overlay-backdrop--placement-left",
131
+ "Overlay-backdrop--placement-right",
132
+ "Overlay-backdrop--placement-bottom",
133
+ "Overlay-backdrop--placement-top",
134
+ "Overlay-backdrop--full",
135
+ "Overlay-backdrop--center-whenNarrow",
136
+ "Overlay-backdrop--anchor-whenNarrow",
137
+ "Overlay-backdrop--side-whenNarrow",
138
+ "Overlay-backdrop--placement-left-whenNarrow",
139
+ "Overlay-whenNarrow",
140
+ "Overlay-backdrop--placement-right-whenNarrow",
141
+ "Overlay-backdrop--placement-bottom-whenNarrow",
142
+ "Overlay-backdrop--placement-top-whenNarrow",
143
+ "Overlay-backdrop--full-whenNarrow"
81
144
  ]
82
145
  }
@@ -36,5 +36,26 @@
36
36
  ".dropdown-menu-sw:after",
37
37
  ".dropdown-menu-se:before",
38
38
  ".dropdown-menu-se:after"
39
+ ],
40
+ "classes": [
41
+ "dropdown",
42
+ "dropdown-caret",
43
+ "dropdown-menu",
44
+ "dropdown-menu-no-overflow",
45
+ "dropdown-item",
46
+ "octicon",
47
+ "color-fg-",
48
+ "Label",
49
+ "btn-link",
50
+ "dropdown-signout",
51
+ "dropdown-divider",
52
+ "dropdown-header",
53
+ "octicon-check",
54
+ "dropdown-menu-w",
55
+ "dropdown-menu-e",
56
+ "dropdown-menu-ne",
57
+ "dropdown-menu-s",
58
+ "dropdown-menu-sw",
59
+ "dropdown-menu-se"
39
60
  ]
40
61
  }
@@ -76,5 +76,32 @@
76
76
  ".Layout-main .Layout-main-centered-xl>.container-lg",
77
77
  ".Layout-main .Layout-main-centered-xl>.container-md",
78
78
  ".Layout-main .Layout-main-centered-xl>.container-xl"
79
+ ],
80
+ "classes": [
81
+ "Layout",
82
+ "Layout-divider",
83
+ "Layout-main",
84
+ "Layout-sidebar",
85
+ "Layout--sidebarPosition-flowRow-start",
86
+ "Layout--sidebarPosition-flowRow-end",
87
+ "Layout--sidebarPosition-flowRow-none",
88
+ "Layout--divided",
89
+ "Layout-divider--flowRow-hidden",
90
+ "Layout-divider--flowRow-shallow",
91
+ "Layout--flowRow-until-md",
92
+ "Layout--flowRow-until-lg",
93
+ "Layout--gutter-none",
94
+ "Layout--gutter-condensed",
95
+ "Layout--gutter-spacious",
96
+ "Layout--sidebar-narrow",
97
+ "Layout--sidebar-wide",
98
+ "Layout--sidebarPosition-start",
99
+ "Layout--sidebarPosition-end",
100
+ "Layout-main-centered-lg",
101
+ "Layout-main-centered-md",
102
+ "Layout-main-centered-xl",
103
+ "container-lg",
104
+ "container-md",
105
+ "container-xl"
79
106
  ]
80
107
  }
@@ -24,5 +24,16 @@
24
24
  ".menu-heading:hover",
25
25
  ".menu-heading:first-child",
26
26
  ".menu-heading:last-child"
27
+ ],
28
+ "classes": [
29
+ "menu",
30
+ "menu-item",
31
+ "selected",
32
+ "octicon",
33
+ "Counter",
34
+ "menu-warning",
35
+ "avatar",
36
+ "alert",
37
+ "menu-heading"
27
38
  ]
28
39
  }
@@ -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 Section < ActionList
10
- # A special "show more" list item that appears at the bottom of the section. Clicking
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 section.
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.
@@ -28,10 +28,10 @@ module Primer
28
28
  system_arguments[:data][:action] = "click:nav-list#showMore"
29
29
  system_arguments[:data][:"current-page"] = "1"
30
30
  system_arguments[:data][:"total-pages"] = pages.to_s
31
- system_arguments[:label_classes] = class_names(
32
- system_arguments[:label_classes],
33
- "color-fg-accent"
34
- )
31
+ system_arguments[:label_arguments] = {
32
+ **system_arguments[:label_arguments] || {},
33
+ color: :accent
34
+ }
35
35
 
36
36
  component_klass.new(list: self, src: src, **system_arguments)
37
37
  }
@@ -51,14 +51,14 @@ module Primer
51
51
  super(**@system_arguments)
52
52
  end
53
53
 
54
- # Cause this section to show its list of sub items when rendered.
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 section.
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,13 +47,17 @@ 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)
53
57
  end
54
58
 
55
59
  def active?
56
- item_active?(self)
60
+ item_active?(self) && items.empty?
57
61
  end
58
62
 
59
63
  # Cause this item to show its list of sub items when rendered.
@@ -75,11 +79,23 @@ module Primer
75
79
 
76
80
  raise "Cannot render a trailing action for an item with subitems" if items.present? && trailing_action.present?
77
81
 
82
+ raise "Cannot pass `selected_by_ids:` for an item with subitems, since parent items cannot be selected" if items.present? && @selected_by_ids.present?
83
+
78
84
  return if items.blank?
79
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
+
80
93
  @content_arguments[:tag] = :button
81
94
  @content_arguments[:"aria-expanded"] = @expanded.to_s
82
- @content_arguments[:"data-action"] = "click:#{@list.custom_element_name}#handleItemWithSubItemClick"
95
+ @content_arguments[:"data-action"] = "
96
+ click:#{@list.custom_element_name}#handleItemWithSubItemClick
97
+ keydown:#{@list.custom_element_name}#handleItemWithSubItemKeydown
98
+ "
83
99
 
84
100
  with_private_trailing_action_icon(:"chevron-down", classes: "ActionListItem-collapseIcon")
85
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: :ul, **@system_arguments)) do %>
2
- <% sections.each_with_index do |section, index| %>
3
- <% if index > 0 %>
4
- <%= render(Primer::Alpha::ActionList::Divider.new) %>
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
- <li>
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();
@@ -157,6 +178,9 @@ _NavListElement_instances = new WeakSet(), _NavListElement_parseHTML = function
157
178
  var _a;
158
179
  // First we compare the selected link to data-item-id for each nav item
159
180
  for (const navItem of this.items) {
181
+ if (navItem.classList.contains('ActionListItem--hasSubItem')) {
182
+ continue;
183
+ }
160
184
  const keys = ((_a = navItem.getAttribute('data-item-id')) === null || _a === void 0 ? void 0 : _a.split(' ')) || [];
161
185
  if (keys.includes(itemId)) {
162
186
  return navItem;