primer_view_components 0.10.0 → 0.12.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 +36 -0
- data/app/assets/javascripts/app/components/primer/alpha/tool_tip.d.ts +1 -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 +1 -1
- data/app/assets/styles/primer_view_components.css.map +1 -1
- data/app/components/primer/alpha/action_bar/item.rb +7 -4
- data/app/components/primer/alpha/action_bar.rb +2 -2
- data/app/components/primer/alpha/action_bar_element.js +2 -2
- data/app/components/primer/alpha/action_bar_element.ts +2 -2
- data/app/components/primer/alpha/action_menu/action_menu_element.js +168 -84
- data/app/components/primer/alpha/action_menu/action_menu_element.ts +204 -79
- data/app/components/primer/alpha/action_menu/list.rb +0 -2
- data/app/components/primer/alpha/segmented_control/item.html.erb +1 -8
- data/app/components/primer/alpha/segmented_control/item.rb +38 -4
- data/app/components/primer/alpha/segmented_control.css +1 -1
- data/app/components/primer/alpha/segmented_control.css.map +1 -1
- data/app/components/primer/alpha/segmented_control.pcss +3 -1
- data/app/components/primer/alpha/tool_tip.d.ts +1 -0
- data/app/components/primer/alpha/tool_tip.js +17 -2
- data/app/components/primer/alpha/tool_tip.ts +16 -0
- data/app/components/primer/beta/base_button.rb +4 -0
- data/app/components/primer/beta/button.css +1 -1
- data/app/components/primer/beta/button.css.map +1 -1
- data/app/components/primer/beta/button.pcss +6 -2
- data/app/components/primer/focus_group.js +28 -3
- data/app/components/primer/focus_group.ts +27 -1
- data/lib/primer/view_components/version.rb +1 -1
- data/previews/primer/alpha/action_menu_preview/with_actions.html.erb +5 -4
- data/previews/primer/alpha/action_menu_preview.rb +4 -1
- data/previews/primer/alpha/segmented_control_preview.rb +35 -0
- data/previews/primer/alpha/tooltip_preview/tooltip_with_dialog_moving_focus_to_input.html.erb +23 -0
- data/previews/primer/alpha/tooltip_preview.rb +5 -0
- data/previews/primer/beta/button_preview.rb +20 -2
- data/previews/primer/beta/icon_button_preview.rb +3 -0
- data/static/arguments.json +18 -1
- data/static/info_arch.json +107 -3
- data/static/previews.json +65 -0
- metadata +3 -2
@@ -20,6 +20,7 @@ export class ActionMenuElement extends HTMLElement {
|
|
20
20
|
#abortController: AbortController
|
21
21
|
#originalLabel = ''
|
22
22
|
#inputName = ''
|
23
|
+
#invokerBeingClicked = false
|
23
24
|
|
24
25
|
get selectVariant(): SelectVariant {
|
25
26
|
return this.getAttribute('data-select-variant') as SelectVariant
|
@@ -52,7 +53,7 @@ export class ActionMenuElement extends HTMLElement {
|
|
52
53
|
}
|
53
54
|
|
54
55
|
get popoverElement(): HTMLElement | null {
|
55
|
-
return this.invokerElement?.popoverTargetElement || null
|
56
|
+
return (this.invokerElement?.popoverTargetElement as HTMLElement) || null
|
56
57
|
}
|
57
58
|
|
58
59
|
get invokerElement(): HTMLButtonElement | null {
|
@@ -94,8 +95,10 @@ export class ActionMenuElement extends HTMLElement {
|
|
94
95
|
this.addEventListener('click', this, {signal})
|
95
96
|
this.addEventListener('mouseover', this, {signal})
|
96
97
|
this.addEventListener('focusout', this, {signal})
|
98
|
+
this.addEventListener('mousedown', this, {signal})
|
97
99
|
this.#setDynamicLabel()
|
98
100
|
this.#updateInput()
|
101
|
+
this.#softDisableItems()
|
99
102
|
|
100
103
|
if (this.includeFragment) {
|
101
104
|
this.includeFragment.addEventListener('include-fragment-replaced', this, {
|
@@ -104,19 +107,69 @@ export class ActionMenuElement extends HTMLElement {
|
|
104
107
|
}
|
105
108
|
}
|
106
109
|
|
110
|
+
#softDisableItems() {
|
111
|
+
const {signal} = this.#abortController
|
112
|
+
|
113
|
+
for (const item of this.#items) {
|
114
|
+
item.addEventListener('click', this.#potentiallyDisallowActivation.bind(this), {signal})
|
115
|
+
item.addEventListener('keydown', this.#potentiallyDisallowActivation.bind(this), {signal})
|
116
|
+
}
|
117
|
+
}
|
118
|
+
|
119
|
+
#potentiallyDisallowActivation(event: Event) {
|
120
|
+
if (!this.#isActivation(event)) return
|
121
|
+
|
122
|
+
const item = (event.target as HTMLElement).closest(menuItemSelectors.join(','))
|
123
|
+
if (!item) return
|
124
|
+
|
125
|
+
if (item.getAttribute('aria-disabled')) {
|
126
|
+
event.preventDefault()
|
127
|
+
event.stopPropagation()
|
128
|
+
event.stopImmediatePropagation()
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
107
132
|
disconnectedCallback() {
|
108
133
|
this.#abortController.abort()
|
109
134
|
}
|
110
135
|
|
136
|
+
#isKeyboardActivation(event: Event): boolean {
|
137
|
+
return (
|
138
|
+
event instanceof KeyboardEvent &&
|
139
|
+
event.type === 'keydown' &&
|
140
|
+
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
141
|
+
(event.key === 'Enter' || event.key === ' ')
|
142
|
+
)
|
143
|
+
}
|
144
|
+
|
145
|
+
#isMouseActivation(event: Event): boolean {
|
146
|
+
return event instanceof MouseEvent && event.type === 'click'
|
147
|
+
}
|
148
|
+
|
149
|
+
#isActivation(event: Event): boolean {
|
150
|
+
return this.#isMouseActivation(event) || this.#isKeyboardActivation(event)
|
151
|
+
}
|
152
|
+
|
111
153
|
handleEvent(event: Event) {
|
112
|
-
const
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
154
|
+
const targetIsInvoker = this.invokerElement?.contains(event.target as HTMLElement)
|
155
|
+
const eventIsActivation = this.#isActivation(event)
|
156
|
+
|
157
|
+
if (targetIsInvoker && event.type === 'mousedown') {
|
158
|
+
this.#invokerBeingClicked = true
|
159
|
+
return
|
160
|
+
}
|
161
|
+
|
162
|
+
// Prevent safari bug that dismisses menu on mousedown instead of allowing
|
163
|
+
// the click event to propagate to the button
|
164
|
+
if (event.type === 'mousedown') {
|
165
|
+
event.preventDefault()
|
166
|
+
return
|
167
|
+
}
|
168
|
+
|
169
|
+
if (targetIsInvoker && eventIsActivation) {
|
170
|
+
this.#handleInvokerActivated(event)
|
171
|
+
this.#invokerBeingClicked = false
|
172
|
+
return
|
120
173
|
}
|
121
174
|
|
122
175
|
// Ignore events within dialogs within menus
|
@@ -124,84 +177,161 @@ export class ActionMenuElement extends HTMLElement {
|
|
124
177
|
return
|
125
178
|
}
|
126
179
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
this.querySelector<HTMLElement>('.ActionListWrap')!.style.display = 'none'
|
135
|
-
const dialog_controller = new AbortController()
|
136
|
-
const {signal} = dialog_controller
|
137
|
-
const handleDialogClose = () => {
|
138
|
-
dialog_controller.abort()
|
139
|
-
this.querySelector<HTMLElement>('.ActionListWrap')!.style.display = ''
|
140
|
-
if (this.popoverElement?.matches(':popover-open')) {
|
141
|
-
this.popoverElement?.hidePopover()
|
142
|
-
}
|
180
|
+
if (event.type === 'focusout') {
|
181
|
+
if (this.#invokerBeingClicked) return
|
182
|
+
|
183
|
+
// Give the browser time to focus the next element
|
184
|
+
requestAnimationFrame(() => {
|
185
|
+
if (!this.contains(document.activeElement) || document.activeElement === this.invokerElement) {
|
186
|
+
this.#handleFocusOut()
|
143
187
|
}
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
}
|
188
|
+
})
|
189
|
+
|
190
|
+
return
|
148
191
|
}
|
149
192
|
|
150
|
-
|
193
|
+
const item = (event.target as Element).closest(menuItemSelectors.join(','))
|
194
|
+
const targetIsItem = item !== null
|
151
195
|
|
152
|
-
if (
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
setTimeout(() => {
|
163
|
-
if (this.popoverElement?.matches(':popover-open')) {
|
164
|
-
this.popoverElement?.hidePopover()
|
165
|
-
}
|
166
|
-
})
|
196
|
+
if (targetIsItem && eventIsActivation) {
|
197
|
+
const dialogInvoker = item.closest('[data-show-dialog-id]')
|
198
|
+
|
199
|
+
if (dialogInvoker) {
|
200
|
+
const dialog = this.ownerDocument.getElementById(dialogInvoker.getAttribute('data-show-dialog-id') || '')
|
201
|
+
|
202
|
+
if (dialog && this.contains(dialogInvoker) && this.contains(dialog)) {
|
203
|
+
this.#handleDialogItemActivated(event, dialog)
|
204
|
+
return
|
205
|
+
}
|
167
206
|
}
|
168
207
|
|
169
|
-
|
170
|
-
|
171
|
-
|
208
|
+
this.#activateItem(event, item)
|
209
|
+
this.#handleItemActivated(event, item)
|
210
|
+
return
|
211
|
+
}
|
172
212
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
213
|
+
if (event.type === 'include-fragment-replaced') {
|
214
|
+
this.#handleIncludeFragmentReplaced()
|
215
|
+
}
|
216
|
+
}
|
177
217
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
item.setAttribute('aria-checked', 'true')
|
182
|
-
}
|
218
|
+
#handleInvokerActivated(event: Event) {
|
219
|
+
event.preventDefault()
|
220
|
+
event.stopPropagation()
|
183
221
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
222
|
+
if (this.#isOpen()) {
|
223
|
+
this.#hide()
|
224
|
+
} else {
|
225
|
+
this.#show()
|
226
|
+
this.#firstItem?.focus()
|
227
|
+
}
|
228
|
+
}
|
189
229
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
230
|
+
#handleDialogItemActivated(event: Event, dialog: HTMLElement) {
|
231
|
+
this.querySelector<HTMLElement>('.ActionListWrap')!.style.display = 'none'
|
232
|
+
const dialog_controller = new AbortController()
|
233
|
+
const {signal} = dialog_controller
|
234
|
+
const handleDialogClose = () => {
|
235
|
+
dialog_controller.abort()
|
236
|
+
this.querySelector<HTMLElement>('.ActionListWrap')!.style.display = ''
|
237
|
+
if (this.#isOpen()) {
|
238
|
+
this.#hide()
|
194
239
|
}
|
240
|
+
}
|
241
|
+
dialog.addEventListener('close', handleDialogClose, {signal})
|
242
|
+
dialog.addEventListener('cancel', handleDialogClose, {signal})
|
243
|
+
}
|
244
|
+
|
245
|
+
#handleItemActivated(event: Event, item: Element) {
|
246
|
+
// Hide popover after current event loop to prevent changes in focus from
|
247
|
+
// altering the target of the event. Not doing this specifically affects
|
248
|
+
// <a> tags. It causes the event to be sent to the currently focused element
|
249
|
+
// instead of the anchor, which effectively prevents navigation, i.e. it
|
250
|
+
// appears as if hitting enter does nothing. Curiously, clicking instead
|
251
|
+
// works fine.
|
252
|
+
if (this.selectVariant !== 'multiple') {
|
253
|
+
setTimeout(() => {
|
254
|
+
if (this.#isOpen()) {
|
255
|
+
this.#hide()
|
256
|
+
}
|
257
|
+
})
|
258
|
+
}
|
259
|
+
|
260
|
+
// The rest of the code below deals with single/multiple selection behavior, and should not
|
261
|
+
// interfere with events fired by menu items whose behavior is specified outside the library.
|
262
|
+
if (this.selectVariant !== 'multiple' && this.selectVariant !== 'single') return
|
195
263
|
|
196
|
-
|
264
|
+
const ariaChecked = item.getAttribute('aria-checked')
|
265
|
+
const checked = ariaChecked !== 'true'
|
197
266
|
|
198
|
-
|
199
|
-
|
200
|
-
|
267
|
+
if (this.selectVariant === 'single') {
|
268
|
+
// Only check, never uncheck here. Single-select mode does not allow unchecking a checked item.
|
269
|
+
if (checked) {
|
270
|
+
item.setAttribute('aria-checked', 'true')
|
271
|
+
}
|
272
|
+
|
273
|
+
for (const checkedItem of this.querySelectorAll('[aria-checked]')) {
|
274
|
+
if (checkedItem !== item) {
|
275
|
+
checkedItem.setAttribute('aria-checked', 'false')
|
276
|
+
}
|
201
277
|
}
|
278
|
+
|
279
|
+
this.#setDynamicLabel()
|
280
|
+
} else {
|
281
|
+
// multi-select mode allows unchecking a checked item
|
282
|
+
item.setAttribute('aria-checked', `${checked}`)
|
283
|
+
}
|
284
|
+
|
285
|
+
this.#updateInput()
|
286
|
+
|
287
|
+
if (event instanceof KeyboardEvent && event.target instanceof HTMLButtonElement) {
|
288
|
+
// prevent buttons from being clicked twice
|
289
|
+
event.preventDefault()
|
290
|
+
return
|
202
291
|
}
|
203
292
|
}
|
204
293
|
|
294
|
+
#activateItem(event: Event, item: Element) {
|
295
|
+
const eventWillActivateByDefault =
|
296
|
+
(event instanceof MouseEvent && event.type === 'click') ||
|
297
|
+
(event instanceof KeyboardEvent &&
|
298
|
+
event.type === 'keydown' &&
|
299
|
+
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
300
|
+
event.key === 'Enter')
|
301
|
+
|
302
|
+
// if the event will result in activating the current item by default, i.e. is a
|
303
|
+
// mouse click or keyboard enter, bail out
|
304
|
+
if (eventWillActivateByDefault) return
|
305
|
+
|
306
|
+
// otherwise, event will not result in activation by default, so we stop it and
|
307
|
+
// simulate a click
|
308
|
+
event.stopPropagation()
|
309
|
+
const elem = item as HTMLElement
|
310
|
+
elem.click()
|
311
|
+
}
|
312
|
+
|
313
|
+
#handleIncludeFragmentReplaced() {
|
314
|
+
if (this.#firstItem) this.#firstItem.focus()
|
315
|
+
this.#softDisableItems()
|
316
|
+
}
|
317
|
+
|
318
|
+
// Close when focus leaves menu
|
319
|
+
#handleFocusOut() {
|
320
|
+
this.#hide()
|
321
|
+
}
|
322
|
+
|
323
|
+
#show() {
|
324
|
+
this.popoverElement?.showPopover()
|
325
|
+
}
|
326
|
+
|
327
|
+
#hide() {
|
328
|
+
this.popoverElement?.hidePopover()
|
329
|
+
}
|
330
|
+
|
331
|
+
#isOpen() {
|
332
|
+
return this.popoverElement?.matches(':popover-open')
|
333
|
+
}
|
334
|
+
|
205
335
|
#setDynamicLabel() {
|
206
336
|
if (!this.dynamicLabel) return
|
207
337
|
const invokerLabel = this.invokerLabel
|
@@ -261,18 +391,13 @@ export class ActionMenuElement extends HTMLElement {
|
|
261
391
|
}
|
262
392
|
}
|
263
393
|
|
264
|
-
#isActivationKeydown(event: Event): boolean {
|
265
|
-
return (
|
266
|
-
event instanceof KeyboardEvent &&
|
267
|
-
event.type === 'keydown' &&
|
268
|
-
!(event.ctrlKey || event.altKey || event.metaKey || event.shiftKey) &&
|
269
|
-
(event.key === 'Enter' || event.key === ' ')
|
270
|
-
)
|
271
|
-
}
|
272
|
-
|
273
394
|
get #firstItem(): HTMLElement | null {
|
274
395
|
return this.querySelector(menuItemSelectors.join(','))
|
275
396
|
}
|
397
|
+
|
398
|
+
get #items(): HTMLElement[] {
|
399
|
+
return Array.from(this.querySelectorAll(menuItemSelectors.join(',')))
|
400
|
+
}
|
276
401
|
}
|
277
402
|
|
278
403
|
if (!window.customElements.get('action-menu')) {
|
@@ -2,12 +2,5 @@
|
|
2
2
|
"SegmentedControl-item",
|
3
3
|
"SegmentedControl-item--selected": @selected
|
4
4
|
) %>" role="listitem" data-targets="segmented-control.items">
|
5
|
-
|
6
|
-
<%= render Primer::Beta::IconButton.new(icon: @icon, "aria-label": @label, **@system_arguments) %>
|
7
|
-
<% else %>
|
8
|
-
<%= render Primer::Beta::Button.new(**@system_arguments) do |button| %>
|
9
|
-
<% button.with_leading_visual_icon(icon: @icon) unless @icon.nil? %>
|
10
|
-
<%= @label %>
|
11
|
-
<% end %>
|
12
|
-
<% end %>
|
5
|
+
<%= render @button %>
|
13
6
|
</li>
|
@@ -13,16 +13,50 @@ module Primer
|
|
13
13
|
# @param selected [Boolean] Whether the item is selected
|
14
14
|
# @param icon [Symbol] The icon to use
|
15
15
|
# @param hide_labels [Symbol] Whether to only show the icon
|
16
|
-
def initialize(
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def initialize(
|
17
|
+
label:,
|
18
|
+
selected: false,
|
19
|
+
icon: nil,
|
20
|
+
hide_labels: false,
|
21
|
+
**system_arguments
|
22
|
+
)
|
20
23
|
@selected = selected
|
21
24
|
|
22
25
|
@system_arguments = system_arguments
|
23
26
|
@system_arguments[:"data-action"] = "click:segmented-control#select" if system_arguments[:href].nil?
|
24
27
|
@system_arguments[:"aria-current"] = selected
|
25
28
|
@system_arguments[:scheme] = :invisible
|
29
|
+
|
30
|
+
if hide_labels
|
31
|
+
@button = Primer::Beta::IconButton.new(
|
32
|
+
icon: icon,
|
33
|
+
"aria-label": label,
|
34
|
+
**@system_arguments
|
35
|
+
)
|
36
|
+
else
|
37
|
+
@button = Primer::Beta::Button.new(**@system_arguments)
|
38
|
+
@button.with_leading_visual_icon(icon: icon) if icon
|
39
|
+
@button.with_content(label)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# @!parse
|
44
|
+
# # Optional trailing Label
|
45
|
+
# #
|
46
|
+
# # @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Button) %>'s `with_trailing_visual_label` slot.
|
47
|
+
# renders_one(:trailing_visual_label)
|
48
|
+
|
49
|
+
# Optional trailing label.
|
50
|
+
#
|
51
|
+
# @param system_arguments [Hash] The arguments accepted by <%= link_to_component(Primer::Beta::Button) %>'s `with_trailing_visual_label` slot.
|
52
|
+
def with_trailing_visual_label(**system_arguments, &block)
|
53
|
+
@button.with_trailing_visual_label(**system_arguments, &block)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def before_render
|
59
|
+
content
|
26
60
|
end
|
27
61
|
end
|
28
62
|
end
|
@@ -1 +1 @@
|
|
1
|
-
.SegmentedControl{background-color:var(--controlTrack-bgColor-rest,var(--color-segmented-control-bg));border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;list-style:none}.SegmentedControl-item{border:var(--borderWidth-thin,max(1px,.0625rem)) solid #0000;border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;padding:var(--control-xsmall-paddingInline-condensed,.25rem);position:relative}.SegmentedControl-item .Button--invisible:hover:not(:disabled){background-color:var(--controlTrack-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.SegmentedControl-item .Button--invisible:active:not(:disabled){background-color:var(--controlTrack-bgColor-active,var(--color-action-list-item-default-active-bg))}.SegmentedControl-item.SegmentedControl-item--selected{background-color:var(--controlKnob-bgColor-rest,var(--color-segmented-control-button-bg));border-color:var(--controlKnob-borderColor-rest,var(--color-segmented-control-button-selected-border))}.SegmentedControl-item.SegmentedControl-item--selected .Button{font-weight:var(--base-text-weight-semibold,600)}.SegmentedControl-item.SegmentedControl-item--selected .Button:hover{background-color:initial}.SegmentedControl-item.SegmentedControl-item--selected:before{border-color:#0000!important}.SegmentedControl-item.SegmentedControl-item--selected+.SegmentedControl-item:before{border-color:#0000}.SegmentedControl-item .Button-label[data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.SegmentedControl-item:not(:first-child):before{border-left:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-default,var(--color-border-default));content:"";inset:0 0 0 -1px;margin-bottom:var(--control-medium-paddingBlock,.375rem);margin-top:var(--control-medium-paddingBlock,.375rem);position:absolute}.SegmentedControl-item .Button{border:0;color:var(--button-default-fgColor-rest,var(--color-btn-text));font-weight:var(--base-text-weight-normal,400);transition:none}.SegmentedControl-item .Button:focus-visible{border-radius:calc(var(--borderRadius-medium,.375rem) - 5px);outline-offset:calc(var(--control-xsmall-paddingInline-condensed,.25rem) - var(--borderWidth-thin,max(1px, .0625rem)))}.SegmentedControl-item .Button--small{height:calc(var(--control-small-size,1.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-small-paddingInline-condensed,.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--small.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--small.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--medium{height:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-medium-paddingInline-normal,.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--medium.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--medium.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--large{height:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-large-paddingInline-spacious,1rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--large.Button--iconOnly{width:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--large.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-large-size,2.5rem);min-width:var(--control-large-size,2.5rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--iconOnly{padding:initial}.SegmentedControl-item .Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.SegmentedControl--fullWidth{display:flex}.SegmentedControl--fullWidth .SegmentedControl-item{flex:1;justify-content:center}.SegmentedControl--fullWidth .Button--iconOnly,.SegmentedControl--fullWidth .Button-withTooltip{width:100
|
1
|
+
.SegmentedControl{background-color:var(--controlTrack-bgColor-rest,var(--color-segmented-control-bg));border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;list-style:none}.SegmentedControl-item{border:var(--borderWidth-thin,max(1px,.0625rem)) solid #0000;border-radius:var(--borderRadius-medium,.375rem);display:inline-flex;padding:var(--control-xsmall-paddingInline-condensed,.25rem);position:relative}.SegmentedControl-item .Button--invisible:hover:not(:disabled){background-color:var(--controlTrack-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.SegmentedControl-item .Button--invisible:active:not(:disabled){background-color:var(--controlTrack-bgColor-active,var(--color-action-list-item-default-active-bg))}.SegmentedControl-item.SegmentedControl-item--selected{background-color:var(--controlKnob-bgColor-rest,var(--color-segmented-control-button-bg));border-color:var(--controlKnob-borderColor-rest,var(--color-segmented-control-button-selected-border))}.SegmentedControl-item.SegmentedControl-item--selected .Button{font-weight:var(--base-text-weight-semibold,600)}.SegmentedControl-item.SegmentedControl-item--selected .Button:hover{background-color:initial}.SegmentedControl-item.SegmentedControl-item--selected:before{border-color:#0000!important}.SegmentedControl-item.SegmentedControl-item--selected+.SegmentedControl-item:before{border-color:#0000}.SegmentedControl-item .Button-label[data-content]:before{content:attr(data-content);display:block;font-weight:var(--base-text-weight-semibold,600);height:0;visibility:hidden}.SegmentedControl-item:not(:first-child):before{border-left:var(--borderWidth-thin,max(1px,.0625rem)) solid var(--borderColor-default,var(--color-border-default));content:"";inset:0 0 0 -1px;margin-bottom:var(--control-medium-paddingBlock,.375rem);margin-top:var(--control-medium-paddingBlock,.375rem);position:absolute}.SegmentedControl-item .Button{border:0;color:var(--button-default-fgColor-rest,var(--color-btn-text));font-weight:var(--base-text-weight-normal,400);transition:none}.SegmentedControl-item .Button:focus-visible{border-radius:calc(var(--borderRadius-medium,.375rem) - 5px);outline-offset:calc(var(--control-xsmall-paddingInline-condensed,.25rem) - var(--borderWidth-thin,max(1px, .0625rem)))}.SegmentedControl-item .Button--small{height:calc(var(--control-small-size,1.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-small-paddingInline-condensed,.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--small.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--small.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--medium{height:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-medium-paddingInline-normal,.75rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--medium.Button--iconOnly{width:calc(var(--control-medium-size,2rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--medium.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-medium-size,2rem);min-width:var(--control-medium-size,2rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--large{height:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2);padding:0 calc(var(--control-large-paddingInline-spacious,1rem) - var(--control-xsmall-paddingInline-condensed,.25rem))}.SegmentedControl-item .Button--large.Button--iconOnly{width:calc(var(--control-large-size,2.5rem) - var(--control-xsmall-paddingInline-condensed,.25rem)*2 - var(--borderWidth-thin,max(1px, .0625rem))*2)}.SegmentedControl-item .Button--large.Button--iconOnly:before{content:"";height:100%;left:50%;min-height:var(--control-large-size,2.5rem);min-width:var(--control-large-size,2.5rem);position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}.SegmentedControl-item .Button--iconOnly{padding:initial}.SegmentedControl-item .Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.SegmentedControl--fullWidth{display:flex}.SegmentedControl--fullWidth .SegmentedControl-item{flex:1;justify-content:center}.SegmentedControl--fullWidth .Button--iconOnly,.SegmentedControl--fullWidth .Button-withTooltip{display:flex;justify-content:center;width:100%!important}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"sources":["segmented_control.pcss","<no source>"],"names":[],"mappings":"AAEA,kBAGE,mFAAqF,CACrF,gDAAyC,CAHzC,mBAAoB,CACpB,eAGF,CAEA,uBAGE,4DAAiD,CACjD,gDAAyC,CAFzC,mBAAoB,CAGpB,4DAAsD,CAJtD,iBAkIF,CA3HI,+DACE,iGACF,CAEA,gEACE,mGACF,CAIF,uDACE,yFAA2F,CAC3F,sGAiBF,CAfE,+DACE,gDAKF,CAHE,qEACE,wBACF,CAGF,8DACE,4BACF,CAEA,qFACE,kBACF,CAIF,0DAKE,0BAA2B,CAJ3B,aAAc,CAEd,gDAA6C,CAD7C,QAAS,CAET,iBAEF,CAIE,gDAME,kHAAqE,CADrE,UAAW,CAHX,gBAAiB,CAEjB,wDAAiD,CADjD,qDAA8C,CAF9C,iBAMF,CAIF,+BACE,QAAS,CAGT,8DAAyC,CAFzC,8CAA2C,CAC3C,eAOF,CAJE,6CAEE,4DAAqD,CADrD,sHAEF,CAGF,sCACE,sJAEC,CACD,yHAWF,CATE,uDACE,mJAOF,CAFI,8DC9FR,WAAA,YAAA,SAAA,2CAAA,0CAAA,kBAAA,QAAA,4CAAA,UD8FoF,CAKlF,uCACE,oJAEC,CACD,wHAWF,CATE,wDACE,mJAOF,CAFI,+DC/GR,WAAA,YAAA,SAAA,2CAAA,0CAAA,kBAAA,QAAA,4CAAA,UD+GoF,CAKlF,sCACE,qJAEC,CACD,uHAWF,CATE,uDACE,oJAOF,CAFI,8DChIR,WAAA,YAAA,SAAA,4CAAA,2CAAA,kBAAA,QAAA,4CAAA,UDgIkF,CAKhF,yCACE,eACF,CAEA,oFACE,8DACF,CAIF,6BACE,
|
1
|
+
{"version":3,"sources":["segmented_control.pcss","<no source>"],"names":[],"mappings":"AAEA,kBAGE,mFAAqF,CACrF,gDAAyC,CAHzC,mBAAoB,CACpB,eAGF,CAEA,uBAGE,4DAAiD,CACjD,gDAAyC,CAFzC,mBAAoB,CAGpB,4DAAsD,CAJtD,iBAkIF,CA3HI,+DACE,iGACF,CAEA,gEACE,mGACF,CAIF,uDACE,yFAA2F,CAC3F,sGAiBF,CAfE,+DACE,gDAKF,CAHE,qEACE,wBACF,CAGF,8DACE,4BACF,CAEA,qFACE,kBACF,CAIF,0DAKE,0BAA2B,CAJ3B,aAAc,CAEd,gDAA6C,CAD7C,QAAS,CAET,iBAEF,CAIE,gDAME,kHAAqE,CADrE,UAAW,CAHX,gBAAiB,CAEjB,wDAAiD,CADjD,qDAA8C,CAF9C,iBAMF,CAIF,+BACE,QAAS,CAGT,8DAAyC,CAFzC,8CAA2C,CAC3C,eAOF,CAJE,6CAEE,4DAAqD,CADrD,sHAEF,CAGF,sCACE,sJAEC,CACD,yHAWF,CATE,uDACE,mJAOF,CAFI,8DC9FR,WAAA,YAAA,SAAA,2CAAA,0CAAA,kBAAA,QAAA,4CAAA,UD8FoF,CAKlF,uCACE,oJAEC,CACD,wHAWF,CATE,wDACE,mJAOF,CAFI,+DC/GR,WAAA,YAAA,SAAA,2CAAA,0CAAA,kBAAA,QAAA,4CAAA,UD+GoF,CAKlF,sCACE,qJAEC,CACD,uHAWF,CATE,uDACE,oJAOF,CAFI,8DChIR,WAAA,YAAA,SAAA,4CAAA,2CAAA,kBAAA,QAAA,4CAAA,UDgIkF,CAKhF,yCACE,eACF,CAEA,oFACE,8DACF,CAIF,6BACE,YAcF,CAZE,oDACE,MAAO,CACP,sBACF,CAGA,gGAGE,YAAa,CACb,sBAAuB,CAFvB,oBAGF","file":"segmented_control.css","sourcesContent":["/* SegmentedControl */\n\n.SegmentedControl {\n display: inline-flex;\n list-style: none;\n background-color: var(--controlTrack-bgColor-rest, var(--color-segmented-control-bg));\n border-radius: var(--borderRadius-medium);\n}\n\n.SegmentedControl-item {\n position: relative;\n display: inline-flex;\n border: var(--borderWidth-thin) solid transparent;\n border-radius: var(--borderRadius-medium);\n padding: var(--control-xsmall-paddingInline-condensed);\n\n & .Button--invisible {\n &:hover:not(:disabled) {\n background-color: var(--controlTrack-bgColor-hover, var(--color-action-list-item-default-hover-bg));\n }\n\n &:active:not(:disabled) {\n background-color: var(--controlTrack-bgColor-active, var(--color-action-list-item-default-active-bg));\n }\n }\n\n /* Selected ---------------------------------------- */\n &.SegmentedControl-item--selected {\n background-color: var(--controlKnob-bgColor-rest, var(--color-segmented-control-button-bg));\n border-color: var(--controlKnob-borderColor-rest, var(--color-segmented-control-button-selected-border));\n\n & .Button {\n font-weight: var(--base-text-weight-semibold);\n\n &:hover {\n background-color: transparent;\n }\n }\n\n &::before {\n border-color: transparent !important;\n }\n\n & + .SegmentedControl-item::before {\n border-color: transparent;\n }\n }\n\n /* renders a visibly hidden \"copy\" of the text in bold, reserving box space for when text becomes bold on selected */\n & .Button-label[data-content]::before {\n display: block;\n height: 0;\n font-weight: var(--base-text-weight-semibold);\n visibility: hidden;\n content: attr(data-content);\n }\n\n /* Separator lines */\n &:not(:first-child) {\n &::before {\n position: absolute;\n inset: 0 0 0 -1px;\n margin-top: var(--control-medium-paddingBlock);\n margin-bottom: var(--control-medium-paddingBlock);\n content: '';\n border-left: var(--borderWidth-thin) solid var(--borderColor-default);\n }\n }\n\n /* Button ----------------------------------------- */\n & .Button {\n border: 0;\n font-weight: var(--base-text-weight-normal);\n transition: none;\n color: var(--button-default-fgColor-rest);\n\n &:focus-visible {\n outline-offset: calc(var(--control-xsmall-paddingInline-condensed) - var(--borderWidth-thin));\n border-radius: calc(var(--borderRadius-medium) - 5px);\n }\n }\n\n & .Button--small {\n height: calc(\n var(--control-small-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n padding: 0 calc(var(--control-small-paddingInline-condensed) - var(--control-xsmall-paddingInline-condensed));\n\n &.Button--iconOnly {\n width: calc(\n var(--control-medium-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n\n &::before {\n @mixin minTouchTarget var(--control-medium-size), var(--control-medium-size);\n }\n }\n }\n\n & .Button--medium {\n height: calc(\n var(--control-medium-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n padding: 0 calc(var(--control-medium-paddingInline-normal) - var(--control-xsmall-paddingInline-condensed));\n\n &.Button--iconOnly {\n width: calc(\n var(--control-medium-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n\n &::before {\n @mixin minTouchTarget var(--control-medium-size), var(--control-medium-size);\n }\n }\n }\n\n & .Button--large {\n height: calc(\n var(--control-large-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n padding: 0 calc(var(--control-large-paddingInline-spacious) - var(--control-xsmall-paddingInline-condensed));\n\n &.Button--iconOnly {\n width: calc(\n var(--control-large-size) - var(--control-xsmall-paddingInline-condensed) * 2 - var(--borderWidth-thin) * 2\n );\n\n &::before {\n @mixin minTouchTarget var(--control-large-size), var(--control-large-size);\n }\n }\n }\n\n & .Button--iconOnly {\n padding: initial;\n }\n\n & .Button--invisible.Button--invisible-noVisuals .Button-label {\n color: var(--button-default-fgColor-rest);\n }\n}\n\n/* fullWidth */\n.SegmentedControl--fullWidth {\n display: flex;\n\n & .SegmentedControl-item {\n flex: 1;\n justify-content: center;\n }\n\n /* is .Button-withTooltip used anywhere? can't find use of it */\n & .Button--iconOnly,\n & .Button-withTooltip {\n width: 100% !important;\n display: flex;\n justify-content: center;\n }\n}\n",null]}
|
@@ -3,6 +3,7 @@ type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw';
|
|
3
3
|
declare class ToolTipElement extends HTMLElement {
|
4
4
|
#private;
|
5
5
|
styles(): string;
|
6
|
+
get showReason(): "focus" | "mouse";
|
6
7
|
get htmlFor(): string;
|
7
8
|
set htmlFor(value: string);
|
8
9
|
get type(): 'description' | 'label';
|
@@ -9,7 +9,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
10
10
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
11
11
|
};
|
12
|
-
var _ToolTipElement_instances, _ToolTipElement_abortController, _ToolTipElement_align, _ToolTipElement_side, _ToolTipElement_allowUpdatePosition, _ToolTipElement_update, _ToolTipElement_updateControlReference, _ToolTipElement_updateDirection, _ToolTipElement_updatePosition;
|
12
|
+
var _ToolTipElement_instances, _ToolTipElement_abortController, _ToolTipElement_align, _ToolTipElement_side, _ToolTipElement_allowUpdatePosition, _ToolTipElement_showReason, _ToolTipElement_update, _ToolTipElement_updateControlReference, _ToolTipElement_updateDirection, _ToolTipElement_updatePosition;
|
13
13
|
import '@oddbird/popover-polyfill';
|
14
14
|
import { getAnchoredPosition } from '@primer/behaviors';
|
15
15
|
const isPopoverOpen = (() => {
|
@@ -60,6 +60,15 @@ function closeOpenTooltips(except) {
|
|
60
60
|
function focusOutListener() {
|
61
61
|
closeOpenTooltips();
|
62
62
|
}
|
63
|
+
function focusInListener(event) {
|
64
|
+
setTimeout(() => {
|
65
|
+
for (const tooltip of openTooltips) {
|
66
|
+
if (isPopoverOpen(tooltip) && tooltip.showReason === 'focus' && tooltip.control !== event.target) {
|
67
|
+
tooltip.hidePopover();
|
68
|
+
}
|
69
|
+
}
|
70
|
+
}, 0);
|
71
|
+
}
|
63
72
|
const tooltips = new Set();
|
64
73
|
const openTooltips = new Set();
|
65
74
|
class ToolTipElement extends HTMLElement {
|
@@ -70,6 +79,7 @@ class ToolTipElement extends HTMLElement {
|
|
70
79
|
_ToolTipElement_align.set(this, 'center');
|
71
80
|
_ToolTipElement_side.set(this, 'outside-bottom');
|
72
81
|
_ToolTipElement_allowUpdatePosition.set(this, false);
|
82
|
+
_ToolTipElement_showReason.set(this, 'mouse');
|
73
83
|
}
|
74
84
|
styles() {
|
75
85
|
return `
|
@@ -203,6 +213,9 @@ class ToolTipElement extends HTMLElement {
|
|
203
213
|
}
|
204
214
|
`;
|
205
215
|
}
|
216
|
+
get showReason() {
|
217
|
+
return __classPrivateFieldGet(this, _ToolTipElement_showReason, "f");
|
218
|
+
}
|
206
219
|
get htmlFor() {
|
207
220
|
return this.getAttribute('for') || '';
|
208
221
|
}
|
@@ -269,6 +282,7 @@ class ToolTipElement extends HTMLElement {
|
|
269
282
|
signal
|
270
283
|
});
|
271
284
|
this.ownerDocument.addEventListener('focusout', focusOutListener);
|
285
|
+
this.ownerDocument.addEventListener('focusin', focusInListener);
|
272
286
|
this.ownerDocument.addEventListener('keydown', this, { signal });
|
273
287
|
}
|
274
288
|
disconnectedCallback() {
|
@@ -293,6 +307,7 @@ class ToolTipElement extends HTMLElement {
|
|
293
307
|
const shouldHide = isMouseLeaveFromButton || isEscapeKeydown || isMouseDownOnButton || isOpeningOtherPopover;
|
294
308
|
await Promise.resolve();
|
295
309
|
if (!showing && shouldShow && !isPopoverOpen(this)) {
|
310
|
+
__classPrivateFieldSet(this, _ToolTipElement_showReason, event.type === 'mouseenter' ? 'mouse' : 'focus', "f");
|
296
311
|
this.showPopover();
|
297
312
|
}
|
298
313
|
else if (showing && shouldHide && isPopoverOpen(this)) {
|
@@ -313,7 +328,7 @@ class ToolTipElement extends HTMLElement {
|
|
313
328
|
}
|
314
329
|
}
|
315
330
|
}
|
316
|
-
_ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new WeakMap(), _ToolTipElement_side = new WeakMap(), _ToolTipElement_allowUpdatePosition = new WeakMap(), _ToolTipElement_instances = new WeakSet(), _ToolTipElement_update = function _ToolTipElement_update(isOpen) {
|
331
|
+
_ToolTipElement_abortController = new WeakMap(), _ToolTipElement_align = new WeakMap(), _ToolTipElement_side = new WeakMap(), _ToolTipElement_allowUpdatePosition = new WeakMap(), _ToolTipElement_showReason = new WeakMap(), _ToolTipElement_instances = new WeakSet(), _ToolTipElement_update = function _ToolTipElement_update(isOpen) {
|
317
332
|
if (isOpen) {
|
318
333
|
openTooltips.add(this);
|
319
334
|
this.classList.remove(TOOLTIP_SR_ONLY_CLASS);
|
@@ -53,6 +53,16 @@ function focusOutListener() {
|
|
53
53
|
closeOpenTooltips()
|
54
54
|
}
|
55
55
|
|
56
|
+
function focusInListener(event: Event) {
|
57
|
+
setTimeout(() => {
|
58
|
+
for (const tooltip of openTooltips) {
|
59
|
+
if (isPopoverOpen(tooltip) && tooltip.showReason === 'focus' && tooltip.control !== event.target) {
|
60
|
+
tooltip.hidePopover()
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}, 0)
|
64
|
+
}
|
65
|
+
|
56
66
|
const tooltips = new Set<ToolTipElement>()
|
57
67
|
const openTooltips = new Set<ToolTipElement>()
|
58
68
|
class ToolTipElement extends HTMLElement {
|
@@ -193,6 +203,10 @@ class ToolTipElement extends HTMLElement {
|
|
193
203
|
#align: AnchorAlignment = 'center'
|
194
204
|
#side: AnchorSide = 'outside-bottom'
|
195
205
|
#allowUpdatePosition = false
|
206
|
+
#showReason: 'focus' | 'mouse' = 'mouse'
|
207
|
+
get showReason() {
|
208
|
+
return this.#showReason
|
209
|
+
}
|
196
210
|
|
197
211
|
get htmlFor(): string {
|
198
212
|
return this.getAttribute('for') || ''
|
@@ -270,6 +284,7 @@ class ToolTipElement extends HTMLElement {
|
|
270
284
|
signal
|
271
285
|
})
|
272
286
|
this.ownerDocument.addEventListener('focusout', focusOutListener)
|
287
|
+
this.ownerDocument.addEventListener('focusin', focusInListener)
|
273
288
|
this.ownerDocument.addEventListener('keydown', this, {signal})
|
274
289
|
}
|
275
290
|
|
@@ -297,6 +312,7 @@ class ToolTipElement extends HTMLElement {
|
|
297
312
|
|
298
313
|
await Promise.resolve()
|
299
314
|
if (!showing && shouldShow && !isPopoverOpen(this)) {
|
315
|
+
this.#showReason = event.type === 'mouseenter' ? 'mouse' : 'focus'
|
300
316
|
this.showPopover()
|
301
317
|
} else if (showing && shouldHide && isPopoverOpen(this)) {
|
302
318
|
this.hidePopover()
|
@@ -19,12 +19,14 @@ module Primer
|
|
19
19
|
# @param type [Symbol] <%= one_of(Primer::Beta::BaseButton::TYPE_OPTIONS) %>
|
20
20
|
# @param block [Boolean] Whether button is full-width with `display: block`.
|
21
21
|
# @param disabled [Boolean] Whether or not the button is disabled. If true, this option forces `tag:` to `:button`.
|
22
|
+
# @param inactive [Boolean] Whether the button looks visually disabled, but can still accept all the same interactions as an enabled button.
|
22
23
|
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
|
23
24
|
def initialize(
|
24
25
|
tag: DEFAULT_TAG,
|
25
26
|
type: DEFAULT_TYPE,
|
26
27
|
block: false,
|
27
28
|
disabled: false,
|
29
|
+
inactive: false,
|
28
30
|
**system_arguments
|
29
31
|
)
|
30
32
|
@system_arguments = system_arguments
|
@@ -37,6 +39,8 @@ module Primer
|
|
37
39
|
"btn-block" => block
|
38
40
|
)
|
39
41
|
|
42
|
+
@system_arguments[:"aria-disabled"] = true if inactive
|
43
|
+
|
40
44
|
@disabled = disabled
|
41
45
|
return unless @disabled
|
42
46
|
|