@ds-mo/ui 2.14.0 → 3.0.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 (175) 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-setting.js.map +1 -1
  14. package/dist/components/ds-card.js +1 -1
  15. package/dist/components/ds-chart-bar.js +1 -1
  16. package/dist/components/ds-chart-bar.js.map +1 -1
  17. package/dist/components/ds-chart-donut.js +1 -1
  18. package/dist/components/ds-chart-donut.js.map +1 -1
  19. package/dist/components/ds-chart-legend.js +1 -1
  20. package/dist/components/ds-chart-legend.js.map +1 -1
  21. package/dist/components/ds-chart-line.js +1 -1
  22. package/dist/components/ds-chart-line.js.map +1 -1
  23. package/dist/components/ds-checkbox.js +1 -1
  24. package/dist/components/ds-checkbox.js.map +1 -1
  25. package/dist/components/ds-chip.js +1 -1
  26. package/dist/components/ds-chip.js.map +1 -1
  27. package/dist/components/ds-divider.js +1 -1
  28. package/dist/components/ds-empty-state.js +1 -1
  29. package/dist/components/ds-empty-state.js.map +1 -1
  30. package/dist/components/ds-field.js +1 -1
  31. package/dist/components/ds-field.js.map +1 -1
  32. package/dist/components/ds-icon.js +1 -1
  33. package/dist/components/ds-input.js +1 -1
  34. package/dist/components/ds-input.js.map +1 -1
  35. package/dist/components/ds-loader.js +1 -1
  36. package/dist/components/ds-loader.js.map +1 -1
  37. package/dist/components/ds-menu.js +1 -1
  38. package/dist/components/ds-modal.js +1 -1
  39. package/dist/components/ds-modal.js.map +1 -1
  40. package/dist/components/ds-pagination.js +1 -1
  41. package/dist/components/ds-pagination.js.map +1 -1
  42. package/dist/components/ds-panel-nav.js +1 -1
  43. package/dist/components/ds-panel-nav.js.map +1 -1
  44. package/dist/components/ds-panel-tools.js +1 -1
  45. package/dist/components/ds-panel-tools.js.map +1 -1
  46. package/dist/components/ds-radio-group.js +1 -1
  47. package/dist/components/ds-radio-group.js.map +1 -1
  48. package/dist/components/ds-select.js +1 -1
  49. package/dist/components/ds-select.js.map +1 -1
  50. package/dist/components/ds-shell-gradient-picker.js +1 -1
  51. package/dist/components/ds-shell-gradient-swatch.js +1 -1
  52. package/dist/components/ds-slider.js +1 -1
  53. package/dist/components/ds-slider.js.map +1 -1
  54. package/dist/components/ds-tab-group-nav.js +1 -1
  55. package/dist/components/ds-tab-group.js +1 -1
  56. package/dist/components/ds-tab-group.js.map +1 -1
  57. package/dist/components/ds-table.js +1 -1
  58. package/dist/components/ds-table.js.map +1 -1
  59. package/dist/components/ds-tag.js +1 -1
  60. package/dist/components/ds-tag.js.map +1 -1
  61. package/dist/components/ds-text.js +1 -1
  62. package/dist/components/ds-toggle.js +1 -1
  63. package/dist/components/ds-tooltip-data-viz.js +1 -1
  64. package/dist/components/ds-tooltip-data-viz.js.map +1 -1
  65. package/dist/components/ds-tooltip.js +1 -1
  66. package/dist/components/p-8WTsyLQ9.js +2 -0
  67. package/dist/components/p-8WTsyLQ9.js.map +1 -0
  68. package/dist/components/{p-B82KZX9D.js → p-9Qu1ls2y.js} +2 -2
  69. package/dist/components/p-BSNlp8Di.js +2 -0
  70. package/dist/components/p-BSNlp8Di.js.map +1 -0
  71. package/dist/components/p-BVNJnFI9.js +2 -0
  72. package/dist/components/p-BVNJnFI9.js.map +1 -0
  73. package/dist/components/p-B_ENgncs.js +2 -0
  74. package/dist/components/p-B_ENgncs.js.map +1 -0
  75. package/dist/components/p-CNgNgezy.js +2 -0
  76. package/dist/components/p-CNgNgezy.js.map +1 -0
  77. package/dist/components/p-CQmul5NK.js +2 -0
  78. package/dist/components/p-CQmul5NK.js.map +1 -0
  79. package/dist/components/p-CsaW5gDM.js +2 -0
  80. package/dist/components/{p-CYmVDfd_.js.map → p-CsaW5gDM.js.map} +1 -1
  81. package/dist/components/p-Cx-ywr1e.js +2 -0
  82. package/dist/components/p-Cx-ywr1e.js.map +1 -0
  83. package/dist/components/p-DQ3l2TXw.js +2 -0
  84. package/dist/components/p-DQ3l2TXw.js.map +1 -0
  85. package/dist/components/p-DRqJ3RUb.js +2 -0
  86. package/dist/components/p-DRqJ3RUb.js.map +1 -0
  87. package/dist/components/p-V2qW8NL0.js +2 -0
  88. package/dist/components/p-V2qW8NL0.js.map +1 -0
  89. package/dist/components/p-sBx2MuF2.js +2 -0
  90. package/dist/components/p-sBx2MuF2.js.map +1 -0
  91. package/dist/lib/components/Text/text-types.d.ts +9 -0
  92. package/dist/lib/utils/control-text.d.ts +5 -0
  93. package/dist/lib/utils/index.d.ts +2 -0
  94. package/dist/lib/utils/index.js +8 -0
  95. package/dist/lib/utils/index.js.map +3 -3
  96. package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +1 -1
  97. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +1 -1
  98. package/dist/types/components/ChartDonut/ChartDonut.d.ts +2 -7
  99. package/dist/types/components/Loader/Loader.d.ts +7 -3
  100. package/dist/types/components/Loader/index.d.ts +1 -1
  101. package/dist/types/components/Select/Select.d.ts +1 -1
  102. package/dist/types/components/Text/Text.d.ts +9 -9
  103. package/dist/types/components/Text/index.d.ts +2 -1
  104. package/dist/types/components/Text/text-types.d.ts +10 -0
  105. package/dist/types/components/Text/text-utils.d.ts +6 -0
  106. package/dist/types/components/Tooltip/Tooltip.d.ts +1 -0
  107. package/dist/types/components/TooltipDataViz/TooltipDataViz.d.ts +3 -2
  108. package/dist/types/components.d.ts +54 -19
  109. package/dist/types/utils/control-text.d.ts +6 -0
  110. package/dist/types/utils/index.d.ts +2 -0
  111. package/package.json +7 -7
  112. package/src/angular/proxies.ts +4 -4
  113. package/src/wc/components/Badge/Badge.tsx +6 -8
  114. package/src/wc/components/Banner/Banner.tsx +3 -1
  115. package/src/wc/components/BarNav/BarNav.tsx +10 -1
  116. package/src/wc/components/ButtonFilled/ButtonFilled.tsx +10 -11
  117. package/src/wc/components/ButtonUnfilled/ButtonUnfilled.tsx +10 -11
  118. package/src/wc/components/Card/Card.tsx +9 -10
  119. package/src/wc/components/ChartDonut/ChartDonut.tsx +4 -47
  120. package/src/wc/components/ChartLegend/ChartLegend.tsx +23 -15
  121. package/src/wc/components/Checkbox/Checkbox.tsx +2 -2
  122. package/src/wc/components/Chip/Chip.tsx +4 -10
  123. package/src/wc/components/EmptyState/EmptyState.tsx +3 -5
  124. package/src/wc/components/Field/Field.tsx +3 -1
  125. package/src/wc/components/Input/Input.tsx +10 -3
  126. package/src/wc/components/Loader/Loader.tsx +77 -30
  127. package/src/wc/components/Loader/index.ts +1 -1
  128. package/src/wc/components/Menu/Menu.tsx +21 -6
  129. package/src/wc/components/Modal/Modal.tsx +16 -3
  130. package/src/wc/components/Pagination/Pagination.tsx +5 -5
  131. package/src/wc/components/PanelNav/PanelNav.tsx +30 -30
  132. package/src/wc/components/PanelTools/PanelTools.tsx +10 -7
  133. package/src/wc/components/RadioGroup/RadioGroup.tsx +3 -1
  134. package/src/wc/components/Select/Select.tsx +15 -17
  135. package/src/wc/components/Slider/Slider.tsx +6 -2
  136. package/src/wc/components/TabGroup/TabGroup.tsx +3 -2
  137. package/src/wc/components/TabGroupNav/TabGroupNav.tsx +3 -2
  138. package/src/wc/components/Table/Table.tsx +21 -16
  139. package/src/wc/components/Tag/Tag.tsx +4 -10
  140. package/src/wc/components/Text/Text.tsx +54 -59
  141. package/src/wc/components/Text/index.ts +12 -1
  142. package/src/wc/components/Text/text-types.ts +23 -0
  143. package/src/wc/components/Text/text-utils.ts +13 -0
  144. package/src/wc/components/Tooltip/Tooltip.tsx +64 -41
  145. package/src/wc/components/TooltipDataViz/TooltipDataViz.tsx +20 -12
  146. package/src/wc/components.d.ts +54 -19
  147. package/src/wc/utils/control-density.css +1 -0
  148. package/src/wc/utils/control-text.ts +11 -0
  149. package/src/wc/utils/index.ts +2 -0
  150. package/src/wc/utils/interaction-fill.css +2 -2
  151. package/src/wc/utils/typography.css +146 -0
  152. package/dist/components/p-1m8r0wFg.js +0 -2
  153. package/dist/components/p-1m8r0wFg.js.map +0 -1
  154. package/dist/components/p-B2_D4IDN.js +0 -2
  155. package/dist/components/p-B2_D4IDN.js.map +0 -1
  156. package/dist/components/p-B5NcWtpp.js +0 -2
  157. package/dist/components/p-B5NcWtpp.js.map +0 -1
  158. package/dist/components/p-BAeKw2pj.js +0 -2
  159. package/dist/components/p-BAeKw2pj.js.map +0 -1
  160. package/dist/components/p-B_g8X0eh.js +0 -2
  161. package/dist/components/p-B_g8X0eh.js.map +0 -1
  162. package/dist/components/p-CDHRJqea.js +0 -2
  163. package/dist/components/p-CDHRJqea.js.map +0 -1
  164. package/dist/components/p-CYmVDfd_.js +0 -2
  165. package/dist/components/p-CtwNUCnp.js +0 -2
  166. package/dist/components/p-CtwNUCnp.js.map +0 -1
  167. package/dist/components/p-CuRjYmBk.js +0 -2
  168. package/dist/components/p-CuRjYmBk.js.map +0 -1
  169. package/dist/components/p-Dlol7hPg.js +0 -2
  170. package/dist/components/p-Dlol7hPg.js.map +0 -1
  171. package/dist/components/p-EK1hOP19.js +0 -2
  172. package/dist/components/p-EK1hOP19.js.map +0 -1
  173. package/dist/components/p-XNHSe8Mg.js +0 -2
  174. package/dist/components/p-XNHSe8Mg.js.map +0 -1
  175. /package/dist/components/{p-B82KZX9D.js.map → p-9Qu1ls2y.js.map} +0 -0
@@ -51,9 +51,9 @@ export class Checkbox {
51
51
  </span>
52
52
  )}
53
53
  </span>
54
- <span id={this.labelId} class="text-body-medium checkbox__label">
54
+ <ds-text class="checkbox__label" as="span" variant="text-body-medium" textId={this.labelId}>
55
55
  {this.label}
56
- </span>
56
+ </ds-text>
57
57
  </Host>
58
58
  );
59
59
  }
@@ -1,4 +1,5 @@
1
1
  import { Component, Prop, Event, EventEmitter, h, Host } from '@stencil/core';
2
+ import { CONTROL_TEXT_VARIANT } from '../../utils';
2
3
 
3
4
  /**
4
5
  * Semantic chip state — replaces Tag’s intent × contrast matrix.
@@ -11,13 +12,6 @@ export type ChipState = 'default' | 'active' | 'error' | 'caution';
11
12
  export type ChipSize = 'md' | 'sm' | 'xs';
12
13
  export type ChipBackground = 'faint' | 'medium' | 'bold' | 'strong' | 'always-dark';
13
14
 
14
- /** Text variant per control-density recipe (md / sm / xs). */
15
- const TEXT_VARIANT: Record<ChipSize, string> = {
16
- md: 'text-body-medium',
17
- sm: 'text-body-small',
18
- xs: 'text-caption',
19
- };
20
-
21
15
  /** Dismiss `ds-icon` size — same iconography metrics as Tag’s leading icon. */
22
16
  const ICON_SIZE: Record<ChipSize, 'md' | 'sm' | 'xs'> = {
23
17
  md: 'md',
@@ -58,7 +52,7 @@ export class Chip {
58
52
  };
59
53
 
60
54
  render() {
61
- const textVariant = TEXT_VARIANT[this.size];
55
+ const textVariant = CONTROL_TEXT_VARIANT[this.size];
62
56
  const iconSize = ICON_SIZE[this.size];
63
57
 
64
58
  const maxWidthStyle = this.maxWidth != null
@@ -88,9 +82,9 @@ export class Chip {
88
82
  style={maxWidthStyle}
89
83
  aria-disabled={this.isInactive || undefined}
90
84
  >
91
- <span class={{ 'tag__label': true, [textVariant]: true }}>
85
+ <ds-text class="tag__label" as="span" variant={textVariant} color="inherit">
92
86
  {this.label}
93
- </span>
87
+ </ds-text>
94
88
  {this.removable && (
95
89
  <button
96
90
  type="button"
@@ -21,11 +21,9 @@ export class EmptyState {
21
21
  render() {
22
22
  return (
23
23
  <Host>
24
- <div class="empty-state">
25
- <p class="text-body-medium" style={{ color: 'var(--color-foreground-secondary)' }}>
26
- {this.message || DEFAULT_MESSAGES[this.type]}
27
- </p>
28
- </div>
24
+ <ds-text class="empty-state" as="p" variant="text-body-medium" color="secondary">
25
+ {this.message || DEFAULT_MESSAGES[this.type]}
26
+ </ds-text>
29
27
  </Host>
30
28
  );
31
29
  }
@@ -19,7 +19,9 @@ export class Field {
19
19
  return (
20
20
  <Host>
21
21
  <div class="field">
22
- <label class="text-body-small-emphasis field__label" htmlFor={id}>{this.label}</label>
22
+ <ds-text as="label" variant="text-body-small" emphasis for={id}>
23
+ {this.label}
24
+ </ds-text>
23
25
  <slot />
24
26
  </div>
25
27
  </Host>
@@ -67,7 +67,7 @@ export class Input {
67
67
  placeholder={this.placeholder}
68
68
  disabled={this.isInactive}
69
69
  autoFocus={this.autoFocus}
70
- class="native-input"
70
+ class="native-input ds-text--body-medium ds-text--regular"
71
71
  aria-label={this.ariaLabel}
72
72
  aria-labelledby={this.ariaLabelledby}
73
73
  aria-describedby={describedBy}
@@ -90,9 +90,16 @@ export class Input {
90
90
  </div>
91
91
  </div>
92
92
  {showError && (
93
- <div id={this.errorId} role="alert" class="error-text">
93
+ <ds-text
94
+ class="error-text"
95
+ as="div"
96
+ variant="text-body-small"
97
+ color="negative"
98
+ textId={this.errorId}
99
+ role="alert"
100
+ >
94
101
  {this.errorMessage}
95
- </div>
102
+ </ds-text>
96
103
  )}
97
104
  </Host>
98
105
  );
@@ -1,5 +1,8 @@
1
- import { Component, Prop, h } from '@stencil/core';
2
- import { resolveCssLengthPx, TOKEN_DEFAULTS } from '../../utils';
1
+ import { Component, Prop, h, Host } from '@stencil/core';
2
+ import type { IconColor, IconSize } from '../Icon/Icon';
3
+
4
+ export type LoaderSize = IconSize;
5
+ export type LoaderColor = IconColor;
3
6
 
4
7
  @Component({
5
8
  tag: 'ds-loader',
@@ -7,8 +10,10 @@ import { resolveCssLengthPx, TOKEN_DEFAULTS } from '../../utils';
7
10
  shadow: true,
8
11
  })
9
12
  export class Loader {
10
- /** Render size number (px) or TokoMo length (`var(--dimension-iconography-md)`, etc.). */
11
- @Prop() size: number | string = TOKEN_DEFAULTS.iconographyMd;
13
+ /** Iconography size token. Maps to `--dimension-iconography-{size}`. Default `md` = 20 px. */
14
+ @Prop() size: LoaderSize = 'md';
15
+ /** Semantic foreground color token, or a raw CSS var reference. Same tokens as `ds-icon`. */
16
+ @Prop() color: LoaderColor | undefined;
12
17
  /**
13
18
  * Accessible label for standalone usage. Wraps the spinner in a live region
14
19
  * and renders the label visually-hidden. Omit when the host element already
@@ -16,37 +21,79 @@ export class Loader {
16
21
  */
17
22
  @Prop() label: string | undefined;
18
23
 
19
- private get sizePx(): number {
20
- return resolveCssLengthPx(this.size, TOKEN_DEFAULTS.iconographyMd);
21
- }
22
-
23
24
  render() {
24
- const px = `${this.sizePx}px`;
25
- const svg = (
26
- <svg
27
- style={{ width: px, height: px }}
28
- viewBox="0 0 16 16"
29
- fill="none"
30
- class="spinner"
31
- aria-hidden="true"
32
- >
33
- <circle
34
- cx="8" cy="8" r="5"
35
- stroke="currentColor"
36
- stroke-width="1"
37
- stroke-linecap="round"
38
- stroke-dasharray="23.6 7.9"
39
- />
40
- </svg>
25
+ const isCustomColor = typeof this.color === 'string' && this.color.startsWith('var(--');
26
+
27
+ const cls: Record<string, boolean> = {
28
+ loader: true,
29
+ [`loader--size-${this.size}`]: true,
30
+ [`loader--color-${this.color}`]: !!this.color && !isCustomColor && this.color !== 'inherit',
31
+ 'loader--color-inherit': this.color === 'inherit',
32
+ };
33
+
34
+ const style = isCustomColor ? { color: this.color as string } : undefined;
35
+
36
+ const spinner = (
37
+ <span class={cls} style={style} aria-hidden="true">
38
+ <svg class="loader__svg" viewBox="0 0 16 16" fill="none" focusable="false">
39
+ <path
40
+ opacity="0.1"
41
+ d="M3 8C3 5.23858 5.23858 3 8 3V2C4.68629 2 2 4.68629 2 8C2 9.99456 2.97323 11.7618 4.47072 12.8528L5.05894 12.044C3.81102 11.1348 3 9.66213 3 8Z"
42
+ fill="currentColor"
43
+ />
44
+ <path
45
+ opacity="0.2"
46
+ fill-rule="evenodd"
47
+ clip-rule="evenodd"
48
+ d="M5.05892 12.0438C5.88425 12.6451 6.90069 12.9998 7.99998 12.9998C9.66211 12.9998 11.1348 12.1888 12.0439 10.9409L12.8527 11.5291C11.7618 13.0266 9.99454 13.9998 7.99998 13.9998C6.68083 13.9998 5.46111 13.5741 4.4707 12.8526L5.05892 12.0438Z"
49
+ fill="currentColor"
50
+ />
51
+ <path
52
+ opacity="0.4"
53
+ fill-rule="evenodd"
54
+ clip-rule="evenodd"
55
+ d="M12.0435 10.9408C12.6447 10.1155 12.9995 9.09906 12.9995 7.99976C12.9995 7.45884 12.9136 6.93798 12.7547 6.45007L13.7057 6.14014C13.8964 6.72562 13.9995 7.35065 13.9995 7.99976C13.9995 9.31891 13.5738 10.5386 12.8523 11.529L12.0435 10.9408Z"
56
+ fill="currentColor"
57
+ />
58
+ <path
59
+ opacity="0.6"
60
+ fill-rule="evenodd"
61
+ clip-rule="evenodd"
62
+ d="M12.7555 6.45152C12.4263 5.43958 11.7831 4.56933 10.9409 3.95577L11.5291 3.14697C12.5398 3.88325 13.3116 4.92755 13.7067 6.14188L12.7555 6.45152Z"
63
+ fill="currentColor"
64
+ />
65
+ <path
66
+ opacity="0.8"
67
+ fill-rule="evenodd"
68
+ clip-rule="evenodd"
69
+ d="M10.941 3.95583C10.5307 3.65688 10.0731 3.41886 9.58154 3.25509L9.89786 2.30615C10.4877 2.50267 11.0368 2.78829 11.5293 3.14704L10.941 3.95583Z"
70
+ fill="currentColor"
71
+ />
72
+ <path
73
+ fill-rule="evenodd"
74
+ clip-rule="evenodd"
75
+ d="M9.89788 2.30636C9.3014 2.10762 8.66327 2 8 2V3C8.55272 3 9.0845 3.08968 9.58157 3.2553L9.89788 2.30636Z"
76
+ fill="currentColor"
77
+ />
78
+ </svg>
79
+ </span>
41
80
  );
42
81
 
43
- if (!this.label) return svg;
82
+ if (!this.label) {
83
+ return (
84
+ <Host style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
85
+ {spinner}
86
+ </Host>
87
+ );
88
+ }
44
89
 
45
90
  return (
46
- <span role="status" aria-live="polite" class="status">
47
- {svg}
48
- <span class="visually-hidden">{this.label}</span>
49
- </span>
91
+ <Host style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}>
92
+ <span role="status" aria-live="polite" class="status">
93
+ {spinner}
94
+ <span class="visually-hidden">{this.label}</span>
95
+ </span>
96
+ </Host>
50
97
  );
51
98
  }
52
99
  }
@@ -1 +1 @@
1
- export type {} from './Loader';
1
+ export type { LoaderSize, LoaderColor } from './Loader';
@@ -357,9 +357,16 @@ export class Menu {
357
357
  aria-label={section.header}
358
358
  >
359
359
  {section.header && (
360
- <div class="section-header ds-control--md" aria-hidden="true">
361
- <span class="text-body-small-emphasis section-label">{section.header}</span>
362
- </div>
360
+ <ds-text
361
+ class="section-header ds-control--md"
362
+ as="span"
363
+ variant="text-body-small"
364
+ emphasis
365
+ color="inherit"
366
+ aria-hidden="true"
367
+ >
368
+ {section.header}
369
+ </ds-text>
363
370
  )}
364
371
  {isMenuGradientPickerSection(section) ? (
365
372
  <ds-shell-gradient-picker
@@ -398,11 +405,19 @@ export class Menu {
398
405
  onFocus={() => { this.focusedIndex = idx; }}
399
406
  >
400
407
  <div class="menu-item__content ds-interaction-fill__content">
401
- <span class={item.isSelected ? 'text-body-medium-emphasis menu-item__label' : 'text-body-medium menu-item__label'}>
408
+ <ds-text
409
+ class="menu-item__label"
410
+ as="span"
411
+ variant="text-body-medium"
412
+ emphasis={!!item.isSelected}
413
+ color="inherit"
414
+ >
402
415
  {item.label}
403
- </span>
416
+ </ds-text>
404
417
  {item.subtext && (
405
- <span class="text-body-small menu-item__subtext">{item.subtext}</span>
418
+ <ds-text class="menu-item__subtext" as="span" variant="text-body-small" color="inherit">
419
+ {item.subtext}
420
+ </ds-text>
406
421
  )}
407
422
  </div>
408
423
  {item.showToggle && (
@@ -179,11 +179,24 @@ export class Modal {
179
179
  style={{ width: `min(${this.resolvedWidth}, calc(100vw - 2 * var(--dimension-space-200)))` }}
180
180
  >
181
181
  <div class="modal-header">
182
- <h2 id={this.titleId} class="text-title-small modal-title">{this.heading}</h2>
182
+ <ds-text
183
+ as="h2"
184
+ variant="text-title-small"
185
+ textId={this.titleId}
186
+ >
187
+ {this.heading}
188
+ </ds-text>
183
189
  {this.subtitle && (
184
- <div id={this.subtitleId} class="modal-subtitle text-body-medium">
190
+ <ds-text
191
+ class="modal-subtitle"
192
+ as="div"
193
+ variant="text-body-medium"
194
+ color="secondary"
195
+ wrap="balance"
196
+ textId={this.subtitleId}
197
+ >
185
198
  {this.subtitle}
186
- </div>
199
+ </ds-text>
187
200
  )}
188
201
  </div>
189
202
  <div class="modal-body">
@@ -62,9 +62,9 @@ export class Pagination {
62
62
 
63
63
  {pages.map((item, i) =>
64
64
  item === 'ellipsis' ? (
65
- <span key={`e${i}`} class="ellipsis">
66
- <span class="text-body-small" style={{ color: 'var(--color-foreground-tertiary)' }}>…</span>
67
- </span>
65
+ <ds-text key={`e${i}`} class="ellipsis" as="span" variant="text-body-small" color="tertiary">
66
+
67
+ </ds-text>
68
68
  ) : (
69
69
  <button
70
70
  key={item}
@@ -74,9 +74,9 @@ export class Pagination {
74
74
  aria-current={item === this.page ? 'page' : undefined}
75
75
  disabled={this.isInactive}
76
76
  >
77
- <span class={item === this.page ? 'text-body-small-emphasis' : 'text-body-small'}>
77
+ <ds-text as="span" variant="text-body-small" emphasis={item === this.page}>
78
78
  {item}
79
- </span>
79
+ </ds-text>
80
80
  </button>
81
81
  )
82
82
  )}
@@ -515,24 +515,24 @@ 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 class="panel-nav__user-initial" as="span" variant="text-caption" emphasis color="inherit">
534
+ {userInitial}
535
+ </ds-text>
536
536
  </span>
537
537
  </span>
538
538
  </button>
@@ -553,17 +553,15 @@ export class PanelNav {
553
553
  <span class="panel-nav__item-icon">
554
554
  <ds-icon name={item.icon} size="md" color="inherit" flag={item.flag} />
555
555
  </span>,
556
- <span class="panel-nav__item-label">
557
- <span class="panel-nav__item-label-text">
558
- <ds-text
559
- as="span"
560
- variant={isActive ? 'text-body-medium-emphasis' : 'text-body-medium'}
561
- color="inherit"
562
- >
563
- {item.label}
564
- </ds-text>
565
- </span>
566
- </span>,
556
+ <ds-text
557
+ class="panel-nav__item-label panel-nav__item-label-text"
558
+ as="span"
559
+ variant="text-body-medium"
560
+ emphasis={isActive}
561
+ color="inherit"
562
+ >
563
+ {item.label}
564
+ </ds-text>,
567
565
  item.dot && (
568
566
  <ds-badge
569
567
  class="panel-nav__item-dot"
@@ -666,13 +664,15 @@ export class PanelNav {
666
664
  return this.parsedGroups.map(group => (
667
665
  <div class="panel-nav__group">
668
666
  {group.label && (
669
- <span class="panel-nav__group-label">
670
- <span class="panel-nav__item-label-text">
671
- <ds-text as="span" variant="text-caption-emphasis" color="inherit">
672
- {group.label}
673
- </ds-text>
674
- </span>
675
- </span>
667
+ <ds-text
668
+ class="panel-nav__group-label panel-nav__item-label-text"
669
+ as="span"
670
+ variant="text-caption"
671
+ emphasis
672
+ color="inherit"
673
+ >
674
+ {group.label}
675
+ </ds-text>
676
676
  )}
677
677
  {group.items.map(item => this.renderNavItem(item, flatIdx++, collapsed))}
678
678
  </div>
@@ -290,14 +290,22 @@ 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 text-body-medium-emphasis">{headerLabel}</span>
293
+ <ds-text
294
+ class="panel-tools__title"
295
+ as="span"
296
+ variant="text-body-medium"
297
+ emphasis
298
+ color="inherit"
299
+ wrap="nowrap"
300
+ >
301
+ {headerLabel}
302
+ </ds-text>
294
303
  </header>
295
304
  <div class="panel-tools__body">
296
305
  <div
297
306
  class={{
298
307
  'panel-tools__view': true,
299
308
  'panel-tools__view--active': this.isViewActive('search'),
300
- 'text-body-medium': true,
301
309
  }}
302
310
  hidden={!this.isViewActive('search')}
303
311
  >
@@ -307,7 +315,6 @@ export class PanelTools {
307
315
  class={{
308
316
  'panel-tools__view': true,
309
317
  'panel-tools__view--active': this.isViewActive('messages'),
310
- 'text-body-medium': true,
311
318
  }}
312
319
  hidden={!this.isViewActive('messages')}
313
320
  >
@@ -317,7 +324,6 @@ export class PanelTools {
317
324
  class={{
318
325
  'panel-tools__view': true,
319
326
  'panel-tools__view--active': this.isViewActive('stacks'),
320
- 'text-body-medium': true,
321
327
  }}
322
328
  hidden={!this.isViewActive('stacks')}
323
329
  >
@@ -327,7 +333,6 @@ export class PanelTools {
327
333
  class={{
328
334
  'panel-tools__view': true,
329
335
  'panel-tools__view--active': this.isViewActive('activity'),
330
- 'text-body-medium': true,
331
336
  }}
332
337
  hidden={!this.isViewActive('activity')}
333
338
  >
@@ -337,7 +342,6 @@ export class PanelTools {
337
342
  class={{
338
343
  'panel-tools__view': true,
339
344
  'panel-tools__view--active': this.isViewActive('agents'),
340
- 'text-body-medium': true,
341
345
  }}
342
346
  hidden={!this.isViewActive('agents')}
343
347
  >
@@ -347,7 +351,6 @@ export class PanelTools {
347
351
  class={{
348
352
  'panel-tools__view': true,
349
353
  'panel-tools__view--active': this.isViewActive('help'),
350
- 'text-body-medium': true,
351
354
  }}
352
355
  hidden={!this.isViewActive('help')}
353
356
  >
@@ -118,7 +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="text-body-medium radio-label">{opt.label}</span>
121
+ <ds-text class="radio-label" as="span" variant="text-body-medium">
122
+ {opt.label}
123
+ </ds-text>
122
124
  </div>
123
125
  );
124
126
  })}
@@ -1,6 +1,11 @@
1
1
  import { Component, Prop, State, Event, EventEmitter, Element, Watch, Listen, h, Host } from '@stencil/core';
2
- import { controlWidthClass, type ControlWidth } from '../../utils/control-width';
3
- import { resolveCssLengthPx, TOKEN_DEFAULTS } from '../../utils';
2
+ import {
3
+ controlWidthClass,
4
+ CONTROL_TEXT_VARIANT,
5
+ resolveCssLengthPx,
6
+ TOKEN_DEFAULTS,
7
+ type ControlWidth,
8
+ } from '../../utils';
4
9
  import type { MenuItemData } from '../Menu/menu-types';
5
10
 
6
11
  export interface SelectOption {
@@ -12,13 +17,6 @@ export type SelectSize = 'md' | 'sm' | 'xs';
12
17
 
13
18
  export type SelectWidth = ControlWidth;
14
19
 
15
- /** Regular (non-emphasis) type per density — selects stay visually lighter than buttons. */
16
- const TEXT_VARIANT: Record<SelectSize, string> = {
17
- md: 'text-body-medium',
18
- sm: 'text-body-small',
19
- xs: 'text-caption',
20
- };
21
-
22
20
  /** `ds-icon` size matching control-density icon metrics. */
23
21
  const ICON_SIZE: Record<SelectSize, 'md' | 'sm' | 'xs'> = {
24
22
  md: 'md',
@@ -207,7 +205,7 @@ export class Select {
207
205
  const showPlaceholder = !this.hasSelection;
208
206
  const hasValue = !showPlaceholder;
209
207
  const label = showPlaceholder ? this.placeholder : this.selectedLabel;
210
- const textVariant = TEXT_VARIANT[this.size];
208
+ const textVariant = CONTROL_TEXT_VARIANT[this.size];
211
209
  const iconSize = ICON_SIZE[this.size];
212
210
  const density = `ds-control--${this.size}`;
213
211
  // Selected fill when a value is set (or while open), gated by `activeFill`.
@@ -249,15 +247,15 @@ export class Select {
249
247
  aria-labelledby={this.ariaLabelledby}
250
248
  onClick={() => this.toggle({ focusVisible: false })}
251
249
  >
252
- <span
253
- class={{
254
- 'trigger__label': true,
255
- [textVariant]: true,
256
- 'ds-interaction-fill__content': true,
257
- }}
250
+ <ds-text
251
+ class="trigger__label ds-interaction-fill__content"
252
+ as="span"
253
+ variant={textVariant}
254
+ color="inherit"
255
+ lineTruncation={1}
258
256
  >
259
257
  {label}
260
- </span>
258
+ </ds-text>
261
259
  <span class="trigger__chevron ds-interaction-fill__content" aria-hidden="true">
262
260
  <ds-icon name="ChevronDown" size={iconSize} color="inherit" />
263
261
  </span>
@@ -38,8 +38,12 @@ export class Slider {
38
38
  return (
39
39
  <Host class="field">
40
40
  <div class="label-row">
41
- <label class="text-body-small-emphasis" htmlFor={finalId}>{this.label}</label>
42
- <span class="text-body-small-emphasis">{this.value}</span>
41
+ <ds-text as="label" variant="text-body-small" emphasis for={finalId}>
42
+ {this.label}
43
+ </ds-text>
44
+ <ds-text as="span" variant="text-body-small" emphasis>
45
+ {this.value}
46
+ </ds-text>
43
47
  </div>
44
48
  <div
45
49
  class={{
@@ -180,9 +180,10 @@ export class TabGroup {
180
180
  <span class={{
181
181
  tab__label: true,
182
182
  'tab__label--dot': !!tab.dot,
183
- [isSelected ? 'text-body-small-emphasis' : 'text-body-small']: true,
184
183
  }}>
185
- {tab.label}
184
+ <ds-text as="span" variant="text-body-small" emphasis={isSelected} color="inherit">
185
+ {tab.label}
186
+ </ds-text>
186
187
  {tab.dot && (
187
188
  <ds-badge
188
189
  class="tab__dot"
@@ -323,9 +323,10 @@ export class TabGroupNav {
323
323
  <span class={{
324
324
  tab__label: true,
325
325
  'tab__label--dot': !!tab.dot,
326
- [isSelected ? 'text-body-medium-emphasis' : 'text-body-medium']: true,
327
326
  }}>
328
- {tab.label}
327
+ <ds-text as="span" variant="text-body-medium" emphasis={isSelected} color="inherit">
328
+ {tab.label}
329
+ </ds-text>
329
330
  {tab.dot && (
330
331
  <ds-badge
331
332
  class="tab__dot"