primer_view_components 0.0.96 → 0.0.97

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.
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)