primer_view_components 0.0.122 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -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/item.rb +11 -0
  8. data/app/components/primer/alpha/action_list.css.json +41 -0
  9. data/app/components/primer/alpha/auto_complete.css.json +11 -0
  10. data/app/components/primer/alpha/banner.css.json +14 -0
  11. data/app/components/primer/alpha/button_marketing.css.json +10 -0
  12. data/app/components/primer/alpha/dialog.css.json +63 -0
  13. data/app/components/primer/alpha/dropdown.css.json +21 -0
  14. data/app/components/primer/alpha/layout.css.json +27 -0
  15. data/app/components/primer/alpha/menu.css.json +11 -0
  16. data/app/components/primer/alpha/nav_list/item.rb +7 -1
  17. data/app/components/primer/alpha/nav_list/section.rb +5 -5
  18. data/app/components/primer/alpha/nav_list.d.ts +6 -3
  19. data/app/components/primer/alpha/nav_list.js +98 -6
  20. data/app/components/primer/alpha/nav_list.rb +7 -2
  21. data/app/components/primer/alpha/nav_list.ts +109 -3
  22. data/app/components/primer/alpha/overlay/body.rb +26 -0
  23. data/app/components/primer/alpha/overlay/footer.rb +41 -0
  24. data/app/components/primer/alpha/overlay/header.html.erb +15 -0
  25. data/app/components/primer/alpha/overlay/header.rb +47 -0
  26. data/app/components/primer/alpha/overlay.css +1 -0
  27. data/app/components/primer/alpha/overlay.css.json +11 -0
  28. data/app/components/primer/alpha/overlay.css.map +1 -0
  29. data/app/components/primer/alpha/overlay.html.erb +11 -0
  30. data/app/components/primer/alpha/overlay.pcss +14 -0
  31. data/app/components/primer/alpha/overlay.rb +194 -0
  32. data/app/components/primer/alpha/segmented_control.css.json +15 -0
  33. data/app/components/primer/alpha/tab_nav.css.json +10 -0
  34. data/app/components/primer/alpha/text_field.css.json +38 -0
  35. data/app/components/primer/alpha/toggle_switch.css.json +16 -0
  36. data/app/components/primer/alpha/underline_nav.css.json +13 -0
  37. data/app/components/primer/anchored_position.d.ts +27 -0
  38. data/app/components/primer/anchored_position.js +149 -0
  39. data/app/components/primer/anchored_position.ts +167 -0
  40. data/app/components/primer/beta/avatar.css.json +14 -0
  41. data/app/components/primer/beta/avatar_stack.css.json +9 -0
  42. data/app/components/primer/beta/blankslate.css.json +12 -0
  43. data/app/components/primer/beta/border_box.css.json +32 -0
  44. data/app/components/primer/beta/breadcrumbs.css.json +4 -0
  45. data/app/components/primer/beta/button.css.json +22 -0
  46. data/app/components/primer/beta/counter.css.json +6 -0
  47. data/app/components/primer/beta/flash.css.json +15 -0
  48. data/app/components/primer/beta/flash.html.erb +1 -2
  49. data/app/components/primer/beta/label.css.json +20 -0
  50. data/app/components/primer/beta/link.css.json +8 -0
  51. data/app/components/primer/beta/popover.css.json +18 -0
  52. data/app/components/primer/beta/progress_bar.css.json +6 -0
  53. data/app/components/primer/beta/state.css.json +10 -0
  54. data/app/components/primer/beta/subhead.css.json +8 -0
  55. data/app/components/primer/beta/timeline_item.css.json +9 -0
  56. data/app/components/primer/beta/truncate.css.json +6 -0
  57. data/app/components/primer/component.rb +1 -1
  58. data/app/components/primer/primer.d.ts +2 -0
  59. data/app/components/primer/primer.js +2 -0
  60. data/app/components/primer/primer.pcss +3 -0
  61. data/app/components/primer/primer.ts +2 -0
  62. data/app/components/primer/truncate.css.json +7 -0
  63. data/app/lib/primer/css/layout.css.json +263 -0
  64. data/app/lib/primer/css/utilities.css.json +1636 -0
  65. data/lib/primer/view_components/linters/base_linter.rb +1 -1
  66. data/lib/primer/view_components/linters/disallow_component_css_counter.rb +30 -0
  67. data/lib/primer/view_components/version.rb +2 -2
  68. data/lib/primer/yard/component_manifest.rb +1 -0
  69. data/previews/primer/alpha/overlay_preview/middle_of_page.html.erb +17 -0
  70. data/previews/primer/alpha/overlay_preview.rb +107 -0
  71. data/static/arguments.json +104 -0
  72. data/static/audited_at.json +4 -0
  73. data/static/classes.json +311 -0
  74. data/static/constants.json +102 -0
  75. data/static/previews.json +21 -0
  76. data/static/statuses.json +4 -0
  77. metadata +19 -2
@@ -2,8 +2,9 @@
2
2
  import {controller, target, targets} from '@github/catalyst'
3
3
 
4
4
  @controller
5
- class NavListElement extends HTMLElement {
5
+ export class NavListElement extends HTMLElement {
6
6
  @target list: HTMLElement
7
+ @targets items: HTMLElement[]
7
8
  @target showMoreItem: HTMLElement
8
9
  @targets focusMarkers: HTMLElement[]
9
10
 
@@ -40,6 +41,43 @@ class NavListElement extends HTMLElement {
40
41
  return this.showMoreItem.getAttribute('src') || ''
41
42
  }
42
43
 
44
+ selectItemById(itemId: string | null): boolean {
45
+ if (!itemId) return false
46
+
47
+ const selectedItem = this.#findSelectedNavItemById(itemId)
48
+
49
+ if (selectedItem) {
50
+ this.#select(selectedItem)
51
+ return true
52
+ }
53
+
54
+ return false
55
+ }
56
+
57
+ selectItemByHref(href: string | null): boolean {
58
+ if (!href) return false
59
+
60
+ const selectedItem = this.#findSelectedNavItemByHref(href)
61
+
62
+ if (selectedItem) {
63
+ this.#select(selectedItem)
64
+ return true
65
+ }
66
+
67
+ return false
68
+ }
69
+
70
+ selectItemByCurrentLocation(): boolean {
71
+ const selectedItem = this.#findSelectedNavItemByCurrentLocation()
72
+
73
+ if (selectedItem) {
74
+ this.#select(selectedItem)
75
+ return true
76
+ }
77
+
78
+ return false
79
+ }
80
+
43
81
  // expand collapsible item onClick
44
82
  expandItem(item: HTMLElement) {
45
83
  item.nextElementSibling?.removeAttribute('data-hidden')
@@ -95,7 +133,7 @@ class NavListElement extends HTMLElement {
95
133
  this.currentPage--
96
134
  return
97
135
  }
98
- const fragment = this.parseHTML(document, html)
136
+ const fragment = this.#parseHTML(document, html)
99
137
  fragment?.querySelector('li > a')?.setAttribute('data-targets', 'nav-list.focusMarkers')
100
138
  this.list.insertBefore(fragment, this.showMoreItem)
101
139
  this.focusMarkers.pop()?.focus()
@@ -114,12 +152,80 @@ class NavListElement extends HTMLElement {
114
152
  }
115
153
  }
116
154
 
117
- private parseHTML(document: Document, html: string): DocumentFragment {
155
+ #parseHTML(document: Document, html: string): DocumentFragment {
118
156
  const template = document.createElement('template')
119
157
  // eslint-disable-next-line github/no-inner-html
120
158
  template.innerHTML = html
121
159
  return document.importNode(template.content, true)
122
160
  }
161
+
162
+ #findSelectedNavItemById(itemId: string): HTMLElement | null {
163
+ // First we compare the selected link to data-item-id for each nav item
164
+ for (const navItem of this.items) {
165
+ if (navItem.classList.contains('ActionListItem--hasSubItem')) {
166
+ continue
167
+ }
168
+
169
+ const keys = navItem.getAttribute('data-item-id')?.split(' ') || []
170
+
171
+ if (keys.includes(itemId)) {
172
+ return navItem
173
+ }
174
+ }
175
+
176
+ return null
177
+ }
178
+
179
+ #findSelectedNavItemByHref(href: string): HTMLElement | null {
180
+ // If we didn't find a match, we compare the selected link to the href of each nav item
181
+ const selectedNavItem = this.querySelector<HTMLAnchorElement>(`.ActionListContent[href="${href}"]`)
182
+ if (selectedNavItem) {
183
+ return selectedNavItem.closest('.ActionListItem')
184
+ }
185
+
186
+ return null
187
+ }
188
+
189
+ #findSelectedNavItemByCurrentLocation(): HTMLElement | null {
190
+ return this.#findSelectedNavItemByHref(window.location.pathname)
191
+ }
192
+
193
+ #select(navItem: HTMLElement) {
194
+ const currentlySelectedItem = this.querySelector('.ActionListItem--navActive') as HTMLElement
195
+ if (currentlySelectedItem) this.#deselect(currentlySelectedItem)
196
+
197
+ navItem.classList.add('ActionListItem--navActive')
198
+
199
+ const parentMenu = this.#findParentMenu(navItem)
200
+
201
+ if (parentMenu) {
202
+ this.expandItem(parentMenu)
203
+ parentMenu.classList.add('ActionListContent--hasActiveSubItem')
204
+ }
205
+ }
206
+
207
+ #deselect(navItem: HTMLElement) {
208
+ navItem.classList.remove('ActionListItem--navActive')
209
+
210
+ const parentMenu = this.#findParentMenu(navItem)
211
+
212
+ if (parentMenu) {
213
+ this.collapseItem(parentMenu)
214
+ parentMenu.classList.remove('ActionListContent--hasActiveSubItem')
215
+ }
216
+ }
217
+
218
+ #findParentMenu(navItem: HTMLElement): HTMLElement | null {
219
+ if (!navItem.classList.contains('ActionListItem--subItem')) return null
220
+
221
+ const parent = navItem.closest('li.ActionListItem--hasSubItem')?.querySelector('button.ActionListContent')
222
+
223
+ if (parent) {
224
+ return parent as HTMLElement
225
+ } else {
226
+ return null
227
+ }
228
+ }
123
229
  }
124
230
 
125
231
  declare global {
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ class Overlay
6
+ # A `Overlay::Body` is a compositional component, used to render the
7
+ # Body of an overlay. See <%= link_to_component(Primer::Alpha::Overlay) %>.
8
+ class Body < Primer::Component
9
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
10
+ def initialize(padding: DEFAULT_PADDING, **system_arguments)
11
+ @system_arguments = deny_tag_argument(**system_arguments)
12
+ @system_arguments[:tag] = :div
13
+ @system_arguments[:classes] = class_names(
14
+ "Overlay-body",
15
+ PADDING_MAPPINGS[fetch_or_fallback(PADDING_OPTIONS, padding, DEFAULT_PADDING)],
16
+ system_arguments[:classes]
17
+ )
18
+ end
19
+
20
+ def call
21
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ class Overlay
6
+ DEFAULT_ALIGN_CONTENT = :end
7
+ ALIGN_CONTENT_MAPPINGS = {
8
+ :start => "Overlay-footer--alignStart",
9
+ :center => "Overlay-footer--alignCenter",
10
+ DEFAULT_ALIGN_CONTENT => "Overlay-footer--alignEnd"
11
+ }.freeze
12
+ ALIGN_CONTENT_OPTIONS = ALIGN_CONTENT_MAPPINGS.keys
13
+
14
+ # A `Overlay::Footer` is a compositional component, used to render the
15
+ # Footer of an overlay. See <%= link_to_component(Primer::Alpha::Overlay) %>.
16
+ class Footer < Primer::Component
17
+ # @param show_divider [Boolean] Show a divider between the footer and body.
18
+ # @param align_content [Symbol] The alginment of contents. <%= one_of(Primer::Alpha::Overlay::ALIGN_CONTENT_OPTIONS) %>
19
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
20
+ def initialize(
21
+ show_divider: false,
22
+ align_content: DEFAULT_ALIGN_CONTENT,
23
+ **system_arguments
24
+ )
25
+ @system_arguments = deny_tag_argument(**system_arguments)
26
+ @system_arguments[:tag] = :div
27
+ @system_arguments[:classes] = class_names(
28
+ "Overlay-footer",
29
+ ALIGN_CONTENT_MAPPINGS[fetch_or_fallback(ALIGN_CONTENT_OPTIONS, align_content, DEFAULT_ALIGN_CONTENT)],
30
+ { "Overlay-footer--divided": show_divider },
31
+ system_arguments[:classes]
32
+ )
33
+ end
34
+
35
+ def call
36
+ render(Primer::BaseComponent.new(**@system_arguments)) { content }
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,15 @@
1
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
2
+ <div class="Overlay-headerContentWrap">
3
+ <div class="Overlay-titleWrap">
4
+ <h1 class="Overlay-title <% if @visually_hide_title || content.present? %>sr-only<% end %>"><%= @title %></h1>
5
+ <% if content.present? %>
6
+ <%= content %>
7
+ <% elsif @subtitle.present? %>
8
+ <h2 id="<%= @id %>-description" class="Overlay-description"><%= @subtitle %></h2>
9
+ <% end %>
10
+ </div>
11
+ <div class="Overlay-actionWrap">
12
+ <%= render Primer::Beta::CloseButton.new(classes: "Overlay-closeButton", "popoverhidetarget": @id) %>
13
+ </div>
14
+ </div>
15
+ <% end %>
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ class Overlay
6
+ # A `Overlay::Header` is a compositional component, used to render the
7
+ # Header of an overlay. See <%= link_to_component(Primer::Alpha::Overlay) %>.
8
+ class Header < Primer::Component
9
+ DEFAULT_SIZE = :medium
10
+ SIZE_MAPPINGS = {
11
+ DEFAULT_SIZE => nil,
12
+ :large => "Overlay-header--large"
13
+ }.freeze
14
+ SIZE_OPTIONS = SIZE_MAPPINGS.keys
15
+
16
+ # @param title [String] Describes the content of the Overlay.
17
+ # @param subtitle [String] Provides dditional context for the Overlay, also setting the `aria-describedby` attribute.
18
+ # @param size [Symbol] The size of the Header. <%= one_of(Primer::Alpha::Overlay::Header::SIZE_OPTIONS) %>
19
+ # @param divider [Boolean] Show a divider between the header and body.
20
+ # @param visually_hide_title [Boolean] Visually hide the `title` while maintaining a label for assistive technologies.
21
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
22
+ def initialize(
23
+ id:,
24
+ title:,
25
+ subtitle: nil,
26
+ size: DEFAULT_SIZE,
27
+ divider: false,
28
+ visually_hide_title: false,
29
+ **system_arguments
30
+ )
31
+ @id = id
32
+ @title = title
33
+ @subtitle = subtitle
34
+ @visually_hide_title = visually_hide_title
35
+ @system_arguments = deny_tag_argument(**system_arguments)
36
+ @system_arguments[:tag] = :header
37
+ @system_arguments[:classes] = class_names(
38
+ "Overlay-header",
39
+ { "Overlay-header--divided": divider },
40
+ SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)],
41
+ system_arguments[:classes]
42
+ )
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1 @@
1
+ .Overlay[popover]{border-width:0;padding:0;position:absolute}.Overlay[popover]:not(:open){display:none}anchored-position{display:block}
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "alpha/overlay",
3
+ "selectors": [
4
+ ".Overlay[popover]",
5
+ ".Overlay[popover]:not(:open)",
6
+ "anchored-position"
7
+ ],
8
+ "classes": [
9
+ "Overlay"
10
+ ]
11
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["overlay.pcss"],"names":[],"mappings":"AAAA,kBACE,cAAe,CACf,SAAU,CACV,iBACF,CAGA,6BACE,YACF,CAEA,kBACE,aACF","file":"overlay.css","sourcesContent":[".Overlay[popover] {\n border-width: 0;\n padding: 0;\n position: absolute;\n}\n\n/* stylelint-disable-next-line selector-pseudo-class-no-unknown */\n.Overlay[popover]:not(:open) {\n display: none;\n}\n\nanchored-position {\n display: block;\n}\n"]}
@@ -0,0 +1,11 @@
1
+ <%= show_button %>
2
+
3
+ <%= render Primer::BaseComponent.new(**@system_arguments) do %>
4
+ <%= header %>
5
+ <% if content.present? %>
6
+ <%= content %>
7
+ <% else %>
8
+ <%= body %>
9
+ <%= footer %>
10
+ <% end %>
11
+ <% end %>
@@ -0,0 +1,14 @@
1
+ .Overlay[popover] {
2
+ border-width: 0;
3
+ padding: 0;
4
+ position: absolute;
5
+ }
6
+
7
+ /* stylelint-disable-next-line selector-pseudo-class-no-unknown */
8
+ .Overlay[popover]:not(:open) {
9
+ display: none;
10
+ }
11
+
12
+ anchored-position {
13
+ display: block;
14
+ }
@@ -0,0 +1,194 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Primer
4
+ module Alpha
5
+ # Overlay components codify design patterns related to floating surfaces such
6
+ # as dialogs and menus. They are private components intended to be used by
7
+ # specialized components, and mostly contain presentational logic and
8
+ # behavior.
9
+ #
10
+ # @accessibility
11
+ # - **Overlay Accessible Name**: An overlay should have an accessible name,
12
+ # so screen readers are aware of the purpose of the Overlay when it opens.
13
+ # Give an accessible name setting `:title`. The accessible name will be
14
+ # used as the main heading inside the Overlay.
15
+ # - **Overlay unique id**: A Overlay should be unique. Give a unique id
16
+ # setting `:id`. If no `:id` is given, a default randomize hex id is
17
+ # generated.
18
+ #
19
+ # The combination of both `:title` and `:id` establishes an
20
+ # `aria-labelledby` relationship between the title and the unique id
21
+ # of the Overlay.
22
+ class Overlay < Primer::Component
23
+ DEFAULT_PADDING = :normal
24
+ PADDING_MAPPINGS = {
25
+ DEFAULT_PADDING => nil,
26
+ :condensed => "Overlay-body--paddingCondensed",
27
+ :none => "Overlay-body--paddingNone"
28
+ }.freeze
29
+
30
+ PADDING_OPTIONS = PADDING_MAPPINGS.keys
31
+
32
+ DEFAULT_SIZE = :auto
33
+ SIZE_MAPPINGS = {
34
+ DEFAULT_SIZE => "Overlay--size-auto",
35
+ :small => "Overlay--size-small",
36
+ :medium => "Overlay--size-medium",
37
+ :medium_portrait => "Overlay--size-medium-portrait",
38
+ :large => "Overlay--size-large",
39
+ :xlarge => "Overlay--size-xlarge"
40
+ }.freeze
41
+ SIZE_OPTIONS = SIZE_MAPPINGS.keys
42
+
43
+ DEFAULT_ANCHOR_ALIGN = :start
44
+ ANCHOR_ALIGN_OPTIONS = [DEFAULT_ANCHOR_ALIGN, :center, :end].freeze
45
+
46
+ DEFAULT_ANCHOR_OFFSET = :normal
47
+ ANCHOR_OFFSET_OPTIONS = [DEFAULT_ANCHOR_OFFSET, :spacious].freeze
48
+
49
+ DEFAULT_ANCHOR_SIDE = :outside_bottom
50
+ ANCHOR_SIDE_MAPPINGS = {
51
+ :inside_top => "inside-top",
52
+ :inside_bottom => "inside-bottom",
53
+ :inside_left => "inside-left",
54
+ :inside_right => "inside-right",
55
+ :inside_center => "inside-center",
56
+ :outside_top => "outside-top",
57
+ DEFAULT_ANCHOR_SIDE => "outside-bottom",
58
+ :outside_left => "outside-left",
59
+ :outside_right => "outside-right"
60
+ }.freeze
61
+ ANCHOR_SIDE_OPTIONS = ANCHOR_SIDE_MAPPINGS.keys
62
+
63
+ DEFAULT_POPOVER = :auto
64
+ POPOVER_OPTIONS = [DEFAULT_POPOVER, :manual].freeze
65
+
66
+ ROLE_OPTIONS = [:dialog, :menu].freeze
67
+
68
+ # Optional button to open the Overlay.
69
+ #
70
+ # @param system_arguments [Hash] The same arguments as <%= link_to_component(Primer::ButtonComponent) %>.
71
+ renders_one :show_button, lambda { |**system_arguments|
72
+ system_arguments[:classes] = class_names(
73
+ system_arguments[:classes]
74
+ )
75
+ system_arguments[:id] = "overlay-show-#{@system_arguments[:id]}"
76
+ system_arguments["popovertoggletarget"] = @system_arguments[:id]
77
+ system_arguments[:data] = (system_arguments[:data] || {}).merge({ "show-dialog-id": @system_arguments[:id] })
78
+ Primer::Beta::Button.new(**system_arguments)
79
+ }
80
+
81
+ # Header content.
82
+ #
83
+ # @param divider [Boolean] Show a divider between the header and body.
84
+ # @param visually_hide_title [Boolean] Visually hide the `title` while maintaining a label for assistive technologies.
85
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
86
+ renders_one :header, lambda { |divider: false, size: :medium, visually_hide_title: @visually_hide_title, **system_arguments|
87
+ Primer::Alpha::Overlay::Header.new(
88
+ id: @id,
89
+ title: @title,
90
+ subtitle: @subtitle,
91
+ size: size,
92
+ divider: divider,
93
+ visually_hide_title: visually_hide_title,
94
+ **system_arguments
95
+ )
96
+ }
97
+
98
+ # Required body content.
99
+ #
100
+ # @param padding [Symbol] The padding. <%= one_of(Primer::Alpha::Overlay::PADDING_OPTIONS) %>
101
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
102
+ renders_one :body, lambda { |padding: @padding, **system_arguments|
103
+ Primer::Alpha::Overlay::Body.new(
104
+ padding: padding,
105
+ **system_arguments
106
+ )
107
+ }
108
+
109
+ # Footer content.
110
+ #
111
+ # @param show_divider [Boolean] Show a divider between the footer and body.
112
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
113
+ renders_one :footer, "Footer"
114
+
115
+ # @example Overlay with Cancel and Submit buttons
116
+ # @description
117
+ # An ID is provided which enables wiring of the open and close buttons to the Overlay.
118
+ # @code
119
+ # <%= render(Primer::Alpha::Overlay.new(
120
+ # title: "Overlay Example",
121
+ # id: "my-Overlay",
122
+ # role: :dialog,
123
+ # )) do |d| %>
124
+ # <% d.with_show_button { "Show Overlay" } %>
125
+ # <% d.with_body do %>
126
+ # <p>Some content</p>
127
+ # <% end %>
128
+ # <% end %>
129
+ # @param id [String] The id of the Overlay.
130
+ # @param title [String] Describes the content of the Overlay.
131
+ # @param subtitle [String] Provides dditional context for the Overlay, also setting the `aria-describedby` attribute.
132
+ # @param popover [Symbol] The popover behaviour. <%= one_of(Primer::Alpha::Overlay::POPOVER_OPTIONS) %>
133
+ # @param popover [Symbol] The popover behaviour. <%= one_of(Primer::Alpha::Overlay::POPOVER_OPTIONS) %>
134
+ # @param size [Symbol] The size of the Overlay. <%= one_of(Primer::Alpha::Overlay::SIZE_OPTIONS) %>
135
+ # @param padding [Symbol] The padding given to the Overlay body. <%= one_of(Primer::Alpha::Overlay::PADDING_OPTIONS) %>
136
+ # @param anchor [String] An ID of the element to anchor onto. Defaults to the `show_button`.
137
+ # @param anchor_align [Symbol] The anchor alignment of the Overlay. <%= one_of(Primer::Alpha::Overlay::ANCHOR_ALIGN_OPTIONS) %>
138
+ # @param anchor_side [Symbol] The side to anchor the Overlay to. <%= one_of(Primer::Alpha::Overlay::ANCHOR_SIDE_OPTIONS) %>
139
+ # @param anchor_offset [Symbol] The anchor offset to give the Overlay. <%= one_of(Primer::Alpha::Overlay::ANCHOR_OFFSET_OPTIONS) %>
140
+ # @param allow_out_of_bounds [Boolean] Allow the Overlay to overflow its container.
141
+ # @param visually_hide_title [Boolean] If true will hide the heading title, while still making it available to Screen Readers.
142
+ # @param role [String] The ARIA role. <%= one_of(Primer::Alpha::Overlay::ROLE_OPTIONS) %>
143
+ # @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
144
+ def initialize(
145
+ title:,
146
+ role:,
147
+ subtitle: nil,
148
+ popover: DEFAULT_POPOVER,
149
+ size: DEFAULT_SIZE,
150
+ padding: DEFAULT_PADDING,
151
+ anchor: nil,
152
+ anchor_align: DEFAULT_ANCHOR_ALIGN,
153
+ anchor_offset: DEFAULT_ANCHOR_OFFSET,
154
+ anchor_side: DEFAULT_ANCHOR_SIDE,
155
+ allow_out_of_bounds: false,
156
+ visually_hide_title: false,
157
+ id: self.class.generate_id,
158
+ **system_arguments
159
+ )
160
+ @system_arguments = deny_tag_argument(**system_arguments)
161
+
162
+ @system_arguments[:role] = fetch_or_fallback(ROLE_OPTIONS, role)
163
+
164
+ @system_arguments[:id] = id.to_s
165
+ @system_arguments[:classes] = class_names(
166
+ "Overlay",
167
+ SIZE_MAPPINGS[fetch_or_fallback(SIZE_OPTIONS, size, DEFAULT_SIZE)],
168
+ "Overlay--motion-scaleFade",
169
+ system_arguments[:classes]
170
+ )
171
+ @system_arguments[:tag] = "anchored-position"
172
+ @system_arguments[:anchor] = anchor || "overlay-show-#{@system_arguments[:id]}"
173
+ @system_arguments[:align] = fetch_or_fallback(ANCHOR_ALIGN_OPTIONS, anchor_align, DEFAULT_ANCHOR_ALIGN)
174
+ @system_arguments[:side] = ANCHOR_SIDE_MAPPINGS[fetch_or_fallback(ANCHOR_SIDE_OPTIONS, anchor_side, DEFAULT_ANCHOR_SIDE)]
175
+ @system_arguments["anchor-offset"] = fetch_or_fallback(ANCHOR_OFFSET_OPTIONS, anchor_offset, DEFAULT_ANCHOR_OFFSET)
176
+ @system_arguments["allow-out-of-bounds"] = true if allow_out_of_bounds
177
+ @id = id.to_s
178
+ @title = title
179
+ @subtitle = subtitle
180
+ @visually_hide_title = visually_hide_title
181
+ @padding = padding
182
+
183
+ @system_arguments[:popover] = popover
184
+ @system_arguments[:aria] ||= {}
185
+ @system_arguments[:aria][:describedby] ||= "#{@id}-description"
186
+ end
187
+
188
+ def before_render
189
+ with_header unless header?
190
+ with_body unless body?
191
+ end
192
+ end
193
+ end
194
+ end
@@ -27,5 +27,20 @@
27
27
  ".SegmentedControl--fullWidth .SegmentedControl-item",
28
28
  ".SegmentedControl--fullWidth .Button--iconOnly",
29
29
  ".SegmentedControl--fullWidth .Button-withTooltip"
30
+ ],
31
+ "classes": [
32
+ "SegmentedControl",
33
+ "SegmentedControl-item",
34
+ "SegmentedControl-item--selected",
35
+ "Button",
36
+ "Button-label",
37
+ "Button--small",
38
+ "Button--iconOnly",
39
+ "Button--medium",
40
+ "Button--large",
41
+ "Button--invisible",
42
+ "Button--invisible-noVisuals",
43
+ "SegmentedControl--fullWidth",
44
+ "Button-withTooltip"
30
45
  ]
31
46
  }
@@ -20,5 +20,15 @@
20
20
  ".tabnav-extra>.octicon",
21
21
  "a.tabnav-extra:hover",
22
22
  ".tabnav-btn"
23
+ ],
24
+ "classes": [
25
+ "tabnav",
26
+ "tabnav-tabs",
27
+ "tabnav-tab",
28
+ "selected",
29
+ "octicon",
30
+ "Counter",
31
+ "tabnav-extra",
32
+ "tabnav-btn"
23
33
  ]
24
34
  }
@@ -130,5 +130,43 @@
130
130
  "input.FormControl-radio[type=radio]:checked",
131
131
  "input.FormControl-radio[type=radio]:checked:disabled",
132
132
  "input.FormControl-radio[type=radio]:focus-visible"
133
+ ],
134
+ "classes": [
135
+ "FormControl",
136
+ "FormControl--fullWidth",
137
+ "FormControl-label",
138
+ "FormControl-caption",
139
+ "FormControl-inlineValidation",
140
+ "FormControl-spacingWrapper",
141
+ "FormControl-horizontalGroup",
142
+ "FormControl-input",
143
+ "FormControl-select",
144
+ "FormControl-textarea",
145
+ "FormControl-small",
146
+ "FormControl-medium",
147
+ "FormControl-large",
148
+ "FormControl-inset",
149
+ "FormControl-monospace",
150
+ "FormControl-error",
151
+ "FormControl-success",
152
+ "FormControl-warning",
153
+ "FormControl-toggleSwitchInput",
154
+ "FormControl-input-wrap",
155
+ "FormControl-input-leadingVisualWrap",
156
+ "FormControl-input-leadingVisual",
157
+ "FormControl-input-trailingAction",
158
+ "FormControl-input-trailingAction--divider",
159
+ "FormControl-input-wrap--leadingVisual",
160
+ "FormControl-input-wrap--trailingAction",
161
+ "FormControl-input-wrap-trailingAction--divider",
162
+ "FormControl-select-wrap",
163
+ "FormControl-checkbox-wrap",
164
+ "FormControl-radio-wrap",
165
+ "FormControl-checkbox-labelWrap",
166
+ "FormControl-radio-labelWrap",
167
+ "FormControl-check-group-wrap",
168
+ "FormControl-radio-group-wrap",
169
+ "FormControl-checkbox",
170
+ "FormControl-radio"
133
171
  ]
134
172
  }
@@ -36,5 +36,21 @@
36
36
  ".ToggleSwitch-statusOff",
37
37
  ".ToggleSwitch--statusAtEnd",
38
38
  ".ToggleSwitch--statusAtEnd .ToggleSwitch-status"
39
+ ],
40
+ "classes": [
41
+ "ToggleSwitch",
42
+ "ToggleSwitch--checked",
43
+ "ToggleSwitch-statusOn",
44
+ "ToggleSwitch-statusOff",
45
+ "ToggleSwitch-track",
46
+ "ToggleSwitch-knob",
47
+ "ToggleSwitch-lineIcon",
48
+ "ToggleSwitch-circleIcon",
49
+ "ToggleSwitch-icons",
50
+ "ToggleSwitch-status",
51
+ "ToggleSwitch-statusIcon",
52
+ "ToggleSwitch--small",
53
+ "ToggleSwitch--disabled",
54
+ "ToggleSwitch--statusAtEnd"
39
55
  ]
40
56
  }
@@ -24,5 +24,18 @@
24
24
  ".UnderlineNav--full .UnderlineNav-body",
25
25
  ".UnderlineNav-octicon",
26
26
  ".UnderlineNav-container"
27
+ ],
28
+ "classes": [
29
+ "UnderlineNav",
30
+ "Counter",
31
+ "Counter--primary",
32
+ "UnderlineNav-body",
33
+ "UnderlineNav-item",
34
+ "selected",
35
+ "UnderlineNav--right",
36
+ "UnderlineNav-actions",
37
+ "UnderlineNav--full",
38
+ "UnderlineNav-octicon",
39
+ "UnderlineNav-container"
27
40
  ]
28
41
  }
@@ -0,0 +1,27 @@
1
+ import type { AnchorAlignment, AnchorSide, PositionSettings } from '@primer/behaviors';
2
+ export default class AnchoredPositionElement extends HTMLElement implements PositionSettings {
3
+ #private;
4
+ get align(): AnchorAlignment;
5
+ set align(value: AnchorAlignment);
6
+ get side(): AnchorSide;
7
+ set side(value: AnchorSide);
8
+ get anchorOffset(): number;
9
+ set anchorOffset(value: number | 'normal' | 'spacious');
10
+ get anchor(): string;
11
+ set anchor(value: string);
12
+ get anchorElement(): HTMLElement | null;
13
+ set anchorElement(value: HTMLElement | null);
14
+ get alignmentOffset(): number;
15
+ set alignmentOffset(value: number);
16
+ get allowOutOfBounds(): boolean;
17
+ set allowOutOfBounds(value: boolean);
18
+ connectedCallback(): void;
19
+ static observedAttributes: string[];
20
+ attributeChangedCallback(): void;
21
+ update(): void;
22
+ }
23
+ declare global {
24
+ interface Window {
25
+ AnchoredPositionElement: typeof AnchoredPositionElement;
26
+ }
27
+ }