@redvars/peacock 3.6.3 → 3.7.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 (179) hide show
  1. package/dist/ButtonConstants-D06bY4uy.js +114 -0
  2. package/dist/ButtonConstants-D06bY4uy.js.map +1 -0
  3. package/dist/{BaseHyperlinkMixin-BNuwbiEf.js → NativeHyperlinkMixin-DrYXyfMQ.js} +8 -10
  4. package/dist/NativeHyperlinkMixin-DrYXyfMQ.js.map +1 -0
  5. package/dist/assets/components.css +1 -1
  6. package/dist/assets/components.css.map +1 -1
  7. package/dist/assets/styles.css +1 -1
  8. package/dist/assets/styles.css.map +1 -1
  9. package/dist/{button-colors-Cg6oxiz-.js → button-colors-Dwnez1tR.js} +201 -186
  10. package/dist/button-colors-Dwnez1tR.js.map +1 -0
  11. package/dist/button-group.js +8 -8
  12. package/dist/button-group.js.map +1 -1
  13. package/dist/button.js +224 -124
  14. package/dist/button.js.map +1 -1
  15. package/dist/calendar-column-view.js +0 -1
  16. package/dist/calendar-column-view.js.map +1 -1
  17. package/dist/calendar-month-view.js +0 -1
  18. package/dist/calendar-month-view.js.map +1 -1
  19. package/dist/card-content.js +0 -1
  20. package/dist/card-content.js.map +1 -1
  21. package/dist/card.js +96 -90
  22. package/dist/card.js.map +1 -1
  23. package/dist/cb-compound-expression.js +4 -1
  24. package/dist/cb-compound-expression.js.map +1 -1
  25. package/dist/cb-divider.js +0 -1
  26. package/dist/cb-divider.js.map +1 -1
  27. package/dist/cb-expression.js +0 -2
  28. package/dist/cb-expression.js.map +1 -1
  29. package/dist/cb-predicate.js +0 -1
  30. package/dist/cb-predicate.js.map +1 -1
  31. package/dist/code-highlighter.js +23 -6
  32. package/dist/code-highlighter.js.map +1 -1
  33. package/dist/custom-elements-jsdocs.json +5102 -18408
  34. package/dist/custom-elements.json +19630 -20205
  35. package/dist/fab.js +181 -117
  36. package/dist/fab.js.map +1 -1
  37. package/dist/{flow-designer-node-9Bqyn6qx.js → flow-designer-node-BWrPuxAR.js} +1 -2
  38. package/dist/flow-designer-node-BWrPuxAR.js.map +1 -0
  39. package/dist/flow-designer-node.js +1 -1
  40. package/dist/flow-designer.js +5 -5
  41. package/dist/icon-button-DJ0kZXYr.js +318 -0
  42. package/dist/icon-button-DJ0kZXYr.js.map +1 -0
  43. package/dist/index.js +8 -8
  44. package/dist/{navigation-rail-DAUuJ_Yp.js → navigation-rail-CM_svs5_.js} +511 -295
  45. package/dist/navigation-rail-CM_svs5_.js.map +1 -0
  46. package/dist/observe-slot-change-D8Xg-kSS.js +60 -0
  47. package/dist/observe-slot-change-D8Xg-kSS.js.map +1 -0
  48. package/dist/peacock-loader.js +7 -7
  49. package/dist/peacock-loader.js.map +1 -1
  50. package/dist/popover-content.js +0 -1
  51. package/dist/popover-content.js.map +1 -1
  52. package/dist/search.js +4 -1
  53. package/dist/search.js.map +1 -1
  54. package/dist/src/__controllers/attachable-controller.d.ts +109 -0
  55. package/dist/src/__mixins/{BaseButtonMixin.d.ts → NativeButtonMixin.d.ts} +3 -3
  56. package/dist/src/__mixins/{BaseHyperlinkMixin.d.ts → NativeHyperlinkMixin.d.ts} +3 -4
  57. package/dist/src/__utils/is-link.d.ts +1 -0
  58. package/dist/src/__utils/observe-slot-change.d.ts +1 -1
  59. package/dist/src/accordion/accordion-item.d.ts +0 -1
  60. package/dist/src/breadcrumb/breadcrumb-item/breadcrumb-item.d.ts +0 -1
  61. package/dist/src/button/ButtonConstants.d.ts +1 -0
  62. package/dist/src/button/GroupButtonInterface.d.ts +4 -0
  63. package/dist/src/button/button/button.d.ts +32 -7
  64. package/dist/src/button/button-group/button-group.d.ts +2 -1
  65. package/dist/src/button/icon-button/icon-button.d.ts +26 -5
  66. package/dist/src/button/index.d.ts +1 -1
  67. package/dist/src/calendar/calendar-column-view.d.ts +0 -1
  68. package/dist/src/calendar/calendar-month-view.d.ts +0 -1
  69. package/dist/src/card/card-content.d.ts +0 -1
  70. package/dist/src/card/card.d.ts +9 -6
  71. package/dist/src/chip/chip/chip.d.ts +22 -3
  72. package/dist/src/condition-builder/cb-compound-expression.d.ts +0 -1
  73. package/dist/src/condition-builder/cb-divider.d.ts +0 -1
  74. package/dist/src/condition-builder/cb-expression.d.ts +0 -1
  75. package/dist/src/condition-builder/cb-predicate.d.ts +0 -1
  76. package/dist/src/fab/fab.d.ts +20 -6
  77. package/dist/src/flow-designer/flow-designer-node.d.ts +0 -1
  78. package/dist/src/focus-ring/focus-ring.d.ts +26 -20
  79. package/dist/src/item/item.d.ts +2 -1
  80. package/dist/src/link/link.d.ts +1 -1
  81. package/dist/src/list/list-item.d.ts +1 -2
  82. package/dist/src/menu/menu-item/menu-item.d.ts +1 -2
  83. package/dist/src/menu/sub-menu/sub-menu.d.ts +0 -1
  84. package/dist/src/navigation-rail/navigation-rail-item.d.ts +0 -2
  85. package/dist/src/popover/popover-content.d.ts +0 -1
  86. package/dist/src/ripple/ripple.d.ts +9 -1
  87. package/dist/src/segmented-button/segmented-button.d.ts +0 -1
  88. package/dist/src/select/option.d.ts +0 -1
  89. package/dist/src/sidebar-menu/sidebar-menu-item.d.ts +0 -1
  90. package/dist/src/sidebar-menu/sidebar-sub-menu.d.ts +0 -1
  91. package/dist/src/tabs/tab-panel.d.ts +0 -1
  92. package/dist/src/tabs/tab.d.ts +4 -6
  93. package/dist/tsconfig.tsbuildinfo +1 -1
  94. package/package.json +4 -2
  95. package/readme.md +2 -2
  96. package/scss/components.scss +0 -1
  97. package/scss/mixin.scss +10 -13
  98. package/scss/styles.scss +1 -3
  99. package/src/__controllers/attachable-controller.ts +198 -0
  100. package/src/__mixins/NativeButtonMixin.ts +87 -0
  101. package/src/__mixins/{BaseHyperlinkMixin.ts → NativeHyperlinkMixin.ts} +15 -15
  102. package/src/__utils/is-link.ts +3 -0
  103. package/src/__utils/observe-slot-change.ts +46 -14
  104. package/src/accordion/accordion-item.scss +1 -1
  105. package/src/accordion/accordion-item.ts +0 -1
  106. package/src/breadcrumb/breadcrumb-item/breadcrumb-item.ts +0 -1
  107. package/src/button/ButtonConstants.ts +1 -0
  108. package/src/button/GroupButtonInterface.ts +4 -0
  109. package/src/button/button/button-colors.scss +2 -2
  110. package/src/button/button/button-layers.scss +124 -0
  111. package/src/button/button/button-sizes.scss +20 -42
  112. package/src/button/button/button.scss +72 -169
  113. package/src/button/button/button.ts +229 -78
  114. package/src/button/button/only-button.scss +13 -0
  115. package/src/button/button-group/button-group.ts +59 -17
  116. package/src/button/icon-button/icon-button-sizes.scss +6 -21
  117. package/src/button/icon-button/icon-button.ts +198 -93
  118. package/src/button/index.ts +1 -1
  119. package/src/calendar/calendar-column-view.ts +0 -1
  120. package/src/calendar/calendar-month-view.ts +0 -1
  121. package/src/card/card-content.ts +2 -3
  122. package/src/card/card.scss +87 -95
  123. package/src/card/card.ts +62 -60
  124. package/src/chip/chip/chip.scss +65 -70
  125. package/src/chip/chip/chip.ts +155 -56
  126. package/src/code-highlighter/code-highlighter.scss +1 -1
  127. package/src/code-highlighter/code-highlighter.ts +20 -5
  128. package/src/condition-builder/cb-compound-expression.scss +4 -0
  129. package/src/condition-builder/cb-compound-expression.ts +0 -1
  130. package/src/condition-builder/cb-divider.ts +0 -1
  131. package/src/condition-builder/cb-expression.scss +0 -1
  132. package/src/condition-builder/cb-expression.ts +0 -1
  133. package/src/condition-builder/cb-predicate.ts +0 -1
  134. package/src/elevation/elevation.scss +5 -1
  135. package/src/fab/fab-colors.scss +2 -2
  136. package/src/fab/fab-sizes.scss +24 -34
  137. package/src/fab/fab.scss +77 -71
  138. package/src/fab/fab.ts +141 -65
  139. package/src/flow-designer/flow-designer-node.ts +0 -1
  140. package/src/focus-ring/focus-ring.ts +81 -72
  141. package/src/item/item.scss +77 -66
  142. package/src/item/item.ts +61 -39
  143. package/src/link/link.scss +1 -10
  144. package/src/link/link.ts +4 -2
  145. package/src/list/list-item.ts +8 -8
  146. package/src/menu/menu-item/menu-item.ts +17 -8
  147. package/src/menu/sub-menu/sub-menu.ts +0 -1
  148. package/src/navigation-rail/navigation-rail-item.scss +5 -0
  149. package/src/navigation-rail/navigation-rail-item.ts +10 -15
  150. package/src/peacock-loader.ts +1 -1
  151. package/src/popover/popover-content.ts +0 -1
  152. package/src/ripple/ripple.ts +52 -20
  153. package/src/search/search.scss +3 -0
  154. package/src/segmented-button/segmented-button.ts +0 -1
  155. package/src/select/option.ts +0 -1
  156. package/src/sidebar-menu/sidebar-menu-item.ts +0 -1
  157. package/src/sidebar-menu/sidebar-sub-menu.ts +0 -1
  158. package/src/skeleton/skeleton.scss +5 -1
  159. package/src/tabs/tab-panel.ts +0 -1
  160. package/src/tabs/tab.ts +60 -70
  161. package/src/text/text.css-component.scss +3 -21
  162. package/src/tooltip/tooltip.scss +5 -8
  163. package/src/tooltip/tooltip.ts +1 -2
  164. package/dist/BaseButton-BNFAYn-S.js +0 -219
  165. package/dist/BaseButton-BNFAYn-S.js.map +0 -1
  166. package/dist/BaseHyperlinkMixin-BNuwbiEf.js.map +0 -1
  167. package/dist/button-colors-Cg6oxiz-.js.map +0 -1
  168. package/dist/flow-designer-node-9Bqyn6qx.js.map +0 -1
  169. package/dist/icon-button-AdJBEoNy.js +0 -251
  170. package/dist/icon-button-AdJBEoNy.js.map +0 -1
  171. package/dist/navigation-rail-DAUuJ_Yp.js.map +0 -1
  172. package/dist/observe-slot-change-BGJfgg2E.js +0 -31
  173. package/dist/observe-slot-change-BGJfgg2E.js.map +0 -1
  174. package/dist/src/button/BaseButton.d.ts +0 -28
  175. package/dist/src/focus-ring/FocusAttachableController.d.ts +0 -8
  176. package/src/__mixins/BaseButtonMixin.ts +0 -83
  177. package/src/button/BaseButton.ts +0 -113
  178. package/src/focus-ring/FocusAttachableController.ts +0 -28
  179. package/src/popover/tooltip.css-component.scss +0 -19
@@ -1,15 +1,26 @@
1
- import { html } from 'lit';
2
- import { property, state } from 'lit/decorators.js';
1
+ import { html, LitElement, nothing } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
3
  import { classMap } from 'lit/directives/class-map.js';
4
4
  import { ifDefined } from 'lit/directives/if-defined.js';
5
+ import { when } from 'lit/directives/when.js';
5
6
  import IndividualComponent from '@/IndividualComponent.js';
6
7
  import styles from './button.scss';
8
+ import onlyButton from './only-button.scss';
9
+ import buttonLayers from './button-layers.scss';
7
10
  import colorStyles from './button-colors.scss';
8
11
  import sizeStyles from './button-sizes.scss';
9
- import { observerSlotChangesWithCallback } from '@/__utils/observe-slot-change.js';
10
12
  import { throttle } from '@/__utils/throttle.js';
11
13
  import { spread } from '@/__directive/spread.js';
12
- import { BaseButton } from '../BaseButton.js';
14
+ import { isLink } from '@/__utils/is-link.js';
15
+ import { observerSlotChangesWithCallback } from '@/__utils/observe-slot-change.js';
16
+ import NativeButtonMixin from '@/__mixins/NativeButtonMixin.js';
17
+ import NativeHyperlinkMixin from '@/__mixins/NativeHyperlinkMixin.js';
18
+ import { GroupButtonInterface } from '@/button/GroupButtonInterface.js';
19
+ import {
20
+ dispatchActivationClick,
21
+ isActivationClick,
22
+ } from '@/__utils/dispatch-event-utils.js';
23
+ import { DISABLED_REASON_ID } from '@/button/ButtonConstants.js';
13
24
 
14
25
  /**
15
26
  * @label Button
@@ -54,15 +65,24 @@ import { BaseButton } from '../BaseButton.js';
54
65
  * @tags display
55
66
  */
56
67
  @IndividualComponent
57
- export class Button extends BaseButton {
58
- static override styles = [styles, colorStyles, sizeStyles];
68
+ export class Button
69
+ extends NativeButtonMixin(NativeHyperlinkMixin(LitElement))
70
+ implements GroupButtonInterface
71
+ {
72
+ static override styles = [
73
+ buttonLayers,
74
+ styles,
75
+ onlyButton,
76
+ sizeStyles,
77
+ colorStyles,
78
+ ];
59
79
 
60
80
  /**
61
81
  * Icon alignment.
62
82
  * Possible values are `"start"`, `"end"`. Defaults to `"end"`.
63
83
  */
64
- @property({ attribute: 'icon-align' })
65
- iconAlign: 'start' | 'end' = 'end';
84
+ @property({ type: Boolean, reflect: true, attribute: 'trailing-icon' })
85
+ trailingIcon = false;
66
86
 
67
87
  /**
68
88
  * Button size.
@@ -71,9 +91,9 @@ export class Button extends BaseButton {
71
91
  @property({ reflect: true }) size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' = 'sm';
72
92
 
73
93
  /**
74
- * Type is preset of color and variant. Type will be only applied.
75
- *
76
- */
94
+ * Type is preset of color and variant. Type will be only applied.
95
+ *
96
+ */
77
97
  @property({ type: String }) type?: 'primary' | 'secondary' | 'tertiary';
78
98
 
79
99
  /**
@@ -86,7 +106,7 @@ export class Button extends BaseButton {
86
106
  * `"tonal"` is a light color button.
87
107
  * `"elevated"` is elevated button
88
108
  */
89
- @property() variant:
109
+ @property({ reflect: true }) variant:
90
110
  | 'elevated'
91
111
  | 'filled'
92
112
  | 'tonal'
@@ -111,15 +131,12 @@ export class Button extends BaseButton {
111
131
  @property({ reflect: true })
112
132
  configAria?: { [key: string]: any };
113
133
 
114
- @state()
115
- private slotHasContent = false;
116
-
117
134
  override focus() {
118
- this.buttonElement?.focus();
135
+ this.getControl()?.focus();
119
136
  }
120
137
 
121
138
  override blur() {
122
- this.buttonElement?.blur();
139
+ this.getControl()?.blur();
123
140
  }
124
141
 
125
142
  override firstUpdated() {
@@ -127,15 +144,34 @@ export class Button extends BaseButton {
127
144
  this.__dispatchClick,
128
145
  this.throttleDelay,
129
146
  );
130
- observerSlotChangesWithCallback(
131
- this.renderRoot.querySelector('slot'),
132
- hasContent => {
133
- this.slotHasContent = hasContent;
134
- this.requestUpdate();
135
- },
136
- );
137
147
 
138
148
  this.__convertTypeToVariantAndColor();
149
+ // Initialize slot presence tracking for smooth transitions when label/icon are added/removed
150
+ const iconSlot = this.renderRoot.querySelector(
151
+ 'slot[name="icon"]',
152
+ ) as HTMLSlotElement | null;
153
+ const labelSlot = this.renderRoot.querySelector(
154
+ 'slot.label',
155
+ ) as HTMLSlotElement | null;
156
+
157
+ // Use MutationObserver-based helper so we react to content/character changes
158
+ if (iconSlot) {
159
+ this.__iconSlotCleanup = observerSlotChangesWithCallback(
160
+ iconSlot,
161
+ has => {
162
+ this.toggleAttribute('has-icon', has);
163
+ },
164
+ );
165
+ }
166
+
167
+ if (labelSlot) {
168
+ this.__labelSlotCleanup = observerSlotChangesWithCallback(
169
+ labelSlot,
170
+ has => {
171
+ this.toggleAttribute('has-label', has);
172
+ },
173
+ );
174
+ }
139
175
  }
140
176
 
141
177
  __convertTypeToVariantAndColor() {
@@ -155,85 +191,200 @@ export class Button extends BaseButton {
155
191
  }
156
192
 
157
193
  override render() {
194
+ const buttonId = isLink(this) ? 'link' : 'button';
195
+
196
+ return html`
197
+ <wc-focus-ring class="focus-ring" for=${buttonId}></wc-focus-ring>
198
+ <wc-elevation class="elevation"></wc-elevation>
199
+ ${when(
200
+ this.variant === 'neo',
201
+ () => html`<div class="neo-background"></div>`,
202
+ )}
203
+ <div class="background"></div>
204
+ ${when(
205
+ this.variant === 'outlined' || this.variant === 'neo',
206
+ () => html`<div class="outline"></div>`,
207
+ )}
208
+ <wc-ripple class="ripple" for=${buttonId}></wc-ripple>
209
+ <wc-skeleton class="skeleton"></wc-skeleton>
210
+
211
+ ${this.renderButtonElement()} ${this.__renderTooltip()}
212
+ `;
213
+ }
214
+
215
+ renderButtonElement() {
216
+ const isElementLink = isLink(this);
158
217
 
159
218
  const cssClasses: any = {
160
219
  button: true,
161
- [`size-${this.size}`]: true,
162
- [`variant-${this.variant}`]: true,
163
- [`color-${this.color}`]: true,
164
- disabled: this.disabled || this.softDisabled,
165
- pressed: this.isPressed,
166
- 'has-content': this.slotHasContent,
167
- 'show-skeleton': this.skeleton,
168
- [`icon-align-${this.iconAlign}`]: true,
220
+ 'native-button': !isElementLink,
221
+ 'native-link': isElementLink,
222
+ 'trailing-icon': this.trailingIcon,
169
223
  };
170
224
 
171
- if (!this.__isLink()) {
172
- cssClasses['native-button'] = true;
173
-
174
- return html`<button
175
- class=${classMap(cssClasses)}
176
- id="button"
177
- type=${this.htmlType}
178
- @click=${this.__dispatchClickWithThrottle}
179
- @mousedown=${this.__handlePress}
180
- @keydown=${this.__handlePress}
181
- @keyup=${this.__handlePress}
182
-
183
- aria-describedby=${ifDefined(this.softDisabled ? BaseButton.DISABLED_REASON_ID : undefined)}
184
- ?aria-disabled=${this.softDisabled}
185
-
186
- ?disabled=${this.disabled}
187
- ${spread(this.configAria)}
188
- >
189
- ${this.renderButtonContent()}
190
- </button>
191
- ${this.__renderTooltip()}`;
192
- } else {
193
- cssClasses['native-link'] = true;
225
+ if (isElementLink) {
194
226
  return html`<a
195
227
  class=${classMap(cssClasses)}
196
- id="button"
228
+ id="link"
197
229
  href=${this.href}
198
230
  target=${this.target}
199
231
  tabindex=${this.disabled ? '-1' : '0'}
200
-
201
232
  @click=${this.__dispatchClick}
202
233
  @mousedown=${this.__handlePress}
203
234
  @keydown=${this.__handlePress}
204
235
  @keyup=${this.__handlePress}
205
236
  role="button"
206
-
207
- aria-describedby=${ifDefined(this.softDisabled ? BaseButton.DISABLED_REASON_ID : undefined)}
237
+ aria-describedby=${ifDefined(
238
+ this.softDisabled ? DISABLED_REASON_ID : undefined,
239
+ )}
208
240
  ?aria-disabled=${this.softDisabled}
209
-
210
241
  ${spread(this.configAria)}
211
242
  >
212
243
  ${this.renderButtonContent()}
213
- </a>
214
- ${this.__renderTooltip()}`;
244
+ </a>`;
215
245
  }
246
+ return html`<button
247
+ class=${classMap(cssClasses)}
248
+ id="button"
249
+ type=${this.htmlType}
250
+ @click=${this.__dispatchClickWithThrottle}
251
+ @mousedown=${this.__handlePress}
252
+ @keydown=${this.__handlePress}
253
+ @keyup=${this.__handlePress}
254
+ aria-describedby=${ifDefined(
255
+ this.softDisabled ? DISABLED_REASON_ID : undefined,
256
+ )}
257
+ ?aria-disabled=${this.softDisabled}
258
+ ?disabled=${this.disabled}
259
+ ${spread(this.configAria)}
260
+ >
261
+ ${this.renderButtonContent()}
262
+ </button>
263
+ ${this.__renderTooltip()}`;
216
264
  }
217
265
 
218
266
  renderButtonContent() {
219
- return html`
220
- <wc-focus-ring class="focus-ring" for='button'></wc-focus-ring>
221
- <wc-elevation class="elevation"></wc-elevation>
222
- <div class="neo-background"></div>
223
- <div class="background"></div>
224
- <div class="outline"></div>
225
- <wc-ripple class="ripple"></wc-ripple>
226
- <wc-skeleton class="skeleton"></wc-skeleton>
267
+ return html` <slot class="icon-slot" name="icon"></slot>
268
+ <slot class="label"></slot>
269
+ <div class="touch"></div>
270
+
271
+ ${this.__renderDisabledReason(this.softDisabled)}`;
272
+ }
227
273
 
228
- <div class="button-content">
229
- <div class="slot-container">
230
- <slot></slot>
231
- </div>
274
+ @property({ type: Boolean, reflect: true }) skeleton: boolean = false;
232
275
 
233
- <slot name="icon"></slot>
234
- </div>
276
+ @property({ type: Boolean, reflect: true }) toggle: boolean = false;
235
277
 
236
- ${this.__renderDisabledReason(this.softDisabled)}
237
- `;
278
+ @property({ type: Boolean, reflect: true }) selected: boolean = false;
279
+
280
+ /**
281
+ * Sets the delay for throttle in milliseconds. Defaults to 200 milliseconds.
282
+ */
283
+ @property() throttleDelay = 200;
284
+
285
+ @property() tooltip?: string;
286
+
287
+ /**
288
+ * States
289
+ */
290
+ @property({ type: Boolean, reflect: true })
291
+ pressed = false;
292
+
293
+ // Query the internal control (button or link) on demand instead of
294
+ // keeping a persistent query reference.
295
+
296
+ // cleanup functions returned by observerSlotChangesWithCallback
297
+ private __iconSlotCleanup: (() => void) | null = null;
298
+
299
+ private __labelSlotCleanup: (() => void) | null = null;
300
+
301
+ override connectedCallback() {
302
+ super.connectedCallback();
303
+ this.addEventListener('click', this.__dispatchClickWithThrottle);
304
+ window.addEventListener('mouseup', this.__handlePress);
305
+ }
306
+
307
+ override disconnectedCallback() {
308
+ // disconnect slot observers first to avoid callbacks during teardown
309
+ try {
310
+ this.__iconSlotCleanup?.();
311
+ } catch (e) {
312
+ /* ignore */
313
+ }
314
+ try {
315
+ this.__labelSlotCleanup?.();
316
+ } catch (e) {
317
+ /* ignore */
318
+ }
319
+
320
+ window.removeEventListener('mouseup', this.__handlePress);
321
+ this.removeEventListener('click', this.__dispatchClickWithThrottle);
322
+ super.disconnectedCallback();
323
+ }
324
+
325
+ __handlePress = (event: KeyboardEvent | MouseEvent) => {
326
+ if (this.disabled || this.skeleton || this.softDisabled) return;
327
+ this.pressed =
328
+ (event instanceof KeyboardEvent &&
329
+ event.type === 'keydown' &&
330
+ (event.key === 'Enter' || event.key === ' ')) ||
331
+ event.type === 'mousedown';
332
+ };
333
+
334
+ __dispatchClickWithThrottle: (event: MouseEvent | KeyboardEvent) => void =
335
+ event => {
336
+ this.__dispatchClick(event);
337
+ };
338
+
339
+ __dispatchClick = (event: MouseEvent | KeyboardEvent) => {
340
+ // If the button is soft-disabled or a disabled link, we need to explicitly
341
+ // prevent the click from propagating to other event listeners as well as
342
+ // prevent the default action.
343
+ if (this.softDisabled || (this.disabled && this.href) || this.skeleton) {
344
+ event.stopImmediatePropagation();
345
+ event.preventDefault();
346
+ return;
347
+ }
348
+
349
+ const control = this.getControl();
350
+
351
+ if (!isActivationClick(event) || !control) {
352
+ return;
353
+ }
354
+
355
+ if (this.toggle) {
356
+ this.selected = !this.selected;
357
+ }
358
+
359
+ this.focus();
360
+ dispatchActivationClick(control);
361
+ };
362
+
363
+ private getControl(): HTMLElement | null {
364
+ return (
365
+ (this.renderRoot?.querySelector('#button') as HTMLElement | null) ??
366
+ (this.renderRoot?.querySelector('#link') as HTMLElement | null)
367
+ );
368
+ }
369
+
370
+ __renderDisabledReason(softDisabled: boolean) {
371
+ if (softDisabled)
372
+ return html`<div
373
+ id=${DISABLED_REASON_ID}
374
+ role="tooltip"
375
+ aria-label=${this.disabledReason}
376
+ class="screen-reader-only"
377
+ >
378
+ ${this.disabledReason}
379
+ </div>`;
380
+ return nothing;
381
+ }
382
+
383
+ __renderTooltip() {
384
+ if (this.tooltip) {
385
+ const buttonId = isLink(this) ? 'link' : 'button';
386
+ return html`<wc-tooltip class="tooltip" for=${buttonId}>${this.tooltip}</wc-tooltip>`;
387
+ }
388
+ return nothing;
238
389
  }
239
390
  }
@@ -0,0 +1,13 @@
1
+
2
+ /* When both icon and label are present, apply the configured spacing */
3
+ :host([has-icon][has-label]) .button {
4
+ gap: var(--private-button-icon-label-spacing);
5
+ }
6
+
7
+ :host(:not([trailing-icon])) .button {
8
+ flex-direction: row;
9
+ }
10
+
11
+ :host([trailing-icon]) .button {
12
+ flex-direction: row-reverse;
13
+ }
@@ -5,7 +5,7 @@ import IndividualComponent from '@/IndividualComponent.js';
5
5
  import styles from './button-group.scss';
6
6
  import { Button } from '../button/button.js';
7
7
  import { IconButton } from '../icon-button/icon-button.js';
8
- import { BaseButton } from '../BaseButton.js';
8
+ import type { GroupButtonInterface } from '@/button/GroupButtonInterface.js';
9
9
 
10
10
  /**
11
11
  * @label Button Group
@@ -25,7 +25,7 @@ import { BaseButton } from '../BaseButton.js';
25
25
  * @tags controls
26
26
  */
27
27
  @IndividualComponent
28
- export class ButtonGroup extends LitElement {
28
+ class ButtonGroup extends LitElement {
29
29
  // Lit prefers CSS-in-JS for better performance and scoping.
30
30
  // If you prefer keeping the SCSS file, you'll need a build tool (like Vite or Webpack)
31
31
  // that can import .scss files as lit-css.
@@ -57,19 +57,29 @@ export class ButtonGroup extends LitElement {
57
57
  * `"vertical"` stacks buttons in a column.
58
58
  * Defaults to `"horizontal"`.
59
59
  */
60
- @property({ reflect: true }) orientation: 'horizontal' | 'vertical' = 'horizontal';
60
+ @property({ reflect: true }) orientation: 'horizontal' | 'vertical' =
61
+ 'horizontal';
61
62
 
62
63
  /**
63
64
  * Color applied to all buttons in the group.
64
65
  * Possible values are `"primary"`, `"success"`, `"danger"`, `"warning"`, `"surface"`, `"on-surface"`.
65
66
  */
66
- @property({ reflect: true }) color?: 'primary' | 'success' | 'danger' | 'warning' | 'surface' | 'on-surface';
67
+ @property({ reflect: true }) color?:
68
+ | 'primary'
69
+ | 'success'
70
+ | 'danger'
71
+ | 'warning'
72
+ | 'surface'
73
+ | 'on-surface';
67
74
 
68
75
  /**
69
76
  * Visual style applied to all buttons in the group.
70
77
  * Possible values are `"filled"`, `"tonal"`, `"outlined"`.
71
78
  */
72
- @property({ attribute: 'button-variant', reflect: true }) buttonVariant?: 'filled' | 'tonal' | 'outlined';
79
+ @property({ attribute: 'button-variant', reflect: true }) buttonVariant?:
80
+ | 'filled'
81
+ | 'tonal'
82
+ | 'outlined';
73
83
 
74
84
  override updated() {
75
85
  this._syncChildren();
@@ -90,18 +100,21 @@ export class ButtonGroup extends LitElement {
90
100
  const isOnly = children.length === 1;
91
101
 
92
102
  if (this.color && 'color' in child) {
93
- (child as BaseButton).color = this.color;
103
+ (child as GroupButtonInterface).color = this.color;
94
104
  }
95
105
 
96
106
  if (this.buttonVariant && 'variant' in child) {
97
- (child as BaseButton).variant = this.buttonVariant;
107
+ (child as GroupButtonInterface).variant = this.buttonVariant;
98
108
  }
99
109
 
100
110
  if (this.variant === 'connected') {
101
111
  child.style.setProperty('--button-container-shape-variant', 'round');
102
112
 
103
113
  if (isOnly) {
104
- child.style.setProperty('--button-container-shape', 'var(--shape-corner-full)');
114
+ child.style.setProperty(
115
+ '--button-container-shape',
116
+ 'var(--shape-corner-full)',
117
+ );
105
118
  child.style.removeProperty('--button-container-shape-start-start');
106
119
  child.style.removeProperty('--button-container-shape-end-start');
107
120
  child.style.removeProperty('--button-container-shape-start-end');
@@ -116,10 +129,22 @@ export class ButtonGroup extends LitElement {
116
129
  child.style.removeProperty('--button-container-shape-end-end');
117
130
  } else {
118
131
  // Left button in horizontal group: round left corners, standard right corners
119
- child.style.setProperty('--button-container-shape-start-start', 'calc(var(--button-height) / 2)');
120
- child.style.setProperty('--button-container-shape-end-start', 'calc(var(--button-height) / 2)');
121
- child.style.setProperty('--button-container-shape-start-end', 'var(--shape-corner-medium)');
122
- child.style.setProperty('--button-container-shape-end-end', 'var(--shape-corner-medium)');
132
+ child.style.setProperty(
133
+ '--button-container-shape-start-start',
134
+ 'calc(var(--button-height) / 2)',
135
+ );
136
+ child.style.setProperty(
137
+ '--button-container-shape-end-start',
138
+ 'calc(var(--button-height) / 2)',
139
+ );
140
+ child.style.setProperty(
141
+ '--button-container-shape-start-end',
142
+ 'var(--shape-corner-medium)',
143
+ );
144
+ child.style.setProperty(
145
+ '--button-container-shape-end-end',
146
+ 'var(--shape-corner-medium)',
147
+ );
123
148
  }
124
149
  } else if (isLast) {
125
150
  child.style.removeProperty('--button-container-shape');
@@ -131,14 +156,29 @@ export class ButtonGroup extends LitElement {
131
156
  child.style.removeProperty('--button-container-shape-end-end');
132
157
  } else {
133
158
  // Right button in horizontal group: standard left corners, round right corners
134
- child.style.setProperty('--button-container-shape-start-start', 'var(--shape-corner-medium)');
135
- child.style.setProperty('--button-container-shape-end-start', 'var(--shape-corner-medium)');
136
- child.style.setProperty('--button-container-shape-start-end', 'calc(var(--button-height) / 2)');
137
- child.style.setProperty('--button-container-shape-end-end', 'calc(var(--button-height) / 2)');
159
+ child.style.setProperty(
160
+ '--button-container-shape-start-start',
161
+ 'var(--shape-corner-medium)',
162
+ );
163
+ child.style.setProperty(
164
+ '--button-container-shape-end-start',
165
+ 'var(--shape-corner-medium)',
166
+ );
167
+ child.style.setProperty(
168
+ '--button-container-shape-start-end',
169
+ 'calc(var(--button-height) / 2)',
170
+ );
171
+ child.style.setProperty(
172
+ '--button-container-shape-end-end',
173
+ 'calc(var(--button-height) / 2)',
174
+ );
138
175
  }
139
176
  } else {
140
177
  // Middle buttons: standard rounded corners on all sides
141
- child.style.setProperty('--button-container-shape', 'var(--shape-corner-medium)');
178
+ child.style.setProperty(
179
+ '--button-container-shape',
180
+ 'var(--shape-corner-medium)',
181
+ );
142
182
  child.style.removeProperty('--button-container-shape-start-start');
143
183
  child.style.removeProperty('--button-container-shape-end-start');
144
184
  child.style.removeProperty('--button-container-shape-start-end');
@@ -169,3 +209,5 @@ export class ButtonGroup extends LitElement {
169
209
  `;
170
210
  }
171
211
  }
212
+
213
+ export default ButtonGroup;
@@ -1,18 +1,19 @@
1
1
  @use '../../../scss/mixin';
2
2
 
3
+ .button .icon-slot {
4
+ overflow: initial;
5
+ }
6
+
3
7
  .button {
4
- --private-button-container-padding: 0.75rem;
5
8
  width: var(--button-height);
9
+
10
+ --private-button-container-padding: 0.75rem;
6
11
  --private-button-container-padding: 0;
7
12
  }
8
13
 
9
14
  :host([size='xs']),
10
15
  :host([size='extra-small']) {
11
16
  --button-height: 2rem;
12
- }
13
-
14
- :host([size='xs']) .button,
15
- :host([size='extra-small']) .button {
16
17
  --private-button-icon-size: 1rem;
17
18
  }
18
19
 
@@ -20,38 +21,22 @@
20
21
  :host([size='sm']),
21
22
  :host([size='small']) {
22
23
  --button-height: 2.5rem;
23
- }
24
-
25
- :host([size='sm']) .button,
26
- :host([size='small']) .button {
27
24
  --private-button-icon-size: 1.25rem;
28
- --private-button-icon-label-spacing: 0.5rem;
29
25
  }
30
26
 
31
27
  :host([size='md']),
32
28
  :host([size='medium']) {
33
29
  --button-height: 3.5rem;
34
- }
35
-
36
- :host([size='md']) .button,
37
- :host([size='medium']) .button {
38
30
  --private-button-icon-size: 1.5rem;
39
31
  }
40
32
 
41
33
  :host([size='lg']),
42
34
  :host([size='large']) {
43
35
  --button-height: 6rem;
44
- }
45
-
46
- :host([size='lg']) .button,
47
- :host([size='large']) .button {
48
36
  --private-button-icon-size: 2rem;
49
37
  }
50
38
 
51
39
  :host([size='xl']) {
52
40
  --button-height: 8.5rem;
53
- }
54
-
55
- :host([size='xl']) .button {
56
41
  --private-button-icon-size: 2.5rem;
57
42
  }