primer_view_components 0.0.96 → 0.0.97

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -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 +1 -1
  6. data/app/assets/styles/primer_view_components.css.map +1 -1
  7. data/app/components/primer/alpha/action_list/action-list-selection.pcss +92 -0
  8. data/app/components/primer/alpha/action_list/action-list.pcss +620 -0
  9. data/app/components/primer/alpha/action_list/divider.rb +35 -0
  10. data/app/components/primer/alpha/action_list/heading.html.erb +8 -0
  11. data/app/components/primer/alpha/action_list/heading.rb +38 -0
  12. data/app/components/primer/alpha/action_list/item.html.erb +39 -0
  13. data/app/components/primer/alpha/action_list/item.rb +230 -0
  14. data/app/components/primer/alpha/action_list.html.erb +15 -0
  15. data/app/components/primer/alpha/action_list.rb +112 -0
  16. data/app/components/primer/alpha/dialog/header.rb +1 -1
  17. data/app/components/primer/alpha/nav_list/item.html.erb +13 -0
  18. data/app/components/primer/alpha/nav_list/item.rb +89 -0
  19. data/app/components/primer/alpha/nav_list/section.html.erb +3 -0
  20. data/app/components/primer/alpha/nav_list/section.rb +88 -0
  21. data/app/components/primer/alpha/nav_list.d.ts +25 -0
  22. data/app/components/primer/alpha/nav_list.html.erb +10 -0
  23. data/app/components/primer/alpha/nav_list.js +130 -0
  24. data/app/components/primer/alpha/nav_list.rb +112 -0
  25. data/app/components/primer/alpha/nav_list.ts +129 -0
  26. data/app/components/primer/primer.d.ts +1 -0
  27. data/app/components/primer/primer.js +1 -0
  28. data/app/components/primer/primer.pcss +1 -0
  29. data/app/components/primer/primer.ts +1 -0
  30. data/lib/postcss_mixins/activeIndicatorLine.pcss +11 -0
  31. data/lib/primer/view_components/version.rb +1 -1
  32. data/lib/tasks/docs.rake +51 -22
  33. data/lib/yard/docs_helper.rb +3 -3
  34. data/static/arguments.json +267 -3
  35. data/static/audited_at.json +7 -0
  36. data/static/constants.json +76 -0
  37. data/static/statuses.json +7 -0
  38. metadata +21 -4
  39. data/app/components/primer/experimental/action_bar.d.ts +0 -14
  40. data/app/components/primer/experimental/action_bar.js +0 -141
@@ -0,0 +1,130 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /* eslint-disable custom-elements/expose-class-on-global */
8
+ import { controller, target, targets } from '@github/catalyst';
9
+ let NavListElement = class NavListElement extends HTMLElement {
10
+ connectedCallback() {
11
+ this.setShowMoreItemState();
12
+ }
13
+ get showMoreDisabled() {
14
+ return this.showMoreItem.hasAttribute('aria-disabled');
15
+ }
16
+ set showMoreDisabled(value) {
17
+ if (value) {
18
+ this.showMoreItem.setAttribute('aria-disabled', 'true');
19
+ }
20
+ else {
21
+ this.showMoreItem.removeAttribute('aria-disabled');
22
+ }
23
+ this.showMoreItem.classList.toggle('disabled', value);
24
+ }
25
+ set currentPage(value) {
26
+ this.showMoreItem.setAttribute('data-current-page', value.toString());
27
+ }
28
+ get currentPage() {
29
+ return parseInt(this.showMoreItem.getAttribute('data-current-page')) || 1;
30
+ }
31
+ get totalPages() {
32
+ return parseInt(this.showMoreItem.getAttribute('data-total-pages')) || 1;
33
+ }
34
+ get paginationSrc() {
35
+ return this.showMoreItem.getAttribute('src') || '';
36
+ }
37
+ // expand collapsible item onClick
38
+ expandItem(item) {
39
+ var _a;
40
+ (_a = item.nextElementSibling) === null || _a === void 0 ? void 0 : _a.removeAttribute('data-hidden');
41
+ item.setAttribute('aria-expanded', 'true');
42
+ }
43
+ collapseItem(item) {
44
+ var _a;
45
+ (_a = item.nextElementSibling) === null || _a === void 0 ? void 0 : _a.setAttribute('data-hidden', '');
46
+ item.setAttribute('aria-expanded', 'false');
47
+ }
48
+ itemIsExpanded(item) {
49
+ if ((item === null || item === void 0 ? void 0 : item.tagName) === 'A') {
50
+ return true;
51
+ }
52
+ return (item === null || item === void 0 ? void 0 : item.getAttribute('aria-expanded')) === 'true';
53
+ }
54
+ // expand/collapse item
55
+ handleItemWithSubItemClick(e) {
56
+ const target = e.target;
57
+ if (!(target instanceof HTMLElement))
58
+ return;
59
+ const button = target.closest('button');
60
+ if (!button)
61
+ return;
62
+ if (this.itemIsExpanded(button)) {
63
+ this.collapseItem(button);
64
+ }
65
+ else {
66
+ this.expandItem(button);
67
+ }
68
+ e.stopPropagation();
69
+ }
70
+ async showMore(e) {
71
+ var _a, _b;
72
+ e.preventDefault();
73
+ if (this.showMoreDisabled)
74
+ return;
75
+ this.showMoreDisabled = true;
76
+ let html;
77
+ try {
78
+ const paginationURL = new URL(this.paginationSrc, window.location.origin);
79
+ this.currentPage++;
80
+ paginationURL.searchParams.append('page', this.currentPage.toString());
81
+ const response = await fetch(paginationURL);
82
+ if (!response.ok)
83
+ return;
84
+ html = await response.text();
85
+ if (this.currentPage === this.totalPages) {
86
+ this.showMoreItem.hidden = true;
87
+ }
88
+ }
89
+ catch (err) {
90
+ // Ignore network errors
91
+ this.showMoreDisabled = false;
92
+ this.currentPage--;
93
+ return;
94
+ }
95
+ const fragment = this.parseHTML(document, html);
96
+ (_a = fragment === null || fragment === void 0 ? void 0 : fragment.querySelector('li > a')) === null || _a === void 0 ? void 0 : _a.setAttribute('data-targets', 'nav-list.focusMarkers');
97
+ this.list.insertBefore(fragment, this.showMoreItem);
98
+ (_b = this.focusMarkers.pop()) === null || _b === void 0 ? void 0 : _b.focus();
99
+ this.showMoreDisabled = false;
100
+ }
101
+ setShowMoreItemState() {
102
+ if (!this.showMoreItem) {
103
+ return;
104
+ }
105
+ if (this.currentPage < this.totalPages) {
106
+ this.showMoreItem.hidden = false;
107
+ }
108
+ else {
109
+ this.showMoreItem.hidden = true;
110
+ }
111
+ }
112
+ parseHTML(document, html) {
113
+ const template = document.createElement('template');
114
+ // eslint-disable-next-line github/no-inner-html
115
+ template.innerHTML = html;
116
+ return document.importNode(template.content, true);
117
+ }
118
+ };
119
+ __decorate([
120
+ target
121
+ ], NavListElement.prototype, "list", void 0);
122
+ __decorate([
123
+ target
124
+ ], NavListElement.prototype, "showMoreItem", void 0);
125
+ __decorate([
126
+ targets
127
+ ], NavListElement.prototype, "focusMarkers", void 0);
128
+ NavListElement = __decorate([
129
+ controller
130
+ ], NavListElement);
@@ -0,0 +1,112 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
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 section in a
7
+ # nav list is a list of links.
8
+ #
9
+ # Nav list sections can contain sub items. Rather than navigating to a URL, sections
10
+ # with sub items expand and collapse on click. To indicate this functionality, the
11
+ # section will automatically render with a trailing chevron icon that changes direction
12
+ # when the section expands and collapses.
13
+ #
14
+ # Nav list items appear visually active when selected. Each nav item must have one
15
+ # or more ID values that determine which item will appear selected. Use the
16
+ # `selected_item_id` argument to select the appropriate item.
17
+ class NavList < Primer::Component
18
+ status :alpha
19
+
20
+ # Sections. Each section is a list of links and an optional heading.
21
+ #
22
+ # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Alpha::NavList::Section) %>.
23
+ renders_many :sections, lambda { |**system_arguments|
24
+ Primer::Alpha::NavList::Section.new(selected_item_id: @selected_item_id, **system_arguments)
25
+ }
26
+
27
+ # @example Items and headings
28
+ #
29
+ # <%= render(Primer::Alpha::NavList.new(selected_item_id: :personal_info)) do |component| %>
30
+ # <% component.with_section(aria: { label: "Settings" }) do |section| %>
31
+ # <% section.with_item(label: "General", selected_by_ids: :general, href: "/settings/general") %>
32
+ # <% end %>
33
+ # <% component.with_section(aria: { label: "Account settings" }) do |section| %>
34
+ # <% section.with_heading(title: "Account Settings") %>
35
+ # <% section.with_item(label: "Personal Information", selected_by_ids: :personal_info, href: "/account/info") %>
36
+ # <% section.with_item(label: "Password", selected_by_ids: :password, href: "/account/password") %>
37
+ # <% section.with_item(label: "Billing info", selected_by_ids: :billing, href: "/account/billing") %>
38
+ # <% end %>
39
+ # <% end %>
40
+ #
41
+ # @example Leading and trailing visuals
42
+ #
43
+ # <%= render(Primer::Alpha::NavList.new(selected_item_id: :personal_info)) do |component| %>
44
+ # <% component.with_section(aria: { label: "Account settings" }) do |section| %>
45
+ # <% section.with_heading(title: "Account Settings") %>
46
+ # <% section.with_item(label: "Personal Information", selected_by_ids: :personal_info, href: "/account/info") do |item| %>
47
+ # <% item.with_leading_visual_avatar(src: "https://github.com/github.png", alt: "GitHub") %>
48
+ # <% end %>
49
+ # <% section.with_item(label: "Notifications", selected_by_ids: :notifications, href: "/account/notifications") do |item| %>
50
+ # <% item.with_leading_visual_icon(icon: :bell) %>
51
+ # <% item.with_trailing_visual_counter(count: 15) %>
52
+ # <% end %>
53
+ # <% section.with_item(label: "Billing info", selected_by_ids: :billing, href: "/account/billing") do |item| %>
54
+ # <% item.with_leading_visual_icon(icon: :package) %>
55
+ # <% item.with_trailing_visual_icon(icon: :"dot-fill", color: :attention) %>
56
+ # <% end %>
57
+ # <% end %>
58
+ # <% end %>
59
+ #
60
+ # @example Expandable sub items
61
+ #
62
+ # <%= render(Primer::Alpha::NavList.new(selected_item_id: :email_notifications)) do |component| %>
63
+ # <% component.with_section(aria: { label: "Account settings" }) do |section| %>
64
+ # <% section.with_heading(title: "Account Settings") %>
65
+ # <% section.with_item(label: "Notification settings", selected_by_ids: :notifications) do |item| %>
66
+ # <% item.with_leading_visual_icon(icon: :bell) %>
67
+ # <% item.with_item(label: "Email", selected_by_ids: :email_notifications, href: "/account/notifications/email") do |subitem| %>
68
+ # <% subitem.with_trailing_visual_icon(icon: :mail) %>
69
+ # <% end %>
70
+ # <% item.with_item(label: "SMS", selected_by_ids: :sms_notifications, href: "/account/notifications/sms") do |subitem| %>
71
+ # <% subitem.with_trailing_visual_icon(icon: :"device-mobile") %>
72
+ # <% end %>
73
+ # <% end %>
74
+ # <% section.with_item(label: "Messages", selected_by_ids: :messages) do |item| %>
75
+ # <% item.with_leading_visual_icon(icon: :bookmark) %>
76
+ # <% item.with_item(label: "Inbox", href: "/account/messages/inbox") do |subitem| %>
77
+ # <% subitem.with_trailing_visual_counter(count: 10) %>
78
+ # <% end %>
79
+ # <% item.with_item(label: "Organizer", href: "/account/messages/organizer") do |subitem| %>
80
+ # <% subitem.with_trailing_visual_label(scheme: :primary) { "New" } %>
81
+ # <% end %>
82
+ # <% end %>
83
+ # <% end %>
84
+ # <% end %>
85
+ #
86
+ # @example Trailing action
87
+ #
88
+ # <%= render(Primer::Alpha::NavList.new) do |component| %>
89
+ # <% component.with_section(aria: { label: "Favorite foods" }) do |section| %>
90
+ # <% section.with_heading(title: "My Favorite Foods") %>
91
+ # <% section.with_item(label: "Popplers", selected_by_ids: :popplers, href: "/foods/popplers") do |item| %>
92
+ # <% item.with_trailing_action(show_on_hover: false, icon: "plus", "aria-label": "Add new food", size: :medium) %>
93
+ # <% end %>
94
+ # <% section.with_item(label: "Slurm", selected_by_ids: :slurm, href: "/foods/slurm") do |item| %>
95
+ # <% item.with_trailing_action(show_on_hover: true, icon: "plus", "aria-label": "Add new food", size: :medium) %>
96
+ # <% end %>
97
+ # <% end %>
98
+ # <% end %>
99
+ #
100
+ # @param selected_item_id [Symbol] The ID of the currently selected item. The default is `nil`, meaning no item is selected.
101
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
102
+ def initialize(selected_item_id: nil, **system_arguments)
103
+ @system_arguments = system_arguments
104
+ @system_arguments[:classes] = class_names(
105
+ @system_arguments[:classes],
106
+ "ActionListWrap"
107
+ )
108
+ @selected_item_id = selected_item_id
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,129 @@
1
+ /* eslint-disable custom-elements/expose-class-on-global */
2
+ import {controller, target, targets} from '@github/catalyst'
3
+
4
+ @controller
5
+ class NavListElement extends HTMLElement {
6
+ @target list: HTMLElement
7
+ @target showMoreItem: HTMLElement
8
+ @targets focusMarkers: HTMLElement[]
9
+
10
+ connectedCallback(): void {
11
+ this.setShowMoreItemState()
12
+ }
13
+
14
+ get showMoreDisabled(): boolean {
15
+ return this.showMoreItem.hasAttribute('aria-disabled')
16
+ }
17
+
18
+ set showMoreDisabled(value: boolean) {
19
+ if (value) {
20
+ this.showMoreItem.setAttribute('aria-disabled', 'true')
21
+ } else {
22
+ this.showMoreItem.removeAttribute('aria-disabled')
23
+ }
24
+ this.showMoreItem.classList.toggle('disabled', value)
25
+ }
26
+
27
+ set currentPage(value: number) {
28
+ this.showMoreItem.setAttribute('data-current-page', value.toString())
29
+ }
30
+
31
+ get currentPage(): number {
32
+ return parseInt(this.showMoreItem.getAttribute('data-current-page') as string) || 1
33
+ }
34
+
35
+ get totalPages(): number {
36
+ return parseInt(this.showMoreItem.getAttribute('data-total-pages') as string) || 1
37
+ }
38
+
39
+ get paginationSrc(): string {
40
+ return this.showMoreItem.getAttribute('src') || ''
41
+ }
42
+
43
+ // expand collapsible item onClick
44
+ expandItem(item: HTMLElement) {
45
+ item.nextElementSibling?.removeAttribute('data-hidden')
46
+ item.setAttribute('aria-expanded', 'true')
47
+ }
48
+
49
+ collapseItem(item: HTMLElement) {
50
+ item.nextElementSibling?.setAttribute('data-hidden', '')
51
+ item.setAttribute('aria-expanded', 'false')
52
+ }
53
+
54
+ itemIsExpanded(item: HTMLElement | null) {
55
+ if (item?.tagName === 'A') {
56
+ return true
57
+ }
58
+ return item?.getAttribute('aria-expanded') === 'true'
59
+ }
60
+
61
+ // expand/collapse item
62
+ handleItemWithSubItemClick(e: Event) {
63
+ const target = e.target
64
+ if (!(target instanceof HTMLElement)) return
65
+
66
+ const button = target.closest<HTMLButtonElement>('button')
67
+ if (!button) return
68
+ if (this.itemIsExpanded(button)) {
69
+ this.collapseItem(button)
70
+ } else {
71
+ this.expandItem(button)
72
+ }
73
+
74
+ e.stopPropagation()
75
+ }
76
+
77
+ private async showMore(e: Event) {
78
+ e.preventDefault()
79
+ if (this.showMoreDisabled) return
80
+ this.showMoreDisabled = true
81
+ let html
82
+ try {
83
+ const paginationURL = new URL(this.paginationSrc, window.location.origin)
84
+ this.currentPage++
85
+ paginationURL.searchParams.append('page', this.currentPage.toString())
86
+ const response = await fetch(paginationURL)
87
+ if (!response.ok) return
88
+ html = await response.text()
89
+ if (this.currentPage === this.totalPages) {
90
+ this.showMoreItem.hidden = true
91
+ }
92
+ } catch (err) {
93
+ // Ignore network errors
94
+ this.showMoreDisabled = false
95
+ this.currentPage--
96
+ return
97
+ }
98
+ const fragment = this.parseHTML(document, html)
99
+ fragment?.querySelector('li > a')?.setAttribute('data-targets', 'nav-list.focusMarkers')
100
+ this.list.insertBefore(fragment, this.showMoreItem)
101
+ this.focusMarkers.pop()?.focus()
102
+ this.showMoreDisabled = false
103
+ }
104
+
105
+ private setShowMoreItemState() {
106
+ if (!this.showMoreItem) {
107
+ return
108
+ }
109
+
110
+ if (this.currentPage < this.totalPages) {
111
+ this.showMoreItem.hidden = false
112
+ } else {
113
+ this.showMoreItem.hidden = true
114
+ }
115
+ }
116
+
117
+ private parseHTML(document: Document, html: string): DocumentFragment {
118
+ const template = document.createElement('template')
119
+ // eslint-disable-next-line github/no-inner-html
120
+ template.innerHTML = html
121
+ return document.importNode(template.content, true)
122
+ }
123
+ }
124
+
125
+ declare global {
126
+ interface Window {
127
+ NavListElement: typeof NavListElement
128
+ }
129
+ }
@@ -1,4 +1,5 @@
1
1
  import './alpha/modal_dialog';
2
+ import './alpha/nav_list';
2
3
  import './alpha/toggle_switch';
3
4
  import './alpha/tool_tip';
4
5
  import './beta/auto_complete/auto_complete';
@@ -1,4 +1,5 @@
1
1
  import './alpha/modal_dialog';
2
+ import './alpha/nav_list';
2
3
  import './alpha/toggle_switch';
3
4
  import './alpha/tool_tip';
4
5
  import './beta/auto_complete/auto_complete';
@@ -1,2 +1,3 @@
1
1
  /* CSS component styles here */
2
2
  @import "./beta/button.pcss";
3
+ @import "./alpha/action_list/action-list.pcss";
@@ -1,4 +1,5 @@
1
1
  import './alpha/modal_dialog'
2
+ import './alpha/nav_list'
2
3
  import './alpha/toggle_switch'
3
4
  import './alpha/tool_tip'
4
5
  import './beta/auto_complete/auto_complete'
@@ -0,0 +1,11 @@
1
+ /* active indicator line for navlist items */
2
+ @define-mixin activeIndicatorLine $padding-left: calc(-1 * var(--base-size-8, 8px)) {
3
+ position: absolute;
4
+ top: calc(50% - 12px);
5
+ left: $padding-left;
6
+ width: var(--base-size-4, 4px);
7
+ height: var(--base-size-24, 24px);
8
+ content: '';
9
+ background: var(--color-accent-fg);
10
+ border-radius: var(--primer-borderRadius-medium, 6px);
11
+ }
@@ -5,7 +5,7 @@ module Primer
5
5
  module VERSION
6
6
  MAJOR = 0
7
7
  MINOR = 0
8
- PATCH = 96
8
+ PATCH = 97
9
9
 
10
10
  STRING = [MAJOR, MINOR, PATCH].join(".")
11
11
  end
data/lib/tasks/docs.rake CHANGED
@@ -88,7 +88,14 @@ namespace :docs do
88
88
  Primer::Alpha::TabNav,
89
89
  Primer::Alpha::TabPanels,
90
90
  Primer::Alpha::Tooltip,
91
- Primer::Alpha::ToggleSwitch
91
+ Primer::Alpha::ToggleSwitch,
92
+ Primer::Alpha::ActionList,
93
+ Primer::Alpha::NavList,
94
+ Primer::Alpha::NavList::Item,
95
+ Primer::Alpha::NavList::Section,
96
+ Primer::Alpha::ActionList::Divider,
97
+ Primer::Alpha::ActionList::Heading,
98
+ Primer::Alpha::ActionList::Item
92
99
  ]
93
100
 
94
101
  js_components = [
@@ -104,7 +111,23 @@ namespace :docs do
104
111
  Primer::Alpha::Tooltip,
105
112
  Primer::ButtonComponent,
106
113
  Primer::IconButton,
107
- Primer::LinkComponent
114
+ Primer::LinkComponent,
115
+ Primer::Alpha::ToggleSwitch,
116
+ Primer::Alpha::ActionList,
117
+ Primer::Alpha::NavList,
118
+ Primer::Alpha::NavList::Section
119
+ ]
120
+
121
+ components_without_examples = [
122
+ # ActionList is a base component that should not be used by itself
123
+ Primer::Alpha::ActionList,
124
+ Primer::Alpha::ActionList::Divider,
125
+ Primer::Alpha::ActionList::Heading,
126
+ Primer::Alpha::ActionList::Item,
127
+
128
+ # Examples can be seen in the NavList docs
129
+ Primer::Alpha::NavList::Item,
130
+ Primer::Alpha::NavList::Section
108
131
  ]
109
132
 
110
133
  all_components = Primer::Component.descendants - [Primer::BaseComponent]
@@ -212,7 +235,9 @@ namespace :docs do
212
235
  args_for_components << component_args
213
236
 
214
237
  # Slots V2 docs
215
- slot_v2_methods = documentation.meths.select { |x| x[:renders_one] || x[:renders_many] }
238
+ slot_v2_methods = documentation.meths.select do |mtd|
239
+ (mtd[:renders_one] || mtd[:renders_many]) && mtd.tag(:private).nil?
240
+ end
216
241
 
217
242
  if slot_v2_methods.any?
218
243
  f.puts
@@ -220,7 +245,7 @@ namespace :docs do
220
245
 
221
246
  slot_v2_methods.each do |slot_documentation|
222
247
  f.puts
223
- f.puts("### `#{slot_documentation.name.to_s.capitalize}`")
248
+ f.puts("### `#{slot_documentation.name}`")
224
249
 
225
250
  if slot_documentation.base_docstring.to_s.present?
226
251
  f.puts
@@ -240,26 +265,30 @@ namespace :docs do
240
265
  end
241
266
  end
242
267
 
243
- errors << { component.name => { example: "No examples found" } } unless initialize_method.tags(:example).any?
244
-
245
- f.puts
246
- f.puts("## Examples")
268
+ example_tags = initialize_method.tags(:example)
247
269
 
248
- initialize_method.tags(:example).each do |tag|
249
- name, description, code = parse_example_tag(tag)
270
+ if example_tags.any?
250
271
  f.puts
251
- f.puts("### #{name}")
252
- if description
272
+ f.puts("## Examples")
273
+
274
+ example_tags.each do |tag|
275
+ name, description, code = parse_example_tag(tag)
276
+ f.puts
277
+ f.puts("### #{name}")
278
+ if description
279
+ f.puts
280
+ f.puts(view_context.render(inline: description.squish))
281
+ end
253
282
  f.puts
254
- f.puts(view_context.render(inline: description.squish))
283
+ html = view_context.render(inline: code)
284
+ f.puts("<Example src=\"#{html.tr('"', "\'").delete("\n")}\" />")
285
+ f.puts
286
+ f.puts("```erb")
287
+ f.puts(code.to_s)
288
+ f.puts("```")
255
289
  end
256
- f.puts
257
- html = view_context.render(inline: code)
258
- f.puts("<Example src=\"#{html.tr('"', "\'").delete("\n")}\" />")
259
- f.puts
260
- f.puts("```erb")
261
- f.puts(code.to_s)
262
- f.puts("```")
290
+ else
291
+ errors << { component.name => { example: "No examples found" } } unless components_without_examples.include?(component)
263
292
  end
264
293
  end
265
294
  end
@@ -454,12 +483,12 @@ namespace :docs do
454
483
  end
455
484
 
456
485
  def docs_metadata(component)
457
- (status_module, short_name) = status_module_and_short_name(component)
486
+ status_module, short_name, class_name = status_module_and_short_name(component)
458
487
  status_path = status_module.nil? ? "" : "#{status_module}/"
459
488
  status = component.status.to_s
460
489
 
461
490
  {
462
- title: short_name,
491
+ title: class_name,
463
492
  component_id: short_name.underscore,
464
493
  status: status.capitalize,
465
494
  source: source_url(component),
@@ -44,10 +44,10 @@ module YARD
44
44
  end
45
45
 
46
46
  def link_to_component(component)
47
- (status_module, short_name) = status_module_and_short_name(component)
47
+ status_module, short_name, class_name = status_module_and_short_name(component)
48
48
  status_path = status_module.nil? ? "" : "#{status_module}/"
49
49
 
50
- "[#{short_name}](/components/#{status_path}#{short_name.downcase})"
50
+ "[#{class_name}](/components/#{status_path}#{short_name.downcase})"
51
51
  end
52
52
 
53
53
  def link_to_octicons
@@ -62,7 +62,7 @@ module YARD
62
62
  name_with_status = component.name.gsub(/Primer::|Component/, "")
63
63
 
64
64
  m = name_with_status.match(/(?<status>Beta|Alpha|Deprecated)?(?<_colons>::)?(?<name>.*)/)
65
- [m[:status]&.downcase, m[:name].gsub("::", "")]
65
+ [m[:status]&.downcase, m[:name].gsub("::", ""), m[:name]]
66
66
  end
67
67
 
68
68
  def pretty_value(val)