openproject-primer_view_components 0.12.1 → 0.13.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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +35 -0
  3. data/app/assets/javascripts/app/components/primer/alpha/tool_tip.d.ts +1 -0
  4. data/app/assets/javascripts/primer_view_components.js +1 -1
  5. data/app/assets/javascripts/primer_view_components.js.map +1 -1
  6. data/app/assets/styles/primer_view_components.css +1 -1
  7. data/app/assets/styles/primer_view_components.css.map +1 -1
  8. data/app/components/primer/alpha/action_bar/item.rb +7 -4
  9. data/app/components/primer/alpha/action_bar.rb +2 -2
  10. data/app/components/primer/alpha/action_bar_element.js +9 -4
  11. data/app/components/primer/alpha/action_bar_element.ts +9 -2
  12. data/app/components/primer/alpha/action_list/form_wrapper.html.erb +4 -2
  13. data/app/components/primer/alpha/action_list/form_wrapper.rb +20 -9
  14. data/app/components/primer/alpha/action_menu/action_menu_element.js +160 -85
  15. data/app/components/primer/alpha/action_menu/action_menu_element.ts +195 -81
  16. data/app/components/primer/alpha/action_menu/list.rb +0 -2
  17. data/app/components/primer/alpha/action_menu.rb +120 -3
  18. data/app/components/primer/alpha/modal_dialog.js +10 -13
  19. data/app/components/primer/alpha/modal_dialog.ts +10 -13
  20. data/app/components/primer/alpha/segmented_control/item.html.erb +1 -8
  21. data/app/components/primer/alpha/segmented_control/item.rb +38 -4
  22. data/app/components/primer/alpha/segmented_control.css +1 -1
  23. data/app/components/primer/alpha/segmented_control.css.json +14 -13
  24. data/app/components/primer/alpha/segmented_control.css.map +1 -1
  25. data/app/components/primer/alpha/segmented_control.pcss +75 -66
  26. data/app/components/primer/alpha/segmented_control.rb +10 -0
  27. data/app/components/primer/alpha/text_field.css +1 -1
  28. data/app/components/primer/alpha/tool_tip.d.ts +1 -0
  29. data/app/components/primer/alpha/tool_tip.js +26 -93
  30. data/app/components/primer/alpha/tool_tip.ts +25 -91
  31. data/app/components/primer/beta/base_button.rb +4 -0
  32. data/app/components/primer/beta/button.css +1 -1
  33. data/app/components/primer/beta/button.css.map +1 -1
  34. data/app/components/primer/beta/button.pcss +6 -2
  35. data/app/components/primer/focus_group.js +28 -3
  36. data/app/components/primer/focus_group.ts +27 -1
  37. data/lib/primer/accessibility.rb +3 -1
  38. data/lib/primer/static/generate_info_arch.rb +86 -5
  39. data/lib/primer/view_components/version.rb +2 -2
  40. data/previews/primer/alpha/action_menu_preview/single_select_form_items.html.erb +31 -0
  41. data/previews/primer/alpha/action_menu_preview/with_actions.html.erb +6 -5
  42. data/previews/primer/alpha/action_menu_preview.rb +10 -1
  43. data/previews/primer/alpha/check_box_preview.rb +1 -0
  44. data/previews/primer/alpha/dialog_preview/autofocus_element.html.erb +8 -0
  45. data/previews/primer/alpha/dialog_preview.rb +5 -0
  46. data/previews/primer/alpha/radio_button_preview.rb +1 -0
  47. data/previews/primer/alpha/segmented_control_preview.rb +35 -0
  48. data/previews/primer/alpha/tooltip_preview/tooltip_with_dialog_moving_focus_to_input.html.erb +23 -0
  49. data/previews/primer/alpha/tooltip_preview.rb +6 -1
  50. data/previews/primer/beta/button_group_preview.rb +6 -6
  51. data/previews/primer/beta/button_preview.rb +20 -2
  52. data/previews/primer/beta/icon_button_preview.rb +3 -0
  53. data/static/arguments.json +18 -1
  54. data/static/classes.json +12 -0
  55. data/static/constants.json +12 -1
  56. data/static/info_arch.json +137 -161
  57. data/static/previews.json +91 -172
  58. metadata +5 -310
@@ -21,9 +21,8 @@ const isPopoverOpen = (() => {
21
21
  return (el: Element) => (selector ? el.matches(selector) : setSelector(el))
22
22
  })()
23
23
 
24
- const TOOLTIP_ARROW_EDGE_OFFSET = 6
25
24
  const TOOLTIP_SR_ONLY_CLASS = 'sr-only'
26
- const TOOLTIP_OFFSET = 10
25
+ const TOOLTIP_OFFSET = 4
27
26
 
28
27
  type Direction = 'n' | 's' | 'e' | 'w' | 'ne' | 'se' | 'nw' | 'sw'
29
28
 
@@ -53,16 +52,25 @@ function focusOutListener() {
53
52
  closeOpenTooltips()
54
53
  }
55
54
 
55
+ function focusInListener(event: Event) {
56
+ setTimeout(() => {
57
+ for (const tooltip of openTooltips) {
58
+ if (isPopoverOpen(tooltip) && tooltip.showReason === 'focus' && tooltip.control !== event.target) {
59
+ tooltip.hidePopover()
60
+ }
61
+ }
62
+ }, 0)
63
+ }
64
+
56
65
  const tooltips = new Set<ToolTipElement>()
57
66
  const openTooltips = new Set<ToolTipElement>()
58
67
  class ToolTipElement extends HTMLElement {
59
68
  styles() {
60
69
  return `
61
70
  :host {
62
- padding: .5em .75em !important;
63
- font: normal normal 11px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
64
- -webkit-font-smoothing: subpixel-antialiased;
65
- color: var(--color-fg-on-emphasis) !important;
71
+ padding: var(--overlay-paddingBlock-condensed) var(--overlay-padding-condensed) !important;
72
+ font: var(--text-body-shorthand-small);
73
+ color: var(--fgColor-onEmphasis, var(--color-fg-on-emphasis)) !important;
66
74
  text-align: center;
67
75
  text-decoration: none;
68
76
  text-shadow: none;
@@ -70,25 +78,17 @@ class ToolTipElement extends HTMLElement {
70
78
  letter-spacing: normal;
71
79
  word-wrap: break-word;
72
80
  white-space: pre;
73
- background: var(--color-neutral-emphasis-plus) !important;
74
- border-radius: 6px;
81
+ background: var(--bgColor-emphasis, var(--color-neutral-emphasis-plus)) !important;
82
+ border-radius: var(--borderRadius-medium);
75
83
  border: 0 !important;
76
84
  opacity: 0;
77
- max-width: 250px;
85
+ max-width: var(--overlay-width-small);
78
86
  word-wrap: break-word;
79
87
  white-space: normal;
80
88
  width: max-content !important;
81
89
  inset: var(--tool-tip-position-top, 0) auto auto var(--tool-tip-position-left, 0) !important;
82
90
  overflow: visible !important;
83
- }
84
-
85
- :host:before{
86
- position: absolute;
87
- z-index: 1000001;
88
- color: var(--color-neutral-emphasis-plus);
89
- content: "";
90
- border: 6px solid transparent;
91
- opacity: 0
91
+ text-wrap: balance;
92
92
  }
93
93
 
94
94
  @keyframes tooltip-appear {
@@ -100,91 +100,19 @@ class ToolTipElement extends HTMLElement {
100
100
  }
101
101
  }
102
102
 
103
- :host:after{
104
- position: absolute;
105
- display: block;
106
- right: 0;
107
- left: 0;
108
- height: 12px;
109
- content: ""
110
- }
111
-
112
103
  :host(:popover-open),
113
104
  :host(:popover-open):before {
114
105
  animation-name: tooltip-appear;
115
106
  animation-duration: .1s;
116
107
  animation-fill-mode: forwards;
117
108
  animation-timing-function: ease-in;
118
- animation-delay: .4s
119
109
  }
120
110
 
121
- :host(.\\:popover-open),
122
- :host(.\\:popover-open):before {
111
+ :host(.\\:popover-open) {
123
112
  animation-name: tooltip-appear;
124
113
  animation-duration: .1s;
125
114
  animation-fill-mode: forwards;
126
115
  animation-timing-function: ease-in;
127
- animation-delay: .4s
128
- }
129
-
130
- :host(.tooltip-s):before,
131
- :host(.tooltip-n):before {
132
- right: 50%;
133
- margin-right: -${TOOLTIP_ARROW_EDGE_OFFSET}px;
134
- }
135
-
136
- :host(.tooltip-s):before,
137
- :host(.tooltip-se):before,
138
- :host(.tooltip-sw):before {
139
- bottom: 100%;
140
- border-bottom-color: var(--color-neutral-emphasis-plus)
141
- }
142
-
143
- :host(.tooltip-s):after,
144
- :host(.tooltip-se):after,
145
- :host(.tooltip-sw):after {
146
- bottom: 100%
147
- }
148
-
149
- :host(.tooltip-n):before,
150
- :host(.tooltip-ne):before,
151
- :host(.tooltip-nw):before {
152
- top: 100%;
153
- border-top-color: var(--color-neutral-emphasis-plus)
154
- }
155
-
156
- :host(.tooltip-n):after,
157
- :host(.tooltip-ne):after,
158
- :host(.tooltip-nw):after {
159
- top: 100%
160
- }
161
-
162
- :host(.tooltip-se):before,
163
- :host(.tooltip-ne):before {
164
- left: 0;
165
- margin-left: ${TOOLTIP_ARROW_EDGE_OFFSET}px;
166
- }
167
-
168
- :host(.tooltip-sw):before,
169
- :host(.tooltip-nw):before {
170
- right: 0;
171
- margin-right: ${TOOLTIP_ARROW_EDGE_OFFSET}px;
172
- }
173
-
174
- :host(.tooltip-w):before {
175
- top: 50%;
176
- bottom: 50%;
177
- left: 100%;
178
- margin-top: -6px;
179
- border-left-color: var(--color-neutral-emphasis-plus)
180
- }
181
-
182
- :host(.tooltip-e):before {
183
- top: 50%;
184
- right: 100%;
185
- bottom: 50%;
186
- margin-top: -6px;
187
- border-right-color: var(--color-neutral-emphasis-plus)
188
116
  }
189
117
  `
190
118
  }
@@ -193,6 +121,10 @@ class ToolTipElement extends HTMLElement {
193
121
  #align: AnchorAlignment = 'center'
194
122
  #side: AnchorSide = 'outside-bottom'
195
123
  #allowUpdatePosition = false
124
+ #showReason: 'focus' | 'mouse' = 'mouse'
125
+ get showReason() {
126
+ return this.#showReason
127
+ }
196
128
 
197
129
  get htmlFor(): string {
198
130
  return this.getAttribute('for') || ''
@@ -270,6 +202,7 @@ class ToolTipElement extends HTMLElement {
270
202
  signal
271
203
  })
272
204
  this.ownerDocument.addEventListener('focusout', focusOutListener)
205
+ this.ownerDocument.addEventListener('focusin', focusInListener)
273
206
  this.ownerDocument.addEventListener('keydown', this, {signal})
274
207
  }
275
208
 
@@ -297,6 +230,7 @@ class ToolTipElement extends HTMLElement {
297
230
 
298
231
  await Promise.resolve()
299
232
  if (!showing && shouldShow && !isPopoverOpen(this)) {
233
+ this.#showReason = event.type === 'mouseenter' ? 'mouse' : 'focus'
300
234
  this.showPopover()
301
235
  } else if (showing && shouldHide && isPopoverOpen(this)) {
302
236
  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
 
@@ -1 +1 @@
1
- :root{--duration-fast:80ms;--easing-easeInOut:cubic-bezier(0.65,0,0.35,1)}.Button{align-items:center;background-color:initial;border:var(--borderWidth-thin,max(1px,.0625rem)) solid;border-color:#0000;border-radius:var(--borderRadius-medium,.375rem);color:var(--button-default-fgColor-rest,var(--color-btn-text));cursor:pointer;display:inline-flex;flex-direction:row;font-size:var(--text-body-size-medium,.875rem);font-weight:var(--base-text-weight-medium,500);gap:var(--base-size-4,.25rem);height:var(--control-medium-size,2rem);justify-content:space-between;min-width:max-content;padding:0 var(--control-medium-paddingInline-normal,.75rem);position:relative;text-align:center;transition:var(--duration-fast) var(--easing-easeInOut);transition-property:color,fill,background-color,border-color;-webkit-user-select:none;user-select:none}@media (pointer:coarse){.Button:before{content:"";height:100%;left:50%;min-height:48px;min-width:48px;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}}.Button:hover{transition-duration:var(--duration-fast)}.Button:active{transition:none}.Button:disabled,.Button[aria-disabled=true]{box-shadow:none;cursor:not-allowed}.Button-withTooltip{display:inline-block;position:relative}a.Button:hover,summary.Button:hover{text-decoration:none}.Button-content{align-items:center;display:grid;flex:1 0 auto;grid-template-areas:"leadingVisual text trailingVisual";grid-template-columns:min-content minmax(0,auto) min-content;place-content:center}.Button-content>:not(:last-child){margin-right:var(--control-medium-gap,.5rem)}.Button-content--alignStart{justify-content:start}.Button-visual{display:flex;pointer-events:none}.Button-visual .Counter{background-color:var(--buttonCounter-default-bgColor-rest,var(--color-btn-counter-bg));color:inherit}.Button-label{grid-area:text;line-height:var(--text-body-lineHeight-medium,1.4285);white-space:nowrap}.Button-leadingVisual{grid-area:leadingVisual}.Button-leadingVisual svg{fill:currentcolor}.Button-trailingVisual{grid-area:trailingVisual}.Button-trailingAction{margin-right:calc(var(--base-size-4,.25rem)*-1)}.Button--small{font-size:var(--text-body-size-small,.75rem);gap:var(--control-small-gap,.25rem);height:var(--control-small-size,1.75rem);padding:0 var(--control-small-paddingInline-condensed,.5rem)}.Button--small .Button-label{line-height:var(--text-body-lineHeight-small,1.6666)}.Button--small .Button-content>:not(:last-child){margin-right:var(--control-small-gap,.25rem)}.Button--large{gap:var(--control-large-gap,.5rem);height:var(--control-large-size,2.5rem);padding:0 var(--control-large-paddingInline-spacious,1rem)}.Button--large .Button-label{line-height:var(--text-body-lineHeight-large,1.5)}.Button--large .Button-content>:not(:last-child){margin-right:var(--control-large-gap,.5rem)}.Button--fullWidth{width:100%}.Button--primary{fill:var(--button-primary-iconColor-rest,var(--color-btn-primary-icon));background-color:var(--button-primary-bgColor-rest,var(--color-btn-primary-bg));border-color:var(--button-primary-borderColor-rest,var(--color-btn-primary-border));box-shadow:var(--shadow-resting-small,var(--color-btn-primary-shadow));color:var(--button-primary-fgColor-rest,var(--color-btn-primary-text))}.Button--primary:hover:not(:disabled){background-color:var(--button-primary-bgColor-hover,var(--color-btn-primary-hover-bg));border-color:var(--button-primary-borderColor-hover,var(--color-btn-primary-hover-border))}.Button--primary:focus{box-shadow:inset 0 0 0 3px var(--fgColor-onEmphasis,var(--color-fg-on-emphasis));outline:2px solid var(--focus-outlineColor,var(--color-accent-fg));outline-offset:-2px}.Button--primary:focus:not(:focus-visible){box-shadow:none;outline:1px solid #0000}.Button--primary:focus-visible{box-shadow:inset 0 0 0 3px var(--fgColor-onEmphasis,var(--color-fg-on-emphasis));outline:2px solid var(--focus-outlineColor,var(--color-accent-fg));outline-offset:-2px}.Button--primary:active:not(:disabled),.Button--primary[aria-pressed=true]{background-color:var(--button-primary-bgColor-active,var(--color-btn-primary-selected-bg));box-shadow:var(--button-primary-shadow-selected,var(--color-btn-primary-selected-shadow))}.Button--primary:disabled,.Button--primary[aria-disabled=true]{fill:var(--button-primary-fgColor-disabled,var(--color-btn-primary-disabled-text));background-color:var(--button-primary-bgColor-disabled,var(--color-btn-primary-disabled-bg));border-color:var(--button-primary-borderColor-disabled,var(--color-btn-primary-disabled-border));color:var(--button-primary-fgColor-disabled,var(--color-btn-primary-disabled-text))}.Button--primary .Counter{background-color:var(--buttonCounter-primary-bgColor-rest,var(--color-btn-primary-counter-bg));color:inherit}.Button--secondary{fill:var(--fgColor-muted,var(--color-fg-muted));background-color:var(--button-default-bgColor-rest,var(--color-btn-bg));border-color:var(--button-default-borderColor-rest,var(--color-btn-border));box-shadow:var(--button-default-shadow-resting,var(--color-btn-shadow)),var(--button-default-shadow-inset,var(--color-btn-inset-shadow));color:var(--button-default-fgColor-rest,var(--color-btn-text))}.Button--secondary:hover:not(:disabled){background-color:var(--button-default-bgColor-hover,var(--color-btn-hover-bg));border-color:var(--button-default-borderColor-hover,var(--color-btn-hover-border))}.Button--secondary:active:not(:disabled){background-color:var(--button-default-bgColor-active,var(--color-btn-active-bg));border-color:var(--button-default-borderColor-active,var(--color-btn-active-border))}.Button--secondary[aria-pressed=true]{background-color:var(--button-default-bgColor-selected,var(--color-btn-selected-bg));box-shadow:var(--shadow-inset,var(--color-primer-shadow-inset))}.Button--secondary:disabled,.Button--secondary[aria-disabled=true]{fill:var(--control-fgColor-disabled,var(--color-primer-fg-disabled));background-color:var(--button-default-bgColor-disabled,var(--color-btn-bg));border-color:var(--button-default-borderColor-disabled,var(--color-btn-border));color:var(--control-fgColor-disabled,var(--color-primer-fg-disabled))}.Button--invisible{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.Button--invisible.Button--iconOnly{color:var(--button-invisible-iconColor-rest,var(--color-fg-muted))}.Button--invisible:hover:not(:disabled){background-color:var(--button-invisible-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.Button--invisible:hover:not(:disabled) .Button-visual{color:var(--button-invisible-iconColor-hover,var(--color-fg-default))}.Button--invisible:active:not(:disabled),.Button--invisible[aria-pressed=true]{background-color:var(--button-invisible-bgColor-active,var(--color-action-list-item-default-active-bg))}.Button--invisible:disabled,.Button--invisible[aria-disabled=true]{fill:var(--button-invisible-fgColor-disabled,var(--color-primer-fg-disabled));background-color:var(--button-invisible-bgColor-disabled,var(--color-action-list-item-default-selected-bg));border-color:var(--button-invisible-borderColor-disabled,var(--color-action-list-item-default-selected-bg));color:var(--button-invisible-fgColor-disabled,var(--color-primer-fg-disabled))}.Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-invisible-fgColor-rest,var(--color-btn-outline-text))}.Button--invisible .Button-visual{color:var(--button-invisible-iconColor-rest,var(--color-fg-muted))}.Button--invisible .Button-visual .Counter{color:var(--fgColor-default,var(--color-fg-default))}.Button--link{fill:var(--fgColor-link,var(--color-accent-fg));border:none;color:var(--fgColor-link,var(--color-accent-fg));display:inline-block;font-size:inherit;height:unset;padding:0}.Button--link:hover:not(:disabled){text-decoration:underline}.Button--link:focus,.Button--link:focus-visible{outline-offset:2px}.Button--link:disabled,.Button--link[aria-disabled=true]{fill:var(--control-fgColor-disabled,var(--color-primer-fg-disabled));background-color:initial;border-color:#0000;color:var(--control-fgColor-disabled,var(--color-primer-fg-disabled))}.Button--danger{fill:var(--button-danger-iconColor-rest,var(--color-btn-danger-icon));background-color:var(--button-danger-bgColor-rest,var(--color-btn-bg));border-color:var(--button-danger-borderColor-rest,var(--color-btn-border));box-shadow:var(--button-default-shadow-resting,var(--color-btn-shadow)),var(--button-default-shadow-inset,var(--color-btn-inset-shadow));color:var(--button-danger-fgColor-rest,var(--color-btn-danger-text))}.Button--danger:hover:not(:disabled){fill:var(--button-danger-fgColor-hover,var(--color-btn-danger-hover-text));background-color:var(--button-danger-bgColor-hover,var(--color-btn-danger-hover-bg));border-color:var(--button-danger-borderColor-hover,var(--color-btn-danger-hover-border));box-shadow:var(--shadow-resting-small,var(--color-shadow-small));color:var(--button-danger-fgColor-hover,var(--color-btn-danger-hover-text))}.Button--danger:hover:not(:disabled) .Counter{background-color:var(--buttonCounter-danger-bgColor-hover,var(--color-btn-danger-hover-counter-bg));color:var(--buttonCounter-danger-fgColor-hover,var(--color-btn-danger-hover-counter-fg))}.Button--danger:active:not(:disabled),.Button--danger[aria-pressed=true]{fill:var(--button-danger-fgColor-active,var(--color-btn-danger-selected-text));background-color:var(--button-danger-bgColor-active,var(--color-btn-danger-selected-bg));border-color:var(--button-danger-borderColor-active,var(--color-btn-danger-selected-border));box-shadow:var(--button-danger-shadow-selected,var(--color-btn-danger-selected-shadow));color:var(--button-danger-fgColor-active,var(--color-btn-danger-selected-text))}.Button--danger:disabled,.Button--danger[aria-disabled=true]{fill:var(--button-danger-fgColor-disabled,var(--color-btn-danger-disabled-text));background-color:var(--button-danger-bgColor-disabled,var(--color-btn-danger-disabled-bg));border-color:var(--button-default-borderColor-disabled,var(--color-btn-border));color:var(--button-danger-fgColor-disabled,var(--color-btn-danger-disabled-text))}.Button--danger:disabled .Counter,.Button--danger[aria-disabled=true] .Counter{background-color:var(--buttonCounter-danger-bgColor-disabled,var(--color-btn-danger-disabled-counter-bg));color:var(--buttonCounter-danger-fgColor-disabled,var(--color-btn-danger-disabled-counter-fg))}.Button--danger .Counter{background-color:var(--buttonCounter-danger-bgColor-rest,var(--color-btn-danger-counter-bg));color:var(--buttonCounter-danger-fgColor-rest,var(--color-btn-danger-counter-fg))}.Button--iconOnly{display:inline-grid;padding:unset;place-content:center;width:var(--control-medium-size,2rem)}.Button--iconOnly.Button--small{width:var(--control-small-size,1.75rem)}.Button--iconOnly.Button--large{width:var(--control-large-size,2.5rem)}
1
+ :root{--duration-fast:80ms;--easing-easeInOut:cubic-bezier(0.65,0,0.35,1)}.Button{align-items:center;background-color:initial;border:var(--borderWidth-thin,max(1px,.0625rem)) solid;border-color:#0000;border-radius:var(--borderRadius-medium,.375rem);color:var(--button-default-fgColor-rest,var(--color-btn-text));cursor:pointer;display:inline-flex;flex-direction:row;font-size:var(--text-body-size-medium,.875rem);font-weight:var(--base-text-weight-medium,500);gap:var(--base-size-4,.25rem);height:var(--control-medium-size,2rem);justify-content:space-between;min-width:max-content;padding:0 var(--control-medium-paddingInline-normal,.75rem);position:relative;text-align:center;transition:var(--duration-fast) var(--easing-easeInOut);transition-property:color,fill,background-color,border-color;-webkit-user-select:none;user-select:none}@media (pointer:coarse){.Button:before{content:"";height:100%;left:50%;min-height:48px;min-width:48px;position:absolute;top:50%;transform:translateX(-50%) translateY(-50%);width:100%}}.Button:hover{transition-duration:var(--duration-fast)}.Button:active{transition:none}.Button:disabled{box-shadow:none;cursor:not-allowed}.Button[aria-disabled=true]{box-shadow:none;cursor:default}.Button-withTooltip{display:inline-block;position:relative}a.Button:hover,summary.Button:hover{text-decoration:none}.Button-content{align-items:center;display:grid;flex:1 0 auto;grid-template-areas:"leadingVisual text trailingVisual";grid-template-columns:min-content minmax(0,auto) min-content;place-content:center}.Button-content>:not(:last-child){margin-right:var(--control-medium-gap,.5rem)}.Button-content--alignStart{justify-content:start}.Button-visual{display:flex;pointer-events:none}.Button-visual .Counter{background-color:var(--buttonCounter-default-bgColor-rest,var(--color-btn-counter-bg));color:inherit}.Button-label{grid-area:text;line-height:var(--text-body-lineHeight-medium,1.4285);white-space:nowrap}.Button-leadingVisual{grid-area:leadingVisual}.Button-leadingVisual svg{fill:currentcolor}.Button-trailingVisual{grid-area:trailingVisual}.Button-trailingAction{margin-right:calc(var(--base-size-4,.25rem)*-1)}.Button--small{font-size:var(--text-body-size-small,.75rem);gap:var(--control-small-gap,.25rem);height:var(--control-small-size,1.75rem);padding:0 var(--control-small-paddingInline-condensed,.5rem)}.Button--small .Button-label{line-height:var(--text-body-lineHeight-small,1.6666)}.Button--small .Button-content>:not(:last-child){margin-right:var(--control-small-gap,.25rem)}.Button--large{gap:var(--control-large-gap,.5rem);height:var(--control-large-size,2.5rem);padding:0 var(--control-large-paddingInline-spacious,1rem)}.Button--large .Button-label{line-height:var(--text-body-lineHeight-large,1.5)}.Button--large .Button-content>:not(:last-child){margin-right:var(--control-large-gap,.5rem)}.Button--fullWidth{width:100%}.Button--primary{fill:var(--button-primary-iconColor-rest,var(--color-btn-primary-icon));background-color:var(--button-primary-bgColor-rest,var(--color-btn-primary-bg));border-color:var(--button-primary-borderColor-rest,var(--color-btn-primary-border));box-shadow:var(--shadow-resting-small,var(--color-btn-primary-shadow));color:var(--button-primary-fgColor-rest,var(--color-btn-primary-text))}.Button--primary:hover:not(:disabled){background-color:var(--button-primary-bgColor-hover,var(--color-btn-primary-hover-bg));border-color:var(--button-primary-borderColor-hover,var(--color-btn-primary-hover-border))}.Button--primary:focus{box-shadow:inset 0 0 0 3px var(--fgColor-onEmphasis,var(--color-fg-on-emphasis));outline:2px solid var(--focus-outlineColor,var(--color-accent-fg));outline-offset:-2px}.Button--primary:focus:not(:focus-visible){box-shadow:none;outline:1px solid #0000}.Button--primary:focus-visible{box-shadow:inset 0 0 0 3px var(--fgColor-onEmphasis,var(--color-fg-on-emphasis));outline:2px solid var(--focus-outlineColor,var(--color-accent-fg));outline-offset:-2px}.Button--primary:active:not(:disabled),.Button--primary[aria-pressed=true]{background-color:var(--button-primary-bgColor-active,var(--color-btn-primary-selected-bg));box-shadow:var(--button-primary-shadow-selected,var(--color-btn-primary-selected-shadow))}.Button--primary:disabled,.Button--primary[aria-disabled=true]{fill:var(--button-primary-fgColor-disabled,var(--color-btn-primary-disabled-text));background-color:var(--button-primary-bgColor-disabled,var(--color-btn-primary-disabled-bg));border-color:var(--button-primary-borderColor-disabled,var(--color-btn-primary-disabled-border));color:var(--button-primary-fgColor-disabled,var(--color-btn-primary-disabled-text))}.Button--primary .Counter{background-color:var(--buttonCounter-primary-bgColor-rest,var(--color-btn-primary-counter-bg));color:inherit}.Button--secondary{fill:var(--fgColor-muted,var(--color-fg-muted));background-color:var(--button-default-bgColor-rest,var(--color-btn-bg));border-color:var(--button-default-borderColor-rest,var(--color-btn-border));box-shadow:var(--button-default-shadow-resting,var(--color-btn-shadow)),var(--button-default-shadow-inset,var(--color-btn-inset-shadow));color:var(--button-default-fgColor-rest,var(--color-btn-text))}.Button--secondary:hover:not(:disabled){background-color:var(--button-default-bgColor-hover,var(--color-btn-hover-bg));border-color:var(--button-default-borderColor-hover,var(--color-btn-hover-border))}.Button--secondary:active:not(:disabled){background-color:var(--button-default-bgColor-active,var(--color-btn-active-bg));border-color:var(--button-default-borderColor-active,var(--color-btn-active-border))}.Button--secondary[aria-pressed=true]{background-color:var(--button-default-bgColor-selected,var(--color-btn-selected-bg));box-shadow:var(--shadow-inset,var(--color-primer-shadow-inset))}.Button--secondary:disabled,.Button--secondary[aria-disabled=true]{fill:var(--control-fgColor-disabled,var(--color-primer-fg-disabled));background-color:var(--button-default-bgColor-disabled,var(--color-btn-bg));border-color:var(--button-default-borderColor-disabled,var(--color-btn-border));color:var(--control-fgColor-disabled,var(--color-primer-fg-disabled))}.Button--invisible{color:var(--button-default-fgColor-rest,var(--color-btn-text))}.Button--invisible.Button--iconOnly{color:var(--button-invisible-iconColor-rest,var(--color-fg-muted))}.Button--invisible:hover:not(:disabled){background-color:var(--button-invisible-bgColor-hover,var(--color-action-list-item-default-hover-bg))}.Button--invisible:hover:not(:disabled) .Button-visual{color:var(--button-invisible-iconColor-hover,var(--color-fg-default))}.Button--invisible:active:not(:disabled),.Button--invisible[aria-pressed=true]{background-color:var(--button-invisible-bgColor-active,var(--color-action-list-item-default-active-bg))}.Button--invisible:disabled,.Button--invisible[aria-disabled=true]{fill:var(--button-invisible-fgColor-disabled,var(--color-primer-fg-disabled));background-color:var(--button-invisible-bgColor-disabled,var(--color-action-list-item-default-selected-bg));border-color:var(--button-invisible-borderColor-disabled,var(--color-action-list-item-default-selected-bg));color:var(--button-invisible-fgColor-disabled,var(--color-primer-fg-disabled))}.Button--invisible.Button--invisible-noVisuals .Button-label{color:var(--button-invisible-fgColor-rest,var(--color-btn-outline-text))}.Button--invisible .Button-visual{color:var(--button-invisible-iconColor-rest,var(--color-fg-muted))}.Button--invisible .Button-visual .Counter{color:var(--fgColor-default,var(--color-fg-default))}.Button--link{fill:var(--fgColor-link,var(--color-accent-fg));border:none;color:var(--fgColor-link,var(--color-accent-fg));display:inline-block;font-size:inherit;height:unset;padding:0}.Button--link:hover:not(:disabled){text-decoration:underline}.Button--link:focus,.Button--link:focus-visible{outline-offset:2px}.Button--link:disabled,.Button--link[aria-disabled=true]{fill:var(--control-fgColor-disabled,var(--color-primer-fg-disabled));background-color:initial;border-color:#0000;color:var(--control-fgColor-disabled,var(--color-primer-fg-disabled))}.Button--danger{fill:var(--button-danger-iconColor-rest,var(--color-btn-danger-icon));background-color:var(--button-danger-bgColor-rest,var(--color-btn-bg));border-color:var(--button-danger-borderColor-rest,var(--color-btn-border));box-shadow:var(--button-default-shadow-resting,var(--color-btn-shadow)),var(--button-default-shadow-inset,var(--color-btn-inset-shadow));color:var(--button-danger-fgColor-rest,var(--color-btn-danger-text))}.Button--danger:hover:not(:disabled){fill:var(--button-danger-fgColor-hover,var(--color-btn-danger-hover-text));background-color:var(--button-danger-bgColor-hover,var(--color-btn-danger-hover-bg));border-color:var(--button-danger-borderColor-hover,var(--color-btn-danger-hover-border));box-shadow:var(--shadow-resting-small,var(--color-shadow-small));color:var(--button-danger-fgColor-hover,var(--color-btn-danger-hover-text))}.Button--danger:hover:not(:disabled) .Counter{background-color:var(--buttonCounter-danger-bgColor-hover,var(--color-btn-danger-hover-counter-bg));color:var(--buttonCounter-danger-fgColor-hover,var(--color-btn-danger-hover-counter-fg))}.Button--danger:active:not(:disabled),.Button--danger[aria-pressed=true]{fill:var(--button-danger-fgColor-active,var(--color-btn-danger-selected-text));background-color:var(--button-danger-bgColor-active,var(--color-btn-danger-selected-bg));border-color:var(--button-danger-borderColor-active,var(--color-btn-danger-selected-border));box-shadow:var(--button-danger-shadow-selected,var(--color-btn-danger-selected-shadow));color:var(--button-danger-fgColor-active,var(--color-btn-danger-selected-text))}.Button--danger:disabled,.Button--danger[aria-disabled=true]{fill:var(--button-danger-fgColor-disabled,var(--color-btn-danger-disabled-text));background-color:var(--button-danger-bgColor-disabled,var(--color-btn-danger-disabled-bg));border-color:var(--button-default-borderColor-disabled,var(--color-btn-border));color:var(--button-danger-fgColor-disabled,var(--color-btn-danger-disabled-text))}.Button--danger:disabled .Counter,.Button--danger[aria-disabled=true] .Counter{background-color:var(--buttonCounter-danger-bgColor-disabled,var(--color-btn-danger-disabled-counter-bg));color:var(--buttonCounter-danger-fgColor-disabled,var(--color-btn-danger-disabled-counter-fg))}.Button--danger .Counter{background-color:var(--buttonCounter-danger-bgColor-rest,var(--color-btn-danger-counter-bg));color:var(--buttonCounter-danger-fgColor-rest,var(--color-btn-danger-counter-fg))}.Button--iconOnly{display:inline-grid;padding:unset;place-content:center;width:var(--control-medium-size,2rem)}.Button--iconOnly.Button--small{width:var(--control-small-size,1.75rem)}.Button--iconOnly.Button--large{width:var(--control-large-size,2.5rem)}
@@ -1 +1 @@
1
- {"version":3,"sources":["button.pcss","<no source>","../../../../lib/postcss_mixins/focusOutlineOnEmphasis.pcss"],"names":[],"mappings":"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","file":"button.css","sourcesContent":["/* CSS for Button */\n\n/* temporary, pre primitives release */\n:root {\n --duration-fast: 80ms;\n --easing-easeInOut: cubic-bezier(0.65, 0, 0.35, 1);\n}\n\n/* base button */\n.Button {\n position: relative;\n font-size: var(--text-body-size-medium);\n font-weight: var(--base-text-weight-medium);\n cursor: pointer;\n user-select: none;\n background-color: transparent;\n border: var(--borderWidth-thin) solid;\n border-color: transparent;\n border-radius: var(--borderRadius-medium);\n color: var(--button-default-fgColor-rest);\n transition: var(--duration-fast) var(--easing-easeInOut);\n transition-property: color, fill, background-color, border-color;\n text-align: center;\n height: var(--control-medium-size);\n padding: 0 var(--control-medium-paddingInline-normal);\n display: inline-flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n gap: var(--base-size-4);\n min-width: max-content;\n\n /* mobile friendly sizing */\n @media (pointer: coarse) {\n &::before {\n @mixin minTouchTarget 48px, 48px;\n }\n }\n\n /* base states */\n\n &:hover {\n transition-duration: var(--duration-fast);\n }\n\n &:active {\n transition: none;\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n cursor: not-allowed;\n box-shadow: none;\n }\n}\n\n.Button-withTooltip {\n position: relative;\n display: inline-block;\n}\n\na.Button,\nsummary.Button {\n &:hover {\n text-decoration: none;\n }\n}\n\n/* wrap grid content to allow trailingAction to lock-right */\n.Button-content {\n flex: 1 0 auto;\n display: grid;\n grid-template-areas: 'leadingVisual text trailingVisual';\n grid-template-columns: min-content minmax(0, auto) min-content;\n align-items: center;\n place-content: center;\n\n /* padding-bottom: 1px; optical alignment for firefox */\n\n & > :not(:last-child) {\n margin-right: var(--control-medium-gap);\n }\n}\n\n/* center child elements for fullWidth */\n.Button-content--alignStart {\n justify-content: start;\n}\n\n/* button child elements */\n\n/* align svg */\n.Button-visual {\n display: flex;\n pointer-events: none; /* allow click handler to work, avoiding visuals */\n\n & .Counter {\n color: inherit;\n background-color: var(--buttonCounter-default-bgColor-rest);\n }\n}\n\n.Button-label {\n grid-area: text;\n white-space: nowrap;\n line-height: var(--text-body-lineHeight-medium);\n}\n\n.Button-leadingVisual {\n grid-area: leadingVisual;\n}\n\n.Button-leadingVisual svg {\n fill: currentcolor;\n}\n\n.Button-trailingVisual {\n grid-area: trailingVisual;\n}\n\n.Button-trailingAction {\n margin-right: calc(var(--base-size-4) * -1);\n}\n\n/* sizes */\n\n.Button--small {\n font-size: var(--text-body-size-small);\n height: var(--control-small-size);\n padding: 0 var(--control-small-paddingInline-condensed);\n gap: var(--control-small-gap);\n\n & .Button-label {\n line-height: var(--text-body-lineHeight-small);\n }\n\n & .Button-content {\n & > :not(:last-child) {\n margin-right: var(--control-small-gap);\n }\n }\n}\n\n.Button--large {\n height: var(--control-large-size);\n padding: 0 var(--control-large-paddingInline-spacious);\n gap: var(--control-large-gap);\n\n & .Button-label {\n line-height: var(--text-body-lineHeight-large);\n }\n\n & .Button-content {\n & > :not(:last-child) {\n margin-right: var(--control-large-gap);\n }\n }\n}\n\n.Button--fullWidth {\n width: 100%;\n}\n\n/* variants */\n\n/* primary */\n.Button--primary {\n color: var(--button-primary-fgColor-rest);\n fill: var(--button-primary-iconColor-rest);\n background-color: var(--button-primary-bgColor-rest);\n border-color: var(--button-primary-borderColor-rest);\n box-shadow: var(--shadow-resting-small, var(--color-btn-primary-shadow));\n\n &:hover:not(:disabled) {\n background-color: var(--button-primary-bgColor-hover);\n border-color: var(--button-primary-borderColor-hover);\n }\n\n /* fallback :focus state */\n &:focus {\n @mixin focusOutlineOnEmphasis;\n\n /* remove fallback :focus if :focus-visible is supported */\n &:not(:focus-visible) {\n outline: solid 1px transparent;\n box-shadow: none;\n }\n }\n\n /* default focus state */\n &:focus-visible {\n @mixin focusOutlineOnEmphasis;\n }\n\n &:active:not(:disabled),\n &[aria-pressed='true'] {\n background-color: var(--button-primary-bgColor-active);\n box-shadow: var(--button-primary-shadow-selected);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--button-primary-fgColor-disabled);\n background-color: var(--button-primary-bgColor-disabled);\n border-color: var(--button-primary-borderColor-disabled);\n fill: var(--button-primary-fgColor-disabled);\n }\n\n & .Counter {\n color: inherit;\n background-color: var(--buttonCounter-primary-bgColor-rest);\n }\n}\n\n/* default (secondary) */\n.Button--secondary {\n color: var(--button-default-fgColor-rest);\n fill: var(--fgColor-muted); /* help this */\n background-color: var(--button-default-bgColor-rest);\n border-color: var(--button-default-borderColor-rest);\n box-shadow: var(--button-default-shadow-resting), var(--button-default-shadow-inset);\n\n &:hover:not(:disabled) {\n background-color: var(--button-default-bgColor-hover);\n border-color: var(--button-default-borderColor-hover);\n }\n\n &:active:not(:disabled) {\n background-color: var(--button-default-bgColor-active);\n border-color: var(--button-default-borderColor-active);\n }\n\n &[aria-pressed='true'] {\n background-color: var(--button-default-bgColor-selected);\n box-shadow: var(--shadow-inset);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--control-fgColor-disabled);\n background-color: var(--button-default-bgColor-disabled);\n border-color: var(--button-default-borderColor-disabled);\n fill: var(--control-fgColor-disabled);\n }\n}\n\n.Button--invisible {\n color: var(--button-default-fgColor-rest);\n\n &.Button--iconOnly {\n color: var(--button-invisible-iconColor-rest, var(--color-fg-muted));\n }\n\n &:hover:not(:disabled) {\n background-color: var(--button-invisible-bgColor-hover);\n\n & .Button-visual {\n color: var(--button-invisible-iconColor-hover, var(--color-fg-default));\n }\n }\n\n &[aria-pressed='true'],\n &:active:not(:disabled) {\n background-color: var(--button-invisible-bgColor-active);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--button-invisible-fgColor-disabled);\n background-color: var(--button-invisible-bgColor-disabled);\n border-color: var(--button-invisible-borderColor-disabled);\n fill: var(--button-invisible-fgColor-disabled);\n }\n\n /* if button has no visuals, use link blue for text */\n &.Button--invisible-noVisuals .Button-label {\n color: var(--button-invisible-fgColor-rest);\n }\n\n & .Button-visual {\n color: var(--button-invisible-iconColor-rest, var(--color-fg-muted));\n\n & .Counter {\n color: var(--fgColor-default);\n }\n }\n}\n\n.Button--link {\n color: var(--fgColor-link);\n fill: var(--fgColor-link);\n display: inline-block;\n font-size: inherit;\n border: none;\n height: unset;\n padding: 0;\n\n &:hover:not(:disabled) {\n text-decoration: underline;\n }\n\n &:focus-visible,\n &:focus {\n outline-offset: 2px;\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--control-fgColor-disabled);\n background-color: transparent;\n border-color: transparent;\n fill: var(--control-fgColor-disabled);\n }\n}\n\n/* danger */\n.Button--danger {\n color: var(--button-danger-fgColor-rest);\n fill: var(--button-danger-iconColor-rest);\n background-color: var(--button-danger-bgColor-rest);\n border-color: var(--button-danger-borderColor-rest);\n box-shadow: var(--button-default-shadow-resting), var(--button-default-shadow-inset);\n\n &:hover:not(:disabled) {\n color: var(--button-danger-fgColor-hover);\n fill: var(--button-danger-fgColor-hover);\n background-color: var(--button-danger-bgColor-hover);\n border-color: var(--button-danger-borderColor-hover);\n box-shadow: var(--shadow-resting-small);\n\n & .Counter {\n color: var(--buttonCounter-danger-fgColor-hover);\n background-color: var(--buttonCounter-danger-bgColor-hover);\n }\n }\n\n &:active:not(:disabled),\n &[aria-pressed='true'] {\n color: var(--button-danger-fgColor-active);\n fill: var(--button-danger-fgColor-active);\n background-color: var(--button-danger-bgColor-active);\n border-color: var(--button-danger-borderColor-active);\n box-shadow: var(--button-danger-shadow-selected);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--button-danger-fgColor-disabled);\n fill: var(--button-danger-fgColor-disabled);\n background-color: var(--button-danger-bgColor-disabled);\n border-color: var(--button-default-borderColor-disabled);\n\n & .Counter {\n color: var(--buttonCounter-danger-fgColor-disabled);\n background-color: var(--buttonCounter-danger-bgColor-disabled);\n }\n }\n\n & .Counter {\n color: var(--buttonCounter-danger-fgColor-rest);\n background-color: var(--buttonCounter-danger-bgColor-rest);\n }\n}\n\n.Button--iconOnly {\n display: inline-grid;\n place-content: center;\n padding: unset;\n width: var(--control-medium-size);\n\n &.Button--small {\n width: var(--control-small-size);\n }\n\n &.Button--large {\n width: var(--control-large-size);\n }\n}\n",null,"/* outline with fg box-shadow for buttons */\n@define-mixin focusOutlineOnEmphasis $outlineOffset: -2px, $outlineColor: var(--focus-outlineColor) {\n outline: 2px solid $outlineColor;\n outline-offset: $outlineOffset;\n box-shadow: inset 0 0 0 3px var(--fgColor-onEmphasis);\n}\n"]}
1
+ {"version":3,"sources":["button.pcss","<no source>","../../../../lib/postcss_mixins/focusOutlineOnEmphasis.pcss"],"names":[],"mappings":"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","file":"button.css","sourcesContent":["/* CSS for Button */\n\n/* temporary, pre primitives release */\n:root {\n --duration-fast: 80ms;\n --easing-easeInOut: cubic-bezier(0.65, 0, 0.35, 1);\n}\n\n/* base button */\n.Button {\n position: relative;\n font-size: var(--text-body-size-medium);\n font-weight: var(--base-text-weight-medium);\n cursor: pointer;\n user-select: none;\n background-color: transparent;\n border: var(--borderWidth-thin) solid;\n border-color: transparent;\n border-radius: var(--borderRadius-medium);\n color: var(--button-default-fgColor-rest);\n transition: var(--duration-fast) var(--easing-easeInOut);\n transition-property: color, fill, background-color, border-color;\n text-align: center;\n height: var(--control-medium-size);\n padding: 0 var(--control-medium-paddingInline-normal);\n display: inline-flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n gap: var(--base-size-4);\n min-width: max-content;\n\n /* mobile friendly sizing */\n @media (pointer: coarse) {\n &::before {\n @mixin minTouchTarget 48px, 48px;\n }\n }\n\n /* base states */\n\n &:hover {\n transition-duration: var(--duration-fast);\n }\n\n &:active {\n transition: none;\n }\n\n &:disabled {\n cursor: not-allowed;\n box-shadow: none;\n }\n\n &[aria-disabled='true'] {\n cursor: default;\n box-shadow: none;\n }\n}\n\n.Button-withTooltip {\n position: relative;\n display: inline-block;\n}\n\na.Button,\nsummary.Button {\n &:hover {\n text-decoration: none;\n }\n}\n\n/* wrap grid content to allow trailingAction to lock-right */\n.Button-content {\n flex: 1 0 auto;\n display: grid;\n grid-template-areas: 'leadingVisual text trailingVisual';\n grid-template-columns: min-content minmax(0, auto) min-content;\n align-items: center;\n place-content: center;\n\n /* padding-bottom: 1px; optical alignment for firefox */\n\n & > :not(:last-child) {\n margin-right: var(--control-medium-gap);\n }\n}\n\n/* center child elements for fullWidth */\n.Button-content--alignStart {\n justify-content: start;\n}\n\n/* button child elements */\n\n/* align svg */\n.Button-visual {\n display: flex;\n pointer-events: none; /* allow click handler to work, avoiding visuals */\n\n & .Counter {\n color: inherit;\n background-color: var(--buttonCounter-default-bgColor-rest);\n }\n}\n\n.Button-label {\n grid-area: text;\n white-space: nowrap;\n line-height: var(--text-body-lineHeight-medium);\n}\n\n.Button-leadingVisual {\n grid-area: leadingVisual;\n}\n\n.Button-leadingVisual svg {\n fill: currentcolor;\n}\n\n.Button-trailingVisual {\n grid-area: trailingVisual;\n}\n\n.Button-trailingAction {\n margin-right: calc(var(--base-size-4) * -1);\n}\n\n/* sizes */\n\n.Button--small {\n font-size: var(--text-body-size-small);\n height: var(--control-small-size);\n padding: 0 var(--control-small-paddingInline-condensed);\n gap: var(--control-small-gap);\n\n & .Button-label {\n line-height: var(--text-body-lineHeight-small);\n }\n\n & .Button-content {\n & > :not(:last-child) {\n margin-right: var(--control-small-gap);\n }\n }\n}\n\n.Button--large {\n height: var(--control-large-size);\n padding: 0 var(--control-large-paddingInline-spacious);\n gap: var(--control-large-gap);\n\n & .Button-label {\n line-height: var(--text-body-lineHeight-large);\n }\n\n & .Button-content {\n & > :not(:last-child) {\n margin-right: var(--control-large-gap);\n }\n }\n}\n\n.Button--fullWidth {\n width: 100%;\n}\n\n/* variants */\n\n/* primary */\n.Button--primary {\n color: var(--button-primary-fgColor-rest);\n fill: var(--button-primary-iconColor-rest);\n background-color: var(--button-primary-bgColor-rest);\n border-color: var(--button-primary-borderColor-rest);\n box-shadow: var(--shadow-resting-small, var(--color-btn-primary-shadow));\n\n &:hover:not(:disabled) {\n background-color: var(--button-primary-bgColor-hover);\n border-color: var(--button-primary-borderColor-hover);\n }\n\n /* fallback :focus state */\n &:focus {\n @mixin focusOutlineOnEmphasis;\n\n /* remove fallback :focus if :focus-visible is supported */\n &:not(:focus-visible) {\n outline: solid 1px transparent;\n box-shadow: none;\n }\n }\n\n /* default focus state */\n &:focus-visible {\n @mixin focusOutlineOnEmphasis;\n }\n\n &:active:not(:disabled),\n &[aria-pressed='true'] {\n background-color: var(--button-primary-bgColor-active);\n box-shadow: var(--button-primary-shadow-selected);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--button-primary-fgColor-disabled);\n background-color: var(--button-primary-bgColor-disabled);\n border-color: var(--button-primary-borderColor-disabled);\n fill: var(--button-primary-fgColor-disabled);\n }\n\n & .Counter {\n color: inherit;\n background-color: var(--buttonCounter-primary-bgColor-rest);\n }\n}\n\n/* default (secondary) */\n.Button--secondary {\n color: var(--button-default-fgColor-rest);\n fill: var(--fgColor-muted); /* help this */\n background-color: var(--button-default-bgColor-rest);\n border-color: var(--button-default-borderColor-rest);\n box-shadow: var(--button-default-shadow-resting), var(--button-default-shadow-inset);\n\n &:hover:not(:disabled) {\n background-color: var(--button-default-bgColor-hover);\n border-color: var(--button-default-borderColor-hover);\n }\n\n &:active:not(:disabled) {\n background-color: var(--button-default-bgColor-active);\n border-color: var(--button-default-borderColor-active);\n }\n\n &[aria-pressed='true'] {\n background-color: var(--button-default-bgColor-selected);\n box-shadow: var(--shadow-inset);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--control-fgColor-disabled);\n background-color: var(--button-default-bgColor-disabled);\n border-color: var(--button-default-borderColor-disabled);\n fill: var(--control-fgColor-disabled);\n }\n}\n\n.Button--invisible {\n color: var(--button-default-fgColor-rest);\n\n &.Button--iconOnly {\n color: var(--button-invisible-iconColor-rest, var(--color-fg-muted));\n }\n\n &:hover:not(:disabled) {\n background-color: var(--button-invisible-bgColor-hover);\n\n & .Button-visual {\n color: var(--button-invisible-iconColor-hover, var(--color-fg-default));\n }\n }\n\n &[aria-pressed='true'],\n &:active:not(:disabled) {\n background-color: var(--button-invisible-bgColor-active);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--button-invisible-fgColor-disabled);\n background-color: var(--button-invisible-bgColor-disabled);\n border-color: var(--button-invisible-borderColor-disabled);\n fill: var(--button-invisible-fgColor-disabled);\n }\n\n /* if button has no visuals, use link blue for text */\n &.Button--invisible-noVisuals .Button-label {\n color: var(--button-invisible-fgColor-rest);\n }\n\n & .Button-visual {\n color: var(--button-invisible-iconColor-rest, var(--color-fg-muted));\n\n & .Counter {\n color: var(--fgColor-default);\n }\n }\n}\n\n.Button--link {\n color: var(--fgColor-link);\n fill: var(--fgColor-link);\n display: inline-block;\n font-size: inherit;\n border: none;\n height: unset;\n padding: 0;\n\n &:hover:not(:disabled) {\n text-decoration: underline;\n }\n\n &:focus-visible,\n &:focus {\n outline-offset: 2px;\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--control-fgColor-disabled);\n background-color: transparent;\n border-color: transparent;\n fill: var(--control-fgColor-disabled);\n }\n}\n\n/* danger */\n.Button--danger {\n color: var(--button-danger-fgColor-rest);\n fill: var(--button-danger-iconColor-rest);\n background-color: var(--button-danger-bgColor-rest);\n border-color: var(--button-danger-borderColor-rest);\n box-shadow: var(--button-default-shadow-resting), var(--button-default-shadow-inset);\n\n &:hover:not(:disabled) {\n color: var(--button-danger-fgColor-hover);\n fill: var(--button-danger-fgColor-hover);\n background-color: var(--button-danger-bgColor-hover);\n border-color: var(--button-danger-borderColor-hover);\n box-shadow: var(--shadow-resting-small);\n\n & .Counter {\n color: var(--buttonCounter-danger-fgColor-hover);\n background-color: var(--buttonCounter-danger-bgColor-hover);\n }\n }\n\n &:active:not(:disabled),\n &[aria-pressed='true'] {\n color: var(--button-danger-fgColor-active);\n fill: var(--button-danger-fgColor-active);\n background-color: var(--button-danger-bgColor-active);\n border-color: var(--button-danger-borderColor-active);\n box-shadow: var(--button-danger-shadow-selected);\n }\n\n &:disabled,\n &[aria-disabled='true'] {\n color: var(--button-danger-fgColor-disabled);\n fill: var(--button-danger-fgColor-disabled);\n background-color: var(--button-danger-bgColor-disabled);\n border-color: var(--button-default-borderColor-disabled);\n\n & .Counter {\n color: var(--buttonCounter-danger-fgColor-disabled);\n background-color: var(--buttonCounter-danger-bgColor-disabled);\n }\n }\n\n & .Counter {\n color: var(--buttonCounter-danger-fgColor-rest);\n background-color: var(--buttonCounter-danger-bgColor-rest);\n }\n}\n\n.Button--iconOnly {\n display: inline-grid;\n place-content: center;\n padding: unset;\n width: var(--control-medium-size);\n\n &.Button--small {\n width: var(--control-small-size);\n }\n\n &.Button--large {\n width: var(--control-large-size);\n }\n}\n",null,"/* outline with fg box-shadow for buttons */\n@define-mixin focusOutlineOnEmphasis $outlineOffset: -2px, $outlineColor: var(--focus-outlineColor) {\n outline: 2px solid $outlineColor;\n outline-offset: $outlineOffset;\n box-shadow: inset 0 0 0 3px var(--fgColor-onEmphasis);\n}\n"]}
@@ -47,11 +47,15 @@
47
47
  transition: none;
48
48
  }
49
49
 
50
- &:disabled,
51
- &[aria-disabled='true'] {
50
+ &:disabled {
52
51
  cursor: not-allowed;
53
52
  box-shadow: none;
54
53
  }
54
+
55
+ &[aria-disabled='true'] {
56
+ cursor: default;
57
+ box-shadow: none;
58
+ }
55
59
  }
56
60
 
57
61
  .Button-withTooltip {
@@ -9,7 +9,7 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
9
9
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
10
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
11
  };
12
- var _FocusGroupElement_instances, _FocusGroupElement_abortController, _FocusGroupElement_items_get;
12
+ var _FocusGroupElement_instances, _FocusGroupElement_retainSignal, _FocusGroupElement_abortController, _FocusGroupElement_items_get;
13
13
  import '@oddbird/popover-polyfill';
14
14
  const validSelectors = ['[role="menuitem"]', '[role="menuitemcheckbox"]', '[role="menuitemradio"]'];
15
15
  const menuItemSelector = validSelectors.map(selector => `:not([hidden]) > ${selector}`).join(', ');
@@ -19,6 +19,7 @@ export default class FocusGroupElement extends HTMLElement {
19
19
  constructor() {
20
20
  super(...arguments);
21
21
  _FocusGroupElement_instances.add(this);
22
+ _FocusGroupElement_retainSignal.set(this, null);
22
23
  _FocusGroupElement_abortController.set(this, null);
23
24
  }
24
25
  get nowrap() {
@@ -57,11 +58,35 @@ export default class FocusGroupElement extends HTMLElement {
57
58
  (_a = __classPrivateFieldGet(this, _FocusGroupElement_abortController, "f")) === null || _a === void 0 ? void 0 : _a.abort();
58
59
  }
59
60
  handleEvent(event) {
61
+ var _a;
60
62
  const { direction, nowrap } = this;
61
63
  if (event.type === 'focusin') {
62
64
  if (this.retain && event.target instanceof Element && event.target.matches(menuItemSelector)) {
65
+ (_a = __classPrivateFieldGet(this, _FocusGroupElement_retainSignal, "f")) === null || _a === void 0 ? void 0 : _a.abort();
66
+ const { signal } = (__classPrivateFieldSet(this, _FocusGroupElement_retainSignal, new AbortController(), "f"));
63
67
  for (const item of __classPrivateFieldGet(this, _FocusGroupElement_instances, "a", _FocusGroupElement_items_get)) {
64
68
  item.setAttribute('tabindex', item === event.target ? '0' : '-1');
69
+ const popover = event.target.closest('[popover]');
70
+ if (item === event.target && (popover === null || popover === void 0 ? void 0 : popover.popover) === 'auto' && popover.closest('focus-group') === this) {
71
+ popover.addEventListener('toggle', (toggleEvent) => {
72
+ var _a, _b;
73
+ if (!(toggleEvent.target instanceof Element))
74
+ return;
75
+ if (toggleEvent.newState === 'closed') {
76
+ (_a = __classPrivateFieldGet(this, _FocusGroupElement_retainSignal, "f")) === null || _a === void 0 ? void 0 : _a.abort();
77
+ item.setAttribute('tabindex', '-1');
78
+ if (popover.id) {
79
+ const invoker = this.querySelector(`[popovertarget="${popover.id}"]`);
80
+ if (invoker) {
81
+ invoker.setAttribute('tabindex', '0');
82
+ }
83
+ else {
84
+ (_b = __classPrivateFieldGet(this, _FocusGroupElement_instances, "a", _FocusGroupElement_items_get)[0]) === null || _b === void 0 ? void 0 : _b.setAttribute('tabindex', '0');
85
+ }
86
+ }
87
+ }
88
+ }, { signal });
89
+ }
65
90
  }
66
91
  }
67
92
  }
@@ -121,7 +146,7 @@ export default class FocusGroupElement extends HTMLElement {
121
146
  let el = focusEl;
122
147
  do {
123
148
  el = el.closest(`[popover]:not(:popover-open)`);
124
- if ((el === null || el === void 0 ? void 0 : el.popover) === 'auto') {
149
+ if ((el === null || el === void 0 ? void 0 : el.popover) === 'auto' && !['ArrowRight', 'ArrowLeft'].includes(event.key)) {
125
150
  el.showPopover();
126
151
  }
127
152
  el = (el === null || el === void 0 ? void 0 : el.parentElement) || null;
@@ -131,7 +156,7 @@ export default class FocusGroupElement extends HTMLElement {
131
156
  }
132
157
  }
133
158
  }
134
- _FocusGroupElement_abortController = new WeakMap(), _FocusGroupElement_instances = new WeakSet(), _FocusGroupElement_items_get = function _FocusGroupElement_items_get() {
159
+ _FocusGroupElement_retainSignal = new WeakMap(), _FocusGroupElement_abortController = new WeakMap(), _FocusGroupElement_instances = new WeakSet(), _FocusGroupElement_items_get = function _FocusGroupElement_items_get() {
135
160
  return this.querySelectorAll(menuItemSelector);
136
161
  };
137
162
  if (!customElements.get('focus-group')) {
@@ -8,6 +8,8 @@ const getMnemonicFor = (item: Element) => item.textContent?.trim()[0].toLowerCas
8
8
  const printable = /^\S$/
9
9
 
10
10
  export default class FocusGroupElement extends HTMLElement {
11
+ #retainSignal: AbortController | null = null
12
+
11
13
  get nowrap(): boolean {
12
14
  return this.hasAttribute('nowrap')
13
15
  }
@@ -60,8 +62,32 @@ export default class FocusGroupElement extends HTMLElement {
60
62
  const {direction, nowrap} = this
61
63
  if (event.type === 'focusin') {
62
64
  if (this.retain && event.target instanceof Element && event.target.matches(menuItemSelector)) {
65
+ this.#retainSignal?.abort()
66
+ const {signal} = (this.#retainSignal = new AbortController())
63
67
  for (const item of this.#items) {
64
68
  item.setAttribute('tabindex', item === event.target ? '0' : '-1')
69
+ const popover = event.target.closest<HTMLElement>('[popover]')
70
+ if (item === event.target && popover?.popover === 'auto' && popover.closest('focus-group') === this) {
71
+ popover.addEventListener(
72
+ 'toggle',
73
+ (toggleEvent: Event) => {
74
+ if (!(toggleEvent.target instanceof Element)) return
75
+ if ((toggleEvent as ToggleEvent).newState === 'closed') {
76
+ this.#retainSignal?.abort()
77
+ item.setAttribute('tabindex', '-1')
78
+ if (popover.id) {
79
+ const invoker = this.querySelector(`[popovertarget="${popover.id}"]`)
80
+ if (invoker) {
81
+ invoker.setAttribute('tabindex', '0')
82
+ } else {
83
+ this.#items[0]?.setAttribute('tabindex', '0')
84
+ }
85
+ }
86
+ }
87
+ },
88
+ {signal}
89
+ )
90
+ }
65
91
  }
66
92
  }
67
93
  } else if (event instanceof KeyboardEvent) {
@@ -111,7 +137,7 @@ export default class FocusGroupElement extends HTMLElement {
111
137
  let el: HTMLElement | null = focusEl
112
138
  do {
113
139
  el = el.closest(`[popover]:not(:popover-open)`)
114
- if (el?.popover === 'auto') {
140
+ if (el?.popover === 'auto' && !['ArrowRight', 'ArrowLeft'].includes(event.key)) {
115
141
  el.showPopover()
116
142
  }
117
143
  el = el?.parentElement || null
@@ -8,7 +8,9 @@ module Primer
8
8
  # Do not add to this list for any other reason!
9
9
  IGNORED_PREVIEWS = [
10
10
  Primer::Beta::MarkdownPreview,
11
- Primer::Beta::AutoCompleteItemPreview
11
+ Primer::Beta::AutoCompleteItemPreview,
12
+ Primer::Alpha::RadioButtonPreview,
13
+ Primer::Alpha::CheckBoxPreview
12
14
  ].freeze
13
15
 
14
16
  # Skip `:region` which relates to preview page structure rather than individual component.
@@ -3,6 +3,7 @@
3
3
  # :nocov:
4
4
 
5
5
  require "json"
6
+ require "kramdown"
6
7
 
7
8
  module Primer
8
9
  module Static
@@ -35,7 +36,7 @@ module Primer
35
36
  # rubocop:disable Style/IfUnlessModifier
36
37
  "description" =>
37
38
  if slot_method.base_docstring.to_s.present?
38
- view_context.render(inline: slot_method.base_docstring)
39
+ render_erb_ignoring_markdown_code_fences(slot_method.base_docstring)
39
40
  end,
40
41
  # rubocop:enable Style/IfUnlessModifier
41
42
  "parameters" => serialize_params(param_tags, component)
@@ -57,7 +58,7 @@ module Primer
57
58
 
58
59
  {
59
60
  "name" => mtd.name,
60
- "description" => view_context.render(inline: mtd.base_docstring),
61
+ "description" => render_erb_ignoring_markdown_code_fences(mtd.base_docstring),
61
62
  "parameters" => serialize_params(param_tags, component)
62
63
  }
63
64
  end
@@ -66,7 +67,7 @@ module Primer
66
67
  if component == Primer::BaseComponent
67
68
  docs.base_docstring
68
69
  else
69
- view_context.render(inline: docs.base_docstring)
70
+ render_erb_ignoring_markdown_code_fences(docs.base_docstring)
70
71
  end
71
72
 
72
73
  memo[component] = {
@@ -119,7 +120,7 @@ module Primer
119
120
  component: "BaseComponent",
120
121
  fully_qualified_name: "Primer::BaseComponent",
121
122
  description_md: docs.base_docstring,
122
- args_md: view_context.render(inline: docs.constructor.base_docstring)
123
+ args_md: render_erb_ignoring_markdown_code_fences(docs.constructor.base_docstring)
123
124
  }
124
125
  end
125
126
 
@@ -131,7 +132,7 @@ module Primer
131
132
  "name" => tag.name,
132
133
  "type" => tag.types&.join(", ") || "",
133
134
  "default" => default_value,
134
- "description" => view_context.render(inline: tag.text.squish)
135
+ "description" => render_erb_ignoring_markdown_code_fences(tag.text.squish)
135
136
  }
136
137
  end
137
138
  end
@@ -151,6 +152,86 @@ module Primer
151
152
  end
152
153
  end
153
154
 
155
+ # Renders ERB code to a string, ignoring markdown code fences. For example, consider the
156
+ # following ERB code inside a markdown document:
157
+ #
158
+ # ### Heading
159
+ # ```erb
160
+ # <%= render(SomeComponent.new) %>
161
+ # ```
162
+ #
163
+ # <%= some_func(a, b) %>
164
+ #
165
+ # The ERB renderer does not understand that the fenced code, i.e. the part inside the triple
166
+ # backticks, should not be rendered. It sees the ERB tags both inside and outside the fence
167
+ # and renders them both.
168
+ #
169
+ # This method renders ERB tags in a markdown string, ignoring any fenced code blocks, so as
170
+ # to prevent rendering fenced ERB code.
171
+ #
172
+ def render_erb_ignoring_markdown_code_fences(markdown_str)
173
+ return view_context.render(inline: markdown_str) unless markdown_str.include?("```")
174
+
175
+ # identify all fenced code blocks in markdown string
176
+ code_ranges = find_fenced_code_ranges_in(markdown_str)
177
+
178
+ # replace code fences with placeholders
179
+ de_fenced_markdown_str = markdown_str.dup.tap do |memo|
180
+ code_ranges.reverse_each.with_index do |code_range, idx|
181
+ memo[code_range] = "<!--codefence#{idx}-->"
182
+ end
183
+ end
184
+
185
+ # Render ERB tags. The only ones left will explicitly exist _outside_ markdown code fences.
186
+ rendered_str = view_context.render(inline: de_fenced_markdown_str)
187
+
188
+ # replace placeholders with original code fences
189
+ code_ranges.reverse_each.with_index do |code_range, idx|
190
+ rendered_str.sub!("<!--codefence#{idx}-->", markdown_str[code_range])
191
+ end
192
+
193
+ rendered_str
194
+ end
195
+
196
+ def find_fenced_code_ranges_in(str)
197
+ doc = Kramdown::Document.new(str)
198
+ line_starts = find_line_starts_in(str)
199
+
200
+ [].tap do |code_ranges|
201
+ each_codespan_in(doc.root) do |node|
202
+ options = node.options
203
+ delimiter = options[:codespan_delimiter]
204
+ next unless delimiter.start_with?("```")
205
+
206
+ start_pos = line_starts[options[:location]]
207
+ end_pos = start_pos + node.value.size + delimiter.size
208
+ end_pos = str.index("```", end_pos) + 3
209
+
210
+ code_ranges << (start_pos...end_pos)
211
+ end
212
+ end
213
+ end
214
+
215
+ def find_line_starts_in(str)
216
+ line_counter = 2
217
+
218
+ { 1 => 0 }.tap do |memo|
219
+ str.scan(/\r?\n/) do
220
+ memo[line_counter] = Regexp.last_match.end(0)
221
+ line_counter += 1
222
+ end
223
+ end
224
+ end
225
+
226
+ def each_codespan_in(node, &block)
227
+ return unless node.respond_to?(:children)
228
+
229
+ node.children.each do |child|
230
+ yield child if child.type == :codespan
231
+ each_codespan_in(child, &block)
232
+ end
233
+ end
234
+
154
235
  def registry
155
236
  @registry ||= Primer::Yard::Registry.make
156
237
  end
@@ -5,8 +5,8 @@ module Primer
5
5
  module ViewComponents
6
6
  module VERSION
7
7
  MAJOR = 0
8
- MINOR = 12
9
- PATCH = 1
8
+ MINOR = 13
9
+ PATCH = 0
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH].join(".")
12
12
  end
@@ -0,0 +1,31 @@
1
+ <%= render(Primer::Alpha::ActionMenu.new(select_variant: :single)) do |menu| %>
2
+ <% menu.with_show_button { "Group By" } %>
3
+ <% menu.with_item(
4
+ label: "Repository",
5
+ href: action_menu_form_action_path(format: route_format),
6
+ form_arguments: {
7
+ method: :post,
8
+ inputs: [{
9
+ name: "query",
10
+ value: "query"
11
+ }, {
12
+ name: "foo", # use "foo" here because that's what the controller expects
13
+ value: "group-by-repository",
14
+ }],
15
+ }
16
+ ) %>
17
+ <% menu.with_item(
18
+ label: "Date",
19
+ href: action_menu_form_action_path(format: route_format),
20
+ form_arguments: {
21
+ method: :post,
22
+ inputs: [{
23
+ name: "query",
24
+ value: "query"
25
+ }, {
26
+ name: "foo", # use "foo" here because that's what the controller expects
27
+ value: "sort-by-date"
28
+ }]
29
+ }
30
+ ) %>
31
+ <% end %>