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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -0
- data/app/assets/javascripts/primer_view_components.js +1 -1
- data/app/assets/javascripts/primer_view_components.js.map +1 -1
- data/app/assets/styles/primer_view_components.css +2 -2
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/action_list/item.rb +11 -0
- data/app/components/primer/alpha/action_list.css.json +41 -0
- data/app/components/primer/alpha/auto_complete.css.json +11 -0
- data/app/components/primer/alpha/banner.css.json +14 -0
- data/app/components/primer/alpha/button_marketing.css.json +10 -0
- data/app/components/primer/alpha/dialog.css.json +63 -0
- data/app/components/primer/alpha/dropdown.css.json +21 -0
- data/app/components/primer/alpha/layout.css.json +27 -0
- data/app/components/primer/alpha/menu.css.json +11 -0
- data/app/components/primer/alpha/nav_list/item.rb +7 -1
- data/app/components/primer/alpha/nav_list/section.rb +5 -5
- data/app/components/primer/alpha/nav_list.d.ts +6 -3
- data/app/components/primer/alpha/nav_list.js +98 -6
- data/app/components/primer/alpha/nav_list.rb +7 -2
- data/app/components/primer/alpha/nav_list.ts +109 -3
- data/app/components/primer/alpha/overlay/body.rb +26 -0
- data/app/components/primer/alpha/overlay/footer.rb +41 -0
- data/app/components/primer/alpha/overlay/header.html.erb +15 -0
- data/app/components/primer/alpha/overlay/header.rb +47 -0
- data/app/components/primer/alpha/overlay.css +1 -0
- data/app/components/primer/alpha/overlay.css.json +11 -0
- data/app/components/primer/alpha/overlay.css.map +1 -0
- data/app/components/primer/alpha/overlay.html.erb +11 -0
- data/app/components/primer/alpha/overlay.pcss +14 -0
- data/app/components/primer/alpha/overlay.rb +194 -0
- data/app/components/primer/alpha/segmented_control.css.json +15 -0
- data/app/components/primer/alpha/tab_nav.css.json +10 -0
- data/app/components/primer/alpha/text_field.css.json +38 -0
- data/app/components/primer/alpha/toggle_switch.css.json +16 -0
- data/app/components/primer/alpha/underline_nav.css.json +13 -0
- data/app/components/primer/anchored_position.d.ts +27 -0
- data/app/components/primer/anchored_position.js +149 -0
- data/app/components/primer/anchored_position.ts +167 -0
- data/app/components/primer/beta/avatar.css.json +14 -0
- data/app/components/primer/beta/avatar_stack.css.json +9 -0
- data/app/components/primer/beta/blankslate.css.json +12 -0
- data/app/components/primer/beta/border_box.css.json +32 -0
- data/app/components/primer/beta/breadcrumbs.css.json +4 -0
- data/app/components/primer/beta/button.css.json +22 -0
- data/app/components/primer/beta/counter.css.json +6 -0
- data/app/components/primer/beta/flash.css.json +15 -0
- data/app/components/primer/beta/flash.html.erb +1 -2
- data/app/components/primer/beta/label.css.json +20 -0
- data/app/components/primer/beta/link.css.json +8 -0
- data/app/components/primer/beta/popover.css.json +18 -0
- data/app/components/primer/beta/progress_bar.css.json +6 -0
- data/app/components/primer/beta/state.css.json +10 -0
- data/app/components/primer/beta/subhead.css.json +8 -0
- data/app/components/primer/beta/timeline_item.css.json +9 -0
- data/app/components/primer/beta/truncate.css.json +6 -0
- data/app/components/primer/component.rb +1 -1
- data/app/components/primer/primer.d.ts +2 -0
- data/app/components/primer/primer.js +2 -0
- data/app/components/primer/primer.pcss +3 -0
- data/app/components/primer/primer.ts +2 -0
- data/app/components/primer/truncate.css.json +7 -0
- data/app/lib/primer/css/layout.css.json +263 -0
- data/app/lib/primer/css/utilities.css.json +1636 -0
- data/lib/primer/view_components/linters/base_linter.rb +1 -1
- data/lib/primer/view_components/linters/disallow_component_css_counter.rb +30 -0
- data/lib/primer/view_components/version.rb +2 -2
- data/lib/primer/yard/component_manifest.rb +1 -0
- data/previews/primer/alpha/overlay_preview/middle_of_page.html.erb +17 -0
- data/previews/primer/alpha/overlay_preview.rb +107 -0
- data/static/arguments.json +104 -0
- data/static/audited_at.json +4 -0
- data/static/classes.json +311 -0
- data/static/constants.json +102 -0
- data/static/previews.json +21 -0
- data/static/statuses.json +4 -0
- 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
|
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
|
-
|
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 @@
|
|
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,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
|
}
|
@@ -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
|
+
}
|