@ds-mo/ui 2.15.0 → 3.0.1

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 (157) hide show
  1. package/dist/.build-stamp +1 -1
  2. package/dist/components/ds-app-shell.js +1 -1
  3. package/dist/components/ds-badge.js +1 -1
  4. package/dist/components/ds-banner.js +1 -1
  5. package/dist/components/ds-banner.js.map +1 -1
  6. package/dist/components/ds-bar-nav.js +1 -1
  7. package/dist/components/ds-bar-nav.js.map +1 -1
  8. package/dist/components/ds-button-filled.js +1 -1
  9. package/dist/components/ds-button-unfilled.js +1 -1
  10. package/dist/components/ds-card-data-viz-donut.js +1 -1
  11. package/dist/components/ds-card-data-viz-donut.js.map +1 -1
  12. package/dist/components/ds-card-setting.js +1 -1
  13. package/dist/components/ds-card.js +1 -1
  14. package/dist/components/ds-chart-bar.js +1 -1
  15. package/dist/components/ds-chart-donut.js +1 -1
  16. package/dist/components/ds-chart-donut.js.map +1 -1
  17. package/dist/components/ds-chart-legend.js +1 -1
  18. package/dist/components/ds-chart-legend.js.map +1 -1
  19. package/dist/components/ds-chart-line.js +1 -1
  20. package/dist/components/ds-checkbox.js +1 -1
  21. package/dist/components/ds-checkbox.js.map +1 -1
  22. package/dist/components/ds-chip.js +1 -1
  23. package/dist/components/ds-chip.js.map +1 -1
  24. package/dist/components/ds-divider.js +1 -1
  25. package/dist/components/ds-empty-state.js +1 -1
  26. package/dist/components/ds-empty-state.js.map +1 -1
  27. package/dist/components/ds-field.js +1 -1
  28. package/dist/components/ds-icon.js +1 -1
  29. package/dist/components/ds-input.js +1 -1
  30. package/dist/components/ds-input.js.map +1 -1
  31. package/dist/components/ds-loader.js +1 -1
  32. package/dist/components/ds-loader.js.map +1 -1
  33. package/dist/components/ds-menu.js +1 -1
  34. package/dist/components/ds-modal.js +1 -1
  35. package/dist/components/ds-modal.js.map +1 -1
  36. package/dist/components/ds-pagination.js +1 -1
  37. package/dist/components/ds-pagination.js.map +1 -1
  38. package/dist/components/ds-panel-nav.js +1 -1
  39. package/dist/components/ds-panel-nav.js.map +1 -1
  40. package/dist/components/ds-panel-tools.js +1 -1
  41. package/dist/components/ds-panel-tools.js.map +1 -1
  42. package/dist/components/ds-radio-group.js +1 -1
  43. package/dist/components/ds-radio-group.js.map +1 -1
  44. package/dist/components/ds-select.js +1 -1
  45. package/dist/components/ds-select.js.map +1 -1
  46. package/dist/components/ds-shell-gradient-picker.js +1 -1
  47. package/dist/components/ds-shell-gradient-swatch.js +1 -1
  48. package/dist/components/ds-slider.js +1 -1
  49. package/dist/components/ds-tab-group-nav.js +1 -1
  50. package/dist/components/ds-tab-group.js +1 -1
  51. package/dist/components/ds-tab-group.js.map +1 -1
  52. package/dist/components/ds-table.js +1 -1
  53. package/dist/components/ds-table.js.map +1 -1
  54. package/dist/components/ds-tag.js +1 -1
  55. package/dist/components/ds-tag.js.map +1 -1
  56. package/dist/components/ds-text.js +1 -1
  57. package/dist/components/ds-toggle.js +1 -1
  58. package/dist/components/ds-tooltip-data-viz.js +1 -1
  59. package/dist/components/ds-tooltip-data-viz.js.map +1 -1
  60. package/dist/components/ds-tooltip.js +1 -1
  61. package/dist/components/p-8WTsyLQ9.js +2 -0
  62. package/dist/components/p-8WTsyLQ9.js.map +1 -0
  63. package/dist/components/{p-CyFVn2Sc.js → p-9Qu1ls2y.js} +2 -2
  64. package/dist/components/p-BOQRM49Q.js +2 -0
  65. package/dist/components/p-BOQRM49Q.js.map +1 -0
  66. package/dist/components/p-BSNlp8Di.js +2 -0
  67. package/dist/components/p-BSNlp8Di.js.map +1 -0
  68. package/dist/components/p-Co2kLhWu.js +2 -0
  69. package/dist/components/p-Co2kLhWu.js.map +1 -0
  70. package/dist/components/p-CsaW5gDM.js +2 -0
  71. package/dist/components/{p-C3ORQUOp.js.map → p-CsaW5gDM.js.map} +1 -1
  72. package/dist/components/{p-BvF44IQK.js → p-Cx-ywr1e.js} +1 -1
  73. package/dist/components/p-Cx-ywr1e.js.map +1 -0
  74. package/dist/components/p-D0gBLLJx.js +2 -0
  75. package/dist/components/p-D0gBLLJx.js.map +1 -0
  76. package/dist/components/p-DEgY_Lnb.js +2 -0
  77. package/dist/components/p-DEgY_Lnb.js.map +1 -0
  78. package/dist/components/p-DI8rHm9u.js +2 -0
  79. package/dist/components/p-DI8rHm9u.js.map +1 -0
  80. package/dist/components/p-DMD-RO1W.js +2 -0
  81. package/dist/components/p-DMD-RO1W.js.map +1 -0
  82. package/dist/components/p-boPMASaQ.js +2 -0
  83. package/dist/components/p-boPMASaQ.js.map +1 -0
  84. package/dist/components/p-vlwhuqVn.js +2 -0
  85. package/dist/components/p-vlwhuqVn.js.map +1 -0
  86. package/dist/lib/utils/control-text.d.ts +4 -4
  87. package/dist/lib/utils/index.d.ts +1 -1
  88. package/dist/lib/utils/index.js.map +2 -2
  89. package/dist/types/components/ChartDonut/ChartDonut.d.ts +2 -7
  90. package/dist/types/components/Loader/Loader.d.ts +7 -3
  91. package/dist/types/components/Loader/index.d.ts +1 -1
  92. package/dist/types/components/Text/Text.d.ts +2 -1
  93. package/dist/types/components/Text/text-utils.d.ts +3 -1
  94. package/dist/types/components/Tooltip/Tooltip.d.ts +6 -0
  95. package/dist/types/components/TooltipDataViz/TooltipDataViz.d.ts +3 -2
  96. package/dist/types/components.d.ts +34 -19
  97. package/dist/types/utils/control-text.d.ts +4 -4
  98. package/dist/types/utils/index.d.ts +1 -1
  99. package/package.json +7 -7
  100. package/src/angular/proxies.ts +2 -2
  101. package/src/wc/components/Banner/Banner.tsx +3 -5
  102. package/src/wc/components/BarNav/BarNav.tsx +14 -6
  103. package/src/wc/components/ButtonFilled/ButtonFilled.tsx +9 -5
  104. package/src/wc/components/ButtonUnfilled/ButtonUnfilled.tsx +9 -5
  105. package/src/wc/components/Card/Card.tsx +9 -12
  106. package/src/wc/components/ChartDonut/ChartDonut.tsx +4 -47
  107. package/src/wc/components/ChartLegend/ChartLegend.tsx +23 -15
  108. package/src/wc/components/Checkbox/Checkbox.tsx +3 -5
  109. package/src/wc/components/Chip/Chip.tsx +3 -5
  110. package/src/wc/components/EmptyState/EmptyState.tsx +3 -5
  111. package/src/wc/components/Input/Input.tsx +10 -3
  112. package/src/wc/components/Loader/Loader.tsx +77 -30
  113. package/src/wc/components/Loader/index.ts +1 -1
  114. package/src/wc/components/Menu/Menu.tsx +22 -17
  115. package/src/wc/components/Modal/Modal.tsx +10 -11
  116. package/src/wc/components/Pagination/Pagination.tsx +3 -3
  117. package/src/wc/components/PanelNav/PanelNav.tsx +37 -31
  118. package/src/wc/components/PanelTools/PanelTools.tsx +10 -5
  119. package/src/wc/components/RadioGroup/RadioGroup.tsx +3 -5
  120. package/src/wc/components/Select/Select.tsx +9 -5
  121. package/src/wc/components/Table/Table.tsx +15 -12
  122. package/src/wc/components/Tag/Tag.tsx +3 -5
  123. package/src/wc/components/Text/Text.tsx +6 -4
  124. package/src/wc/components/Text/text-utils.ts +8 -1
  125. package/src/wc/components/Tooltip/Tooltip.tsx +53 -6
  126. package/src/wc/components/TooltipDataViz/TooltipDataViz.tsx +20 -12
  127. package/src/wc/components.d.ts +34 -19
  128. package/src/wc/utils/control-density.css +2 -6
  129. package/src/wc/utils/control-text.ts +4 -4
  130. package/src/wc/utils/index.ts +1 -1
  131. package/src/wc/utils/interaction-fill.css +2 -2
  132. package/src/wc/utils/typography.css +146 -0
  133. package/dist/components/p-061wD4FM.js +0 -2
  134. package/dist/components/p-061wD4FM.js.map +0 -1
  135. package/dist/components/p-AiGt4dQS.js +0 -2
  136. package/dist/components/p-AiGt4dQS.js.map +0 -1
  137. package/dist/components/p-BDQgqw5J.js +0 -2
  138. package/dist/components/p-BDQgqw5J.js.map +0 -1
  139. package/dist/components/p-B_g8X0eh.js +0 -2
  140. package/dist/components/p-B_g8X0eh.js.map +0 -1
  141. package/dist/components/p-BvF44IQK.js.map +0 -1
  142. package/dist/components/p-C3ORQUOp.js +0 -2
  143. package/dist/components/p-DIgHkkPe.js +0 -2
  144. package/dist/components/p-DIgHkkPe.js.map +0 -1
  145. package/dist/components/p-DOqi-Vkb.js +0 -2
  146. package/dist/components/p-DOqi-Vkb.js.map +0 -1
  147. package/dist/components/p-DQ3MyAC7.js +0 -2
  148. package/dist/components/p-DQ3MyAC7.js.map +0 -1
  149. package/dist/components/p-DkcH8mRl.js +0 -2
  150. package/dist/components/p-DkcH8mRl.js.map +0 -1
  151. package/dist/components/p-DrhmNrKD.js +0 -2
  152. package/dist/components/p-DrhmNrKD.js.map +0 -1
  153. package/dist/components/p-DujEDZ7f.js +0 -2
  154. package/dist/components/p-DujEDZ7f.js.map +0 -1
  155. package/dist/components/p-DwQ-zdqa.js +0 -2
  156. package/dist/components/p-DwQ-zdqa.js.map +0 -1
  157. /package/dist/components/{p-CyFVn2Sc.js.map → p-9Qu1ls2y.js.map} +0 -0
@@ -515,24 +515,31 @@ export class PanelNav {
515
515
  onKeyDown={(e: KeyboardEvent) => this.handleRovingKeyDown(e, this.getUserRovingIndex())}
516
516
  onFocus={() => { this.rovingIndex = this.getUserRovingIndex(); }}
517
517
  >
518
- <span class="panel-nav__item-label panel-nav__footer-user-label">
519
- <span class="panel-nav__item-label-text">
520
- <ds-text as="span" variant="text-body-medium" emphasis color="inherit">
521
- {userName}
522
- </ds-text>
523
- </span>
524
- </span>
518
+ <ds-text
519
+ class="panel-nav__item-label panel-nav__footer-user-label panel-nav__item-label-text"
520
+ as="span"
521
+ variant="text-body-medium"
522
+ emphasis
523
+ color="inherit"
524
+ >
525
+ {userName}
526
+ </ds-text>
525
527
  <span class="panel-nav__item-icon panel-nav__footer-user-icon" aria-hidden="true">
526
528
  <span class="panel-nav__footer-icon-expanded">
527
529
  <ds-icon name="ChevronUpDown" size="md" color="inherit" />
528
530
  </span>
529
531
  <span class="panel-nav__footer-icon-collapsed">
530
532
  <ds-icon name="Circle" size="md" color="inherit" />
531
- <span class="panel-nav__user-initial">
532
- <ds-text as="span" variant="text-caption" emphasis color="inherit">
533
- {userInitial}
534
- </ds-text>
535
- </span>
533
+ <ds-text
534
+ class="panel-nav__user-initial"
535
+ as="span"
536
+ variant="text-caption"
537
+ emphasis
538
+ align="center"
539
+ color="inherit"
540
+ >
541
+ {userInitial}
542
+ </ds-text>
536
543
  </span>
537
544
  </span>
538
545
  </button>
@@ -553,18 +560,15 @@ export class PanelNav {
553
560
  <span class="panel-nav__item-icon">
554
561
  <ds-icon name={item.icon} size="md" color="inherit" flag={item.flag} />
555
562
  </span>,
556
- <span class="panel-nav__item-label">
557
- <span class="panel-nav__item-label-text">
558
- <ds-text
559
- as="span"
560
- variant="text-body-medium"
561
- emphasis={isActive}
562
- color="inherit"
563
- >
564
- {item.label}
565
- </ds-text>
566
- </span>
567
- </span>,
563
+ <ds-text
564
+ class="panel-nav__item-label panel-nav__item-label-text"
565
+ as="span"
566
+ variant="text-body-medium"
567
+ emphasis={isActive}
568
+ color="inherit"
569
+ >
570
+ {item.label}
571
+ </ds-text>,
568
572
  item.dot && (
569
573
  <ds-badge
570
574
  class="panel-nav__item-dot"
@@ -667,13 +671,15 @@ export class PanelNav {
667
671
  return this.parsedGroups.map(group => (
668
672
  <div class="panel-nav__group">
669
673
  {group.label && (
670
- <span class="panel-nav__group-label">
671
- <span class="panel-nav__item-label-text">
672
- <ds-text as="span" variant="text-caption" emphasis color="inherit">
673
- {group.label}
674
- </ds-text>
675
- </span>
676
- </span>
674
+ <ds-text
675
+ class="panel-nav__group-label"
676
+ as="span"
677
+ variant="text-caption"
678
+ emphasis
679
+ color="inherit"
680
+ >
681
+ {group.label}
682
+ </ds-text>
677
683
  )}
678
684
  {group.items.map(item => this.renderNavItem(item, flatIdx++, collapsed))}
679
685
  </div>
@@ -290,11 +290,16 @@ export class PanelTools {
290
290
  >
291
291
  <div class="panel-tools__drawer-surface">
292
292
  <header class="panel-tools__header">
293
- <span class="panel-tools__title">
294
- <ds-text as="span" variant="text-body-medium" emphasis color="inherit" wrap="nowrap">
295
- {headerLabel}
296
- </ds-text>
297
- </span>
293
+ <ds-text
294
+ class="panel-tools__title"
295
+ as="span"
296
+ variant="text-body-medium"
297
+ emphasis
298
+ color="primary"
299
+ wrap="nowrap"
300
+ >
301
+ {headerLabel}
302
+ </ds-text>
298
303
  </header>
299
304
  <div class="panel-tools__body">
300
305
  <div
@@ -118,11 +118,9 @@ export class RadioGroup {
118
118
  <span class={{ circle: true, 'circle--checked': isChecked }}>
119
119
  {isChecked && <span class="dot" />}
120
120
  </span>
121
- <span class="radio-label">
122
- <ds-text as="span" variant="text-body-medium">
123
- {opt.label}
124
- </ds-text>
125
- </span>
121
+ <ds-text class="radio-label" as="span" variant="text-body-medium">
122
+ {opt.label}
123
+ </ds-text>
126
124
  </div>
127
125
  );
128
126
  })}
@@ -247,11 +247,15 @@ export class Select {
247
247
  aria-labelledby={this.ariaLabelledby}
248
248
  onClick={() => this.toggle({ focusVisible: false })}
249
249
  >
250
- <span class="trigger__label ds-interaction-fill__content">
251
- <ds-text as="span" variant={textVariant} color="inherit" lineTruncation={1}>
252
- {label}
253
- </ds-text>
254
- </span>
250
+ <ds-text
251
+ class="trigger__label ds-interaction-fill__content"
252
+ as="span"
253
+ variant={textVariant}
254
+ color="inherit"
255
+ lineTruncation={1}
256
+ >
257
+ {label}
258
+ </ds-text>
255
259
  <span class="trigger__chevron ds-interaction-fill__content" aria-hidden="true">
256
260
  <ds-icon name="ChevronDown" size={iconSize} color="inherit" />
257
261
  </span>
@@ -181,11 +181,15 @@ export class Table {
181
181
 
182
182
  {/* Empty state */}
183
183
  {isEmpty && (
184
- <div class="empty-row" style={{ gridColumn: '1 / -1' }}>
185
- <ds-text as="p" variant="text-body-medium" color="secondary">
186
- {this.emptyMessage}
187
- </ds-text>
188
- </div>
184
+ <ds-text
185
+ class="empty-row"
186
+ as="p"
187
+ variant="text-body-medium"
188
+ color="secondary"
189
+ style={{ gridColumn: '1 / -1' }}
190
+ >
191
+ {this.emptyMessage}
192
+ </ds-text>
189
193
  )}
190
194
 
191
195
  {/* Data rows */}
@@ -211,21 +215,20 @@ export class Table {
211
215
  }}
212
216
  >
213
217
  {visibleCols.map(col => (
214
- <div
218
+ <ds-text
215
219
  key={col.id}
216
220
  class={{
217
221
  'cell': true,
218
222
  'align-right': col.align === 'right',
219
223
  'align-center': col.align === 'center',
220
224
  }}
225
+ as="span"
226
+ variant="text-body-medium"
227
+ lineTruncation={1}
221
228
  role="cell"
222
229
  >
223
- <span class="cell-value">
224
- <ds-text as="span" variant="text-body-medium">
225
- {String(getCellValue(col, row) ?? '')}
226
- </ds-text>
227
- </span>
228
- </div>
230
+ {String(getCellValue(col, row) ?? '')}
231
+ </ds-text>
229
232
  ))}
230
233
  </div>
231
234
  );
@@ -54,11 +54,9 @@ export class Tag {
54
54
  <span class="tag__icon-slot" data-icon-size={iconSize}>
55
55
  <slot name="icon" />
56
56
  </span>
57
- <span class="tag__label">
58
- <ds-text as="span" variant={textVariant} color="inherit">
59
- {this.label}
60
- </ds-text>
61
- </span>
57
+ <ds-text class="tag__label" as="span" variant={textVariant} color="inherit">
58
+ {this.label}
59
+ </ds-text>
62
60
  </Host>
63
61
  );
64
62
  }
@@ -1,5 +1,5 @@
1
1
  import { Component, Prop, h, Host } from '@stencil/core';
2
- import { textVariantClass } from './text-utils';
2
+ import { textDisplayClass, textVariantClass } from './text-utils';
3
3
  import type {
4
4
  TextAlign,
5
5
  TextColor,
@@ -20,7 +20,8 @@ export class Text {
20
20
  @Prop() variant: TextVariant = 'text-body-medium';
21
21
  /**
22
22
  * Heavier weight + tighter letter-spacing for the variant.
23
- * `false` (default): regular weight (caption stays medium).
23
+ * `false` (default): one step below emphasis (display semibold, title/body
24
+ * medium, caption medium).
24
25
  * `true`: display bold, title/caption semibold, body medium.
25
26
  */
26
27
  @Prop() emphasis: boolean = false;
@@ -46,6 +47,7 @@ export class Text {
46
47
 
47
48
  const cls: Record<string, boolean> = {
48
49
  'ds-text': true,
50
+ [textDisplayClass(this.as)]: true,
49
51
  [textVariantClass(this.variant)]: true,
50
52
  'ds-text--emphasis': this.emphasis,
51
53
  'ds-text--regular': !this.emphasis,
@@ -87,8 +89,8 @@ export class Text {
87
89
  if (this.textId) extraProps['id'] = this.textId;
88
90
 
89
91
  return (
90
- <Host style={{ display: 'contents' }}>
91
- <Tag class={cls} style={style} {...extraProps}>
92
+ <Host class={cls} style={style}>
93
+ <Tag class="ds-text__element" {...extraProps}>
92
94
  <slot />
93
95
  </Tag>
94
96
  </Host>
@@ -1,6 +1,13 @@
1
- import type { TextVariant } from './text-types';
1
+ import type { TextElement, TextVariant } from './text-types';
2
2
 
3
3
  /** `text-body-medium` → `ds-text--body-medium` */
4
4
  export function textVariantClass(variant: TextVariant): string {
5
5
  return `ds-text--${variant.replace(/^text-/, '')}`;
6
6
  }
7
+
8
+ /** Inline semantics get a measurable inline box; paragraphs/headings get a block box. */
9
+ export function textDisplayClass(element: TextElement): string {
10
+ return element === 'span' || element === 'label'
11
+ ? 'ds-text--inline-box'
12
+ : 'ds-text--block-box';
13
+ }
@@ -30,12 +30,14 @@ type DsTextEl = HTMLElement & {
30
30
  variant: TextVariant;
31
31
  emphasis: boolean;
32
32
  color: string;
33
+ wrap: string;
33
34
  };
34
35
 
35
36
  function createDsText(opts: {
36
37
  variant: TextVariant;
37
38
  emphasis?: boolean;
38
39
  color?: string;
40
+ wrap?: 'wrap' | 'nowrap' | 'balance' | 'pretty';
39
41
  text: string;
40
42
  }): DsTextEl {
41
43
  const el = document.createElement('ds-text') as DsTextEl;
@@ -43,10 +45,24 @@ function createDsText(opts: {
43
45
  el.variant = opts.variant;
44
46
  el.emphasis = opts.emphasis ?? false;
45
47
  el.color = opts.color ?? 'inherit';
48
+ if (opts.wrap) el.wrap = opts.wrap;
46
49
  el.textContent = opts.text;
47
50
  return el;
48
51
  }
49
52
 
53
+ /**
54
+ * Control-density label styles for portaled ds-text.
55
+ * Scoped CSS requires `sc-ds-tooltip` on the host, but Text's `<Host class>`
56
+ * overwrites imperative className — so these must be inline to stick.
57
+ */
58
+ function styleTooltipLabel(el: HTMLElement) {
59
+ el.style.flexShrink = '0';
60
+ el.style.minWidth = 'max-content';
61
+ el.style.maxWidth = 'none';
62
+ el.style.padding = '0 var(--ds-control-label-inset, var(--dimension-space-025))';
63
+ el.style.color = 'var(--color-foreground-primary)';
64
+ }
65
+
50
66
  /**
51
67
  * Imperative body portal for the popup.
52
68
  * Stencil must not own the portaled node — moving a VDOM child to `document.body`
@@ -91,6 +107,7 @@ export class Tooltip {
91
107
  private closeTimer: ReturnType<typeof setTimeout> | null = null;
92
108
  private anchor: HTMLElement | null = null;
93
109
  private popupEl: HTMLElement | null = null;
110
+ private positionObserver: ResizeObserver | null = null;
94
111
  private skipEnterAnimation = false;
95
112
  private isOpen = false;
96
113
  private mouseEnterHandler: () => void = () => this.show();
@@ -129,7 +146,7 @@ export class Tooltip {
129
146
  }
130
147
  if (!this.popupEl || !this.isOpen) return;
131
148
  this.renderPopupContent();
132
- this.calculatePosition();
149
+ this.schedulePosition();
133
150
  }
134
151
 
135
152
  private get viewportPadPx(): number {
@@ -197,11 +214,39 @@ export class Tooltip {
197
214
  }
198
215
 
199
216
  private destroyPopup() {
217
+ this.positionObserver?.disconnect();
218
+ this.positionObserver = null;
200
219
  if (!this.popupEl) return;
201
220
  this.popupEl.remove();
202
221
  this.popupEl = null;
203
222
  }
204
223
 
224
+ /**
225
+ * Position after `ds-text` upgrades and lays out. Measuring synchronously in
226
+ * `mountPopup` reads a collapsed/fallback width and places left/right tips wrong.
227
+ */
228
+ private schedulePosition() {
229
+ if (!this.popupEl) return;
230
+
231
+ const reapplyLabelStyles = () => {
232
+ const label = this.popupEl?.querySelector(':scope > .tooltip-inner > ds-text');
233
+ if (label instanceof HTMLElement) styleTooltipLabel(label);
234
+ };
235
+
236
+ requestAnimationFrame(() => {
237
+ reapplyLabelStyles();
238
+ this.calculatePosition();
239
+ requestAnimationFrame(() => {
240
+ reapplyLabelStyles();
241
+ this.calculatePosition();
242
+ });
243
+ });
244
+
245
+ this.positionObserver?.disconnect();
246
+ this.positionObserver = new ResizeObserver(() => this.calculatePosition());
247
+ this.positionObserver.observe(this.popupEl);
248
+ }
249
+
205
250
  /** Drop the open tip immediately (warm handoff to another tooltip). */
206
251
  private hideInstant() {
207
252
  this.clearTimers();
@@ -222,6 +267,7 @@ export class Tooltip {
222
267
  activeTooltip.hideInstant();
223
268
  instant = true;
224
269
  }
270
+ // eslint-disable-next-line @typescript-eslint/no-this-alias -- module singleton tracks the active instance
225
271
  activeTooltip = this;
226
272
  this.skipEnterAnimation = instant;
227
273
  if (instant) {
@@ -275,7 +321,7 @@ export class Tooltip {
275
321
  this.popupEl.classList.toggle('tooltip-popup--instant', this.skipEnterAnimation);
276
322
  this.popupEl.classList.remove('tooltip-popup--closing');
277
323
  this.renderPopupContent();
278
- this.calculatePosition();
324
+ this.schedulePosition();
279
325
  this.isOpen = true;
280
326
  }
281
327
 
@@ -303,10 +349,11 @@ export class Tooltip {
303
349
 
304
350
  appendShortcut('start');
305
351
 
306
- const labelWrap = document.createElement('span');
307
- labelWrap.className = `tooltip-label ${sc}`;
308
- labelWrap.appendChild(createDsText({ variant: textVariant, text: this.label }));
309
- inner.appendChild(labelWrap);
352
+ // ds-text is the layout box (metric-box + 2px control label-inset).
353
+ // Inline styles required — see styleTooltipLabel.
354
+ const label = createDsText({ variant: textVariant, wrap: 'nowrap', text: this.label });
355
+ styleTooltipLabel(label);
356
+ inner.appendChild(label);
310
357
 
311
358
  appendShortcut('end');
312
359
 
@@ -8,8 +8,9 @@ export type TooltipDataVizSide = 'left' | 'right';
8
8
  export type TooltipDataVizAlign = 'top' | 'bottom';
9
9
 
10
10
  /**
11
- * Positioned value/label callout for chart hover interactions (donut slice, bar,
12
- * line point, ...). Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element
11
+ * Positioned value/label callout for chart hover interactions (bar, line point, …).
12
+ * Donut charts skip this legend sync already surfaces the hovered slice.
13
+ * Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element —
13
14
  * charts hover-highlight data that lives inside an SVG, so the chart itself computes
14
15
  * the anchor point (e.g. the cursor position while hovering) and passes it in as `x`/`y`.
15
16
  *
@@ -120,16 +121,23 @@ export class TooltipDataViz {
120
121
  style={{ left: `${this.x}px`, top: `${this.y}px`, transform: `translate(${translateX}, ${translateY})` }}
121
122
  >
122
123
  <div class="tooltip-data-viz__item ds-control--md">
123
- <span class="tooltip-data-viz__label">
124
- <ds-text as="span" variant="text-body-medium" color="var(--color-foreground-on-translucent-background-secondary)">
125
- {this.label}
126
- </ds-text>
127
- </span>
128
- <span class="tooltip-data-viz__value">
129
- <ds-text as="span" variant="text-body-medium" emphasis color="var(--color-foreground-on-translucent-background-primary)">
130
- {this.value}
131
- </ds-text>
132
- </span>
124
+ <ds-text
125
+ class="tooltip-data-viz__label"
126
+ as="span"
127
+ variant="text-body-medium"
128
+ color="var(--color-foreground-on-translucent-background-secondary)"
129
+ >
130
+ {this.label}
131
+ </ds-text>
132
+ <ds-text
133
+ class="tooltip-data-viz__value"
134
+ as="span"
135
+ variant="text-body-medium"
136
+ emphasis
137
+ color="var(--color-foreground-on-translucent-background-primary)"
138
+ >
139
+ {this.value}
140
+ </ds-text>
133
141
  </div>
134
142
  </Host>
135
143
  );
@@ -22,6 +22,7 @@ import { DividerInset, DividerLength, DividerOrientation, DividerSurface } from
22
22
  import { EmptyStateType } from "./components/EmptyState/EmptyState";
23
23
  import { IconColor, IconSize } from "./components/Icon/Icon";
24
24
  import { InputType } from "./components/Input/Input";
25
+ import { LoaderColor, LoaderSize } from "./components/Loader/Loader";
25
26
  import { MenuItemData, MenuSection } from "./components/Menu/menu-types";
26
27
  import { MenuAlign, MenuSide } from "./components/Menu/menu-position";
27
28
  import { ModalWidth } from "./components/Modal/Modal";
@@ -56,6 +57,7 @@ export { DividerInset, DividerLength, DividerOrientation, DividerSurface } from
56
57
  export { EmptyStateType } from "./components/EmptyState/EmptyState";
57
58
  export { IconColor, IconSize } from "./components/Icon/Icon";
58
59
  export { InputType } from "./components/Input/Input";
60
+ export { LoaderColor, LoaderSize } from "./components/Loader/Loader";
59
61
  export { MenuItemData, MenuSection } from "./components/Menu/menu-types";
60
62
  export { MenuAlign, MenuSide } from "./components/Menu/menu-position";
61
63
  export { ModalWidth } from "./components/Modal/Modal";
@@ -401,7 +403,7 @@ export namespace Components {
401
403
  }
402
404
  interface DsChartDonut {
403
405
  /**
404
- * Externally controlled highlight, matched by `label` — e.g. drive this from a sibling `ds-chart-legend`'s `dsItemHover` event to keep chart and legend hover in sync. Falls back to this component's own pointer/focus hover when unset. External sync dims slices onlythe data-viz tooltip is reserved for this component's own pointer/keyboard interaction.
406
+ * Externally controlled highlight, matched by `label` — e.g. drive this from a sibling `ds-chart-legend`'s `dsItemHover` event to keep chart and legend hover in sync. Falls back to this component's own pointer/focus hover when unset. Slice hover dims peer slices and emits `dsSliceHover` for legend sync no data-viz tooltip (the legend already surfaces label/value).
405
407
  * @default null
406
408
  */
407
409
  "activeLabel": string | null;
@@ -639,15 +641,19 @@ export namespace Components {
639
641
  "value": string;
640
642
  }
641
643
  interface DsLoader {
644
+ /**
645
+ * Semantic foreground color token, or a raw CSS var reference. Same tokens as `ds-icon`.
646
+ */
647
+ "color": LoaderColor | undefined;
642
648
  /**
643
649
  * Accessible label for standalone usage. Wraps the spinner in a live region and renders the label visually-hidden. Omit when the host element already conveys busy state via aria-busy.
644
650
  */
645
651
  "label": string | undefined;
646
652
  /**
647
- * Render size number (px) or TokoMo length (`var(--dimension-iconography-md)`, etc.).
648
- * @default TOKEN_DEFAULTS.iconographyMd
653
+ * Iconography size token. Maps to `--dimension-iconography-{size}`. Default `md` = 20 px.
654
+ * @default 'md'
649
655
  */
650
- "size": number | string;
656
+ "size": LoaderSize;
651
657
  }
652
658
  interface DsMenu {
653
659
  /**
@@ -1070,7 +1076,7 @@ export namespace Components {
1070
1076
  "color": TextColor | undefined;
1071
1077
  "decoration": TextDecoration | undefined;
1072
1078
  /**
1073
- * Heavier weight + tighter letter-spacing for the variant. `false` (default): regular weight (caption stays medium). `true`: display bold, title/caption semibold, body medium.
1079
+ * Heavier weight + tighter letter-spacing for the variant. `false` (default): one step below emphasis (display semibold, title/body medium, caption medium). `true`: display bold, title/caption semibold, body medium.
1074
1080
  * @default false
1075
1081
  */
1076
1082
  "emphasis": boolean;
@@ -1156,8 +1162,9 @@ export namespace Components {
1156
1162
  "size": TooltipSize;
1157
1163
  }
1158
1164
  /**
1159
- * Positioned value/label callout for chart hover interactions (donut slice, bar,
1160
- * line point, ...). Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element
1165
+ * Positioned value/label callout for chart hover interactions (bar, line point, …).
1166
+ * Donut charts skip this legend sync already surfaces the hovered slice.
1167
+ * Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element —
1161
1168
  * charts hover-highlight data that lives inside an SVG, so the chart itself computes
1162
1169
  * the anchor point (e.g. the cursor position while hovering) and passes it in as `x`/`y`.
1163
1170
  * Renders `position: absolute` — place inside a `position: relative` chart wrapper,
@@ -1851,8 +1858,9 @@ declare global {
1851
1858
  new (): HTMLDsTooltipElement;
1852
1859
  };
1853
1860
  /**
1854
- * Positioned value/label callout for chart hover interactions (donut slice, bar,
1855
- * line point, ...). Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element
1861
+ * Positioned value/label callout for chart hover interactions (bar, line point, …).
1862
+ * Donut charts skip this legend sync already surfaces the hovered slice.
1863
+ * Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element —
1856
1864
  * charts hover-highlight data that lives inside an SVG, so the chart itself computes
1857
1865
  * the anchor point (e.g. the cursor position while hovering) and passes it in as `x`/`y`.
1858
1866
  * Renders `position: absolute` — place inside a `position: relative` chart wrapper,
@@ -2255,7 +2263,7 @@ declare namespace LocalJSX {
2255
2263
  }
2256
2264
  interface DsChartDonut {
2257
2265
  /**
2258
- * Externally controlled highlight, matched by `label` — e.g. drive this from a sibling `ds-chart-legend`'s `dsItemHover` event to keep chart and legend hover in sync. Falls back to this component's own pointer/focus hover when unset. External sync dims slices onlythe data-viz tooltip is reserved for this component's own pointer/keyboard interaction.
2266
+ * Externally controlled highlight, matched by `label` — e.g. drive this from a sibling `ds-chart-legend`'s `dsItemHover` event to keep chart and legend hover in sync. Falls back to this component's own pointer/focus hover when unset. Slice hover dims peer slices and emits `dsSliceHover` for legend sync no data-viz tooltip (the legend already surfaces label/value).
2259
2267
  * @default null
2260
2268
  */
2261
2269
  "activeLabel"?: string | null;
@@ -2511,15 +2519,19 @@ declare namespace LocalJSX {
2511
2519
  "value"?: string;
2512
2520
  }
2513
2521
  interface DsLoader {
2522
+ /**
2523
+ * Semantic foreground color token, or a raw CSS var reference. Same tokens as `ds-icon`.
2524
+ */
2525
+ "color"?: LoaderColor | undefined;
2514
2526
  /**
2515
2527
  * Accessible label for standalone usage. Wraps the spinner in a live region and renders the label visually-hidden. Omit when the host element already conveys busy state via aria-busy.
2516
2528
  */
2517
2529
  "label"?: string | undefined;
2518
2530
  /**
2519
- * Render size number (px) or TokoMo length (`var(--dimension-iconography-md)`, etc.).
2520
- * @default TOKEN_DEFAULTS.iconographyMd
2531
+ * Iconography size token. Maps to `--dimension-iconography-{size}`. Default `md` = 20 px.
2532
+ * @default 'md'
2521
2533
  */
2522
- "size"?: number | string;
2534
+ "size"?: LoaderSize;
2523
2535
  }
2524
2536
  interface DsMenu {
2525
2537
  /**
@@ -2985,7 +2997,7 @@ declare namespace LocalJSX {
2985
2997
  "color"?: TextColor | undefined;
2986
2998
  "decoration"?: TextDecoration | undefined;
2987
2999
  /**
2988
- * Heavier weight + tighter letter-spacing for the variant. `false` (default): regular weight (caption stays medium). `true`: display bold, title/caption semibold, body medium.
3000
+ * Heavier weight + tighter letter-spacing for the variant. `false` (default): one step below emphasis (display semibold, title/body medium, caption medium). `true`: display bold, title/caption semibold, body medium.
2989
3001
  * @default false
2990
3002
  */
2991
3003
  "emphasis"?: boolean;
@@ -3072,8 +3084,9 @@ declare namespace LocalJSX {
3072
3084
  "size"?: TooltipSize;
3073
3085
  }
3074
3086
  /**
3075
- * Positioned value/label callout for chart hover interactions (donut slice, bar,
3076
- * line point, ...). Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element
3087
+ * Positioned value/label callout for chart hover interactions (bar, line point, …).
3088
+ * Donut charts skip this legend sync already surfaces the hovered slice.
3089
+ * Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element —
3077
3090
  * charts hover-highlight data that lives inside an SVG, so the chart itself computes
3078
3091
  * the anchor point (e.g. the cursor position while hovering) and passes it in as `x`/`y`.
3079
3092
  * Renders `position: absolute` — place inside a `position: relative` chart wrapper,
@@ -3264,7 +3277,8 @@ declare namespace LocalJSX {
3264
3277
  "ariaDescribedby": string | undefined;
3265
3278
  }
3266
3279
  interface DsLoaderAttributes {
3267
- "size": string;
3280
+ "size": LoaderSize;
3281
+ "color": LoaderColor | undefined;
3268
3282
  "label": string | undefined;
3269
3283
  }
3270
3284
  interface DsMenuAttributes {
@@ -3537,8 +3551,9 @@ declare module "@stencil/core" {
3537
3551
  */
3538
3552
  "ds-tooltip": LocalJSX.IntrinsicElements["ds-tooltip"] & JSXBase.HTMLAttributes<HTMLDsTooltipElement>;
3539
3553
  /**
3540
- * Positioned value/label callout for chart hover interactions (donut slice, bar,
3541
- * line point, ...). Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element
3554
+ * Positioned value/label callout for chart hover interactions (bar, line point, …).
3555
+ * Donut charts skip this legend sync already surfaces the hovered slice.
3556
+ * Unlike `ds-tooltip`, this doesn't bind to a slotted anchor element —
3542
3557
  * charts hover-highlight data that lives inside an SVG, so the chart itself computes
3543
3558
  * the anchor point (e.g. the cursor position while hovering) and passes it in as `x`/`y`.
3544
3559
  * Renders `position: absolute` — place inside a `position: relative` chart wrapper,
@@ -3,8 +3,8 @@
3
3
  * (Tag, PanelNav items, BarNav tabs, Menu items, Chip, etc.).
4
4
  *
5
5
  * Apply `.ds-control--md|sm|xs` on the control (host or inner row). Then use the
6
- * `--ds-control-*` vars for height, padding, icon box, label inset, gap, radius,
7
- * and line-height (for wrappers around `ds-text`).
6
+ * `--ds-control-*` vars for height, padding, icon box, label inset, gap, and radius.
7
+ * Text line-height belongs exclusively to the selected `ds-text` variant.
8
8
  *
9
9
  * Both `:host(.ds-control--*)` and `.ds-control--*` are listed so Stencil scoped
10
10
  * components work whether the class is on the host (Tag) or an inner item (PanelNav).
@@ -20,8 +20,6 @@
20
20
  --ds-control-label-inset: var(--dimension-space-025);
21
21
  --ds-control-gap: var(--dimension-space-050);
22
22
  --ds-control-radius: var(--dimension-radius-025);
23
- /* Matches text-body-medium line-height — wrappers around ds-text need this. */
24
- --ds-control-line-height: var(--typography-lineheight-md);
25
23
  }
26
24
 
27
25
  :host(.ds-control--sm),
@@ -32,7 +30,6 @@
32
30
  --ds-control-label-inset: var(--dimension-space-025);
33
31
  --ds-control-gap: var(--dimension-space-025);
34
32
  --ds-control-radius: var(--dimension-radius-025);
35
- --ds-control-line-height: var(--typography-lineheight-sm);
36
33
  }
37
34
 
38
35
  :host(.ds-control--xs),
@@ -43,5 +40,4 @@
43
40
  --ds-control-label-inset: var(--dimension-space-025);
44
41
  --ds-control-gap: var(--dimension-space-025);
45
42
  --ds-control-radius: var(--dimension-radius-025);
46
- --ds-control-line-height: var(--typography-lineheight-xs);
47
43
  }