@ds-mo/ui 2.13.1 → 2.15.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 (160) 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-menu.js +1 -1
  36. package/dist/components/ds-modal.js +1 -1
  37. package/dist/components/ds-modal.js.map +1 -1
  38. package/dist/components/ds-pagination.js +1 -1
  39. package/dist/components/ds-pagination.js.map +1 -1
  40. package/dist/components/ds-panel-nav.js +1 -1
  41. package/dist/components/ds-panel-nav.js.map +1 -1
  42. package/dist/components/ds-panel-tools.js +1 -1
  43. package/dist/components/ds-panel-tools.js.map +1 -1
  44. package/dist/components/ds-radio-group.js +1 -1
  45. package/dist/components/ds-radio-group.js.map +1 -1
  46. package/dist/components/ds-select.js +1 -1
  47. package/dist/components/ds-select.js.map +1 -1
  48. package/dist/components/ds-shell-gradient-picker.js +1 -1
  49. package/dist/components/ds-shell-gradient-swatch.js +1 -1
  50. package/dist/components/ds-slider.js +1 -1
  51. package/dist/components/ds-slider.js.map +1 -1
  52. package/dist/components/ds-tab-group-nav.js +1 -1
  53. package/dist/components/ds-tab-group.js +1 -1
  54. package/dist/components/ds-tab-group.js.map +1 -1
  55. package/dist/components/ds-table.js +1 -1
  56. package/dist/components/ds-table.js.map +1 -1
  57. package/dist/components/ds-tag.js +1 -1
  58. package/dist/components/ds-tag.js.map +1 -1
  59. package/dist/components/ds-text.js +1 -1
  60. package/dist/components/ds-toggle.js +1 -1
  61. package/dist/components/ds-tooltip-data-viz.js +1 -1
  62. package/dist/components/ds-tooltip.js +1 -1
  63. package/dist/components/p-061wD4FM.js +2 -0
  64. package/dist/components/p-061wD4FM.js.map +1 -0
  65. package/dist/components/p-AiGt4dQS.js +2 -0
  66. package/dist/components/p-AiGt4dQS.js.map +1 -0
  67. package/dist/components/p-BDQgqw5J.js +2 -0
  68. package/dist/components/p-BDQgqw5J.js.map +1 -0
  69. package/dist/components/p-BvF44IQK.js +2 -0
  70. package/dist/components/p-BvF44IQK.js.map +1 -0
  71. package/dist/components/{p-Be3PHv34.js → p-C3ORQUOp.js} +2 -2
  72. package/dist/components/{p-B82KZX9D.js → p-CyFVn2Sc.js} +2 -2
  73. package/dist/components/p-DIgHkkPe.js +2 -0
  74. package/dist/components/p-DIgHkkPe.js.map +1 -0
  75. package/dist/components/p-DOqi-Vkb.js +2 -0
  76. package/dist/components/p-DOqi-Vkb.js.map +1 -0
  77. package/dist/components/p-DQ3MyAC7.js +2 -0
  78. package/dist/components/p-DQ3MyAC7.js.map +1 -0
  79. package/dist/components/{p-CQmf2CeW.js → p-DkcH8mRl.js} +2 -2
  80. package/dist/components/p-DrhmNrKD.js +2 -0
  81. package/dist/components/p-DrhmNrKD.js.map +1 -0
  82. package/dist/components/{p-B2_D4IDN.js → p-DujEDZ7f.js} +2 -2
  83. package/dist/components/p-DujEDZ7f.js.map +1 -0
  84. package/dist/components/p-DwQ-zdqa.js +2 -0
  85. package/dist/components/p-DwQ-zdqa.js.map +1 -0
  86. package/dist/lib/components/Text/text-types.d.ts +9 -0
  87. package/dist/lib/utils/control-text.d.ts +5 -0
  88. package/dist/lib/utils/index.d.ts +2 -0
  89. package/dist/lib/utils/index.js +8 -0
  90. package/dist/lib/utils/index.js.map +3 -3
  91. package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +1 -1
  92. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +1 -1
  93. package/dist/types/components/PanelTools/PanelTools.d.ts +1 -1
  94. package/dist/types/components/PanelTools/index.d.ts +1 -1
  95. package/dist/types/components/PanelTools/panel-tools-types.d.ts +3 -1
  96. package/dist/types/components/Select/Select.d.ts +1 -1
  97. package/dist/types/components/Text/Text.d.ts +9 -9
  98. package/dist/types/components/Text/index.d.ts +2 -1
  99. package/dist/types/components/Text/text-types.d.ts +10 -0
  100. package/dist/types/components/Text/text-utils.d.ts +4 -0
  101. package/dist/types/components/Tooltip/Tooltip.d.ts +1 -0
  102. package/dist/types/components.d.ts +24 -4
  103. package/dist/types/utils/control-text.d.ts +6 -0
  104. package/dist/types/utils/index.d.ts +2 -0
  105. package/package.json +2 -2
  106. package/src/angular/proxies.ts +2 -2
  107. package/src/wc/components/Badge/Badge.tsx +6 -8
  108. package/src/wc/components/Banner/Banner.tsx +5 -1
  109. package/src/wc/components/BarNav/BarNav.tsx +5 -1
  110. package/src/wc/components/ButtonFilled/ButtonFilled.tsx +6 -11
  111. package/src/wc/components/ButtonUnfilled/ButtonUnfilled.tsx +6 -11
  112. package/src/wc/components/Card/Card.tsx +10 -8
  113. package/src/wc/components/Checkbox/Checkbox.tsx +4 -2
  114. package/src/wc/components/Chip/Chip.tsx +6 -10
  115. package/src/wc/components/EmptyState/EmptyState.tsx +2 -2
  116. package/src/wc/components/Field/Field.tsx +3 -1
  117. package/src/wc/components/Menu/Menu.tsx +14 -4
  118. package/src/wc/components/Modal/Modal.tsx +17 -3
  119. package/src/wc/components/Pagination/Pagination.tsx +3 -3
  120. package/src/wc/components/PanelNav/PanelNav.tsx +5 -4
  121. package/src/wc/components/PanelTools/PanelTools.tsx +37 -10
  122. package/src/wc/components/PanelTools/index.ts +1 -0
  123. package/src/wc/components/PanelTools/panel-tools-types.ts +12 -1
  124. package/src/wc/components/RadioGroup/RadioGroup.tsx +5 -1
  125. package/src/wc/components/Select/Select.tsx +12 -18
  126. package/src/wc/components/Slider/Slider.tsx +6 -2
  127. package/src/wc/components/TabGroup/TabGroup.tsx +3 -2
  128. package/src/wc/components/TabGroupNav/TabGroupNav.tsx +3 -2
  129. package/src/wc/components/Table/Table.tsx +12 -10
  130. package/src/wc/components/Tag/Tag.tsx +6 -10
  131. package/src/wc/components/Text/Text.tsx +51 -57
  132. package/src/wc/components/Text/index.ts +12 -1
  133. package/src/wc/components/Text/text-types.ts +23 -0
  134. package/src/wc/components/Text/text-utils.ts +6 -0
  135. package/src/wc/components/Tooltip/Tooltip.tsx +58 -41
  136. package/src/wc/components/TooltipDataViz/TooltipDataViz.tsx +1 -1
  137. package/src/wc/components.d.ts +24 -4
  138. package/src/wc/utils/control-density.css +6 -1
  139. package/src/wc/utils/control-text.ts +11 -0
  140. package/src/wc/utils/index.ts +2 -0
  141. package/dist/components/p-1m8r0wFg.js +0 -2
  142. package/dist/components/p-1m8r0wFg.js.map +0 -1
  143. package/dist/components/p-3FLHei19.js +0 -2
  144. package/dist/components/p-3FLHei19.js.map +0 -1
  145. package/dist/components/p-B2_D4IDN.js.map +0 -1
  146. package/dist/components/p-B5NcWtpp.js +0 -2
  147. package/dist/components/p-B5NcWtpp.js.map +0 -1
  148. package/dist/components/p-CDHRJqea.js +0 -2
  149. package/dist/components/p-CDHRJqea.js.map +0 -1
  150. package/dist/components/p-CtwNUCnp.js +0 -2
  151. package/dist/components/p-CtwNUCnp.js.map +0 -1
  152. package/dist/components/p-CuRjYmBk.js +0 -2
  153. package/dist/components/p-CuRjYmBk.js.map +0 -1
  154. package/dist/components/p-CwARVsZQ.js +0 -2
  155. package/dist/components/p-CwARVsZQ.js.map +0 -1
  156. package/dist/components/p-EK1hOP19.js +0 -2
  157. package/dist/components/p-EK1hOP19.js.map +0 -1
  158. /package/dist/components/{p-Be3PHv34.js.map → p-C3ORQUOp.js.map} +0 -0
  159. /package/dist/components/{p-B82KZX9D.js.map → p-CyFVn2Sc.js.map} +0 -0
  160. /package/dist/components/{p-CQmf2CeW.js.map → p-DkcH8mRl.js.map} +0 -0
@@ -1,6 +1,7 @@
1
1
  import { Component, Prop, Event, EventEmitter, Element, State, Watch, Method, h, Host } from '@stencil/core';
2
2
  import type { ChromeTransitionDetail } from '../../nav/chrome-transition';
3
3
  import {
4
+ PANEL_TOOLS_FOOTER_TOOL_ID,
4
5
  PANEL_TOOLS_LABELS,
5
6
  PANEL_TOOLS_PRIMARY_TOOL_ID,
6
7
  type PanelToolsItem,
@@ -19,7 +20,7 @@ export class PanelTools {
19
20
  /** When false, only the icon rail is shown. */
20
21
  @Prop({ mutable: true, reflect: true }) open: boolean = false;
21
22
 
22
- /** Active tool view — `search`, `agents`, `messages`, `stacks`, or `activity`. */
23
+ /** Active tool view — `search`, `agents`, `messages`, `stacks`, `activity`, or `help`. */
23
24
  @Prop({ mutable: true, attribute: 'active-tool', reflect: true })
24
25
  activeTool: PanelToolsToolId | '' = '';
25
26
 
@@ -62,8 +63,15 @@ export class PanelTools {
62
63
  private get orderedRailItems(): PanelToolsItem[] {
63
64
  const railItems = this.railItems;
64
65
  const headerItem = railItems.find(item => item.id === PANEL_TOOLS_PRIMARY_TOOL_ID);
65
- const bodyItems = railItems.filter(item => item.id !== PANEL_TOOLS_PRIMARY_TOOL_ID);
66
- return headerItem ? [headerItem, ...bodyItems] : bodyItems;
66
+ const footerItem = railItems.find(item => item.id === PANEL_TOOLS_FOOTER_TOOL_ID);
67
+ const bodyItems = railItems.filter(
68
+ item => item.id !== PANEL_TOOLS_PRIMARY_TOOL_ID && item.id !== PANEL_TOOLS_FOOTER_TOOL_ID,
69
+ );
70
+ const ordered: PanelToolsItem[] = [];
71
+ if (headerItem) ordered.push(headerItem);
72
+ ordered.push(...bodyItems);
73
+ if (footerItem) ordered.push(footerItem);
74
+ return ordered;
67
75
  }
68
76
 
69
77
  disconnectedCallback() {
@@ -230,7 +238,13 @@ export class PanelTools {
230
238
  const headerLabel = this.headerLabel();
231
239
  const orderedRailItems = this.orderedRailItems;
232
240
  const headerItem = orderedRailItems.find(item => item.id === PANEL_TOOLS_PRIMARY_TOOL_ID);
233
- const bodyItems = orderedRailItems.filter(item => item.id !== PANEL_TOOLS_PRIMARY_TOOL_ID);
241
+ const footerItem = orderedRailItems.find(item => item.id === PANEL_TOOLS_FOOTER_TOOL_ID);
242
+ const bodyItems = orderedRailItems.filter(
243
+ item => item.id !== PANEL_TOOLS_PRIMARY_TOOL_ID && item.id !== PANEL_TOOLS_FOOTER_TOOL_ID,
244
+ );
245
+ const footerIndex = footerItem
246
+ ? (headerItem ? 1 : 0) + bodyItems.length
247
+ : -1;
234
248
  const showDrawerChrome = this.isDrawerPresent();
235
249
  const drawerResting = panelToolsDrawerResting(this.open, this.motion);
236
250
 
@@ -259,6 +273,11 @@ export class PanelTools {
259
273
  this.renderRailAction(item, headerItem ? bodyIdx + 1 : bodyIdx),
260
274
  )}
261
275
  </div>
276
+ {footerItem ? (
277
+ <div class="panel-tools__rail-footer">
278
+ {this.renderRailAction(footerItem, footerIndex)}
279
+ </div>
280
+ ) : null}
262
281
  </nav>
263
282
 
264
283
  <div
@@ -271,14 +290,17 @@ export class PanelTools {
271
290
  >
272
291
  <div class="panel-tools__drawer-surface">
273
292
  <header class="panel-tools__header">
274
- <span class="panel-tools__title text-body-medium-emphasis">{headerLabel}</span>
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>
275
298
  </header>
276
299
  <div class="panel-tools__body">
277
300
  <div
278
301
  class={{
279
302
  'panel-tools__view': true,
280
303
  'panel-tools__view--active': this.isViewActive('search'),
281
- 'text-body-medium': true,
282
304
  }}
283
305
  hidden={!this.isViewActive('search')}
284
306
  >
@@ -288,7 +310,6 @@ export class PanelTools {
288
310
  class={{
289
311
  'panel-tools__view': true,
290
312
  'panel-tools__view--active': this.isViewActive('messages'),
291
- 'text-body-medium': true,
292
313
  }}
293
314
  hidden={!this.isViewActive('messages')}
294
315
  >
@@ -298,7 +319,6 @@ export class PanelTools {
298
319
  class={{
299
320
  'panel-tools__view': true,
300
321
  'panel-tools__view--active': this.isViewActive('stacks'),
301
- 'text-body-medium': true,
302
322
  }}
303
323
  hidden={!this.isViewActive('stacks')}
304
324
  >
@@ -308,7 +328,6 @@ export class PanelTools {
308
328
  class={{
309
329
  'panel-tools__view': true,
310
330
  'panel-tools__view--active': this.isViewActive('activity'),
311
- 'text-body-medium': true,
312
331
  }}
313
332
  hidden={!this.isViewActive('activity')}
314
333
  >
@@ -318,12 +337,20 @@ export class PanelTools {
318
337
  class={{
319
338
  'panel-tools__view': true,
320
339
  'panel-tools__view--active': this.isViewActive('agents'),
321
- 'text-body-medium': true,
322
340
  }}
323
341
  hidden={!this.isViewActive('agents')}
324
342
  >
325
343
  <slot name="agents" />
326
344
  </div>
345
+ <div
346
+ class={{
347
+ 'panel-tools__view': true,
348
+ 'panel-tools__view--active': this.isViewActive('help'),
349
+ }}
350
+ hidden={!this.isViewActive('help')}
351
+ >
352
+ <slot name="help" />
353
+ </div>
327
354
  </div>
328
355
  </div>
329
356
  </div>
@@ -1,5 +1,6 @@
1
1
  export type { PanelToolsItem, PanelToolsToolId } from './panel-tools-types';
2
2
  export {
3
+ PANEL_TOOLS_FOOTER_TOOL_ID,
3
4
  PANEL_TOOLS_LABELS,
4
5
  PANEL_TOOLS_PRIMARY_TOOL_ID,
5
6
  PANEL_TOOLS_TOOL_IDS,
@@ -1,5 +1,11 @@
1
1
  /** Tool ids for the `ds-panel-tools` rail and drawer views. */
2
- export type PanelToolsToolId = 'search' | 'agents' | 'messages' | 'stacks' | 'activity';
2
+ export type PanelToolsToolId =
3
+ | 'search'
4
+ | 'agents'
5
+ | 'messages'
6
+ | 'stacks'
7
+ | 'activity'
8
+ | 'help';
3
9
 
4
10
  export const PANEL_TOOLS_TOOL_IDS: PanelToolsToolId[] = [
5
11
  'search',
@@ -7,17 +13,22 @@ export const PANEL_TOOLS_TOOL_IDS: PanelToolsToolId[] = [
7
13
  'messages',
8
14
  'stacks',
9
15
  'activity',
16
+ 'help',
10
17
  ];
11
18
 
12
19
  /** Rail header slot — mirrors panel-nav M logo row. */
13
20
  export const PANEL_TOOLS_PRIMARY_TOOL_ID: PanelToolsToolId = 'search';
14
21
 
22
+ /** Rail footer slot — flush to the bottom of the tools column. */
23
+ export const PANEL_TOOLS_FOOTER_TOOL_ID: PanelToolsToolId = 'help';
24
+
15
25
  export const PANEL_TOOLS_LABELS: Record<PanelToolsToolId, string> = {
16
26
  search: 'Search',
17
27
  messages: 'Messages',
18
28
  stacks: 'Stacks',
19
29
  activity: 'Activity',
20
30
  agents: 'Agents',
31
+ help: 'Help & Support',
21
32
  };
22
33
 
23
34
  export interface PanelToolsItem {
@@ -118,7 +118,11 @@ 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
+ <span class="radio-label">
122
+ <ds-text as="span" variant="text-body-medium">
123
+ {opt.label}
124
+ </ds-text>
125
+ </span>
122
126
  </div>
123
127
  );
124
128
  })}
@@ -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,14 +247,10 @@ 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
- }}
258
- >
259
- {label}
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>
260
254
  </span>
261
255
  <span class="trigger__chevron ds-interaction-fill__content" aria-hidden="true">
262
256
  <ds-icon name="ChevronDown" size={iconSize} color="inherit" />
@@ -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"
@@ -150,9 +150,9 @@ export class Table {
150
150
  }}
151
151
  style={col.minWidth ? { minWidth: typeof col.minWidth === 'number' ? `${col.minWidth}px` : col.minWidth as string } : undefined}
152
152
  >
153
- <span class="text-body-small-emphasis" style={{ color: 'var(--color-foreground-secondary)' }}>
153
+ <ds-text as="span" variant="text-body-small" emphasis color="secondary">
154
154
  {col.header}
155
- </span>
155
+ </ds-text>
156
156
  {isSorted && (
157
157
  <span class="sort-indicator" aria-hidden="true">
158
158
  {sort.direction === 'asc' ? '↑' : '↓'}
@@ -182,9 +182,9 @@ export class Table {
182
182
  {/* Empty state */}
183
183
  {isEmpty && (
184
184
  <div class="empty-row" style={{ gridColumn: '1 / -1' }}>
185
- <p class="text-body-medium" style={{ margin: '0', color: 'var(--color-foreground-secondary)' }}>
185
+ <ds-text as="p" variant="text-body-medium" color="secondary">
186
186
  {this.emptyMessage}
187
- </p>
187
+ </ds-text>
188
188
  </div>
189
189
  )}
190
190
 
@@ -220,8 +220,10 @@ export class Table {
220
220
  }}
221
221
  role="cell"
222
222
  >
223
- <span class="text-body-medium cell-value">
224
- {String(getCellValue(col, row) ?? '')}
223
+ <span class="cell-value">
224
+ <ds-text as="span" variant="text-body-medium">
225
+ {String(getCellValue(col, row) ?? '')}
226
+ </ds-text>
225
227
  </span>
226
228
  </div>
227
229
  ))}
@@ -243,11 +245,11 @@ export class Table {
243
245
  this.dsPageChange.emit({ pageIndex: this.pageIndex });
244
246
  }}
245
247
  >
246
- <span class="text-body-small">Previous</span>
248
+ <ds-text as="span" variant="text-body-small">Previous</ds-text>
247
249
  </button>
248
- <span class="text-body-small" style={{ color: 'var(--color-foreground-secondary)' }}>
250
+ <ds-text as="span" variant="text-body-small" color="secondary">
249
251
  Page {this.pageIndex! + 1} of {totalPages}
250
- </span>
252
+ </ds-text>
251
253
  <button
252
254
  type="button"
253
255
  class="page-button"
@@ -257,7 +259,7 @@ export class Table {
257
259
  this.dsPageChange.emit({ pageIndex: this.pageIndex });
258
260
  }}
259
261
  >
260
- <span class="text-body-small">Next</span>
262
+ <ds-text as="span" variant="text-body-small">Next</ds-text>
261
263
  </button>
262
264
  </div>
263
265
  )}
@@ -1,16 +1,10 @@
1
1
  import { Component, Prop, h, Host } from '@stencil/core';
2
+ import { CONTROL_TEXT_VARIANT } from '../../utils';
2
3
 
3
4
  export type TagIntent = 'neutral' | 'brand' | 'ai' | 'negative' | 'warning' | 'caution' | 'positive';
4
5
  export type TagContrast = 'strong' | 'bold' | 'medium' | 'faint';
5
6
  export type TagSize = 'md' | 'sm' | 'xs';
6
7
 
7
- /** Text variant per control-density recipe (md / sm / xs). */
8
- const TEXT_VARIANT: Record<TagSize, string> = {
9
- md: 'text-body-medium',
10
- sm: 'text-body-small',
11
- xs: 'text-caption',
12
- };
13
-
14
8
  /**
15
9
  * `ds-icon` size prop matching control-density icon metrics
16
10
  * (md→20 / sm→16 / xs→12 via `--dimension-iconography-*`).
@@ -35,7 +29,7 @@ export class Tag {
35
29
  @Prop() maxWidth: string | number | undefined;
36
30
 
37
31
  render() {
38
- const textVariant = TEXT_VARIANT[this.size];
32
+ const textVariant = CONTROL_TEXT_VARIANT[this.size];
39
33
  const iconSize = ICON_SIZE[this.size];
40
34
 
41
35
  const maxWidthStyle = this.maxWidth != null
@@ -60,8 +54,10 @@ export class Tag {
60
54
  <span class="tag__icon-slot" data-icon-size={iconSize}>
61
55
  <slot name="icon" />
62
56
  </span>
63
- <span class={{ 'tag__label': true, [textVariant]: true }}>
64
- {this.label}
57
+ <span class="tag__label">
58
+ <ds-text as="span" variant={textVariant} color="inherit">
59
+ {this.label}
60
+ </ds-text>
65
61
  </span>
66
62
  </Host>
67
63
  );
@@ -1,32 +1,15 @@
1
1
  import { Component, Prop, h, Host } from '@stencil/core';
2
-
3
- export type TextVariant =
4
- | 'text-display-medium'
5
- | 'text-display-small'
6
- | 'text-title-large'
7
- | 'text-title-medium'
8
- | 'text-title-small'
9
- | 'text-body-large'
10
- | 'text-body-large-emphasis'
11
- | 'text-body-medium'
12
- | 'text-body-medium-emphasis'
13
- | 'text-body-small'
14
- | 'text-body-small-emphasis'
15
- | 'text-caption'
16
- | 'text-caption-emphasis';
17
-
18
- export type TextColorToken =
19
- | 'primary' | 'secondary' | 'tertiary'
20
- | 'brand' | 'negative' | 'positive' | 'warning' | 'caution' | 'ai'
21
- | 'on-strong' | 'on-bold' | 'inherit';
22
-
23
- export type TextColor = TextColorToken | `var(--${string})`;
24
- export type TextDecoration = 'none' | 'underline' | 'dotted-underline';
25
- export type TextAlign = 'left' | 'center' | 'right';
26
- export type LineTruncation = 1 | 2 | 3 | 4 | 5 | 'none';
27
- export type TextWrap = 'wrap' | 'nowrap' | 'balance' | 'pretty';
28
- export type TextElement = 'p' | 'span' | 'div' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
29
- export type TextFontFeature = 'normal' | 'tabular-nums';
2
+ import { textVariantClass } from './text-utils';
3
+ import type {
4
+ TextAlign,
5
+ TextColor,
6
+ TextDecoration,
7
+ TextElement,
8
+ TextFontFeature,
9
+ TextVariant,
10
+ LineTruncation,
11
+ TextWrap,
12
+ } from './text-types';
30
13
 
31
14
  @Component({
32
15
  tag: 'ds-text',
@@ -35,6 +18,12 @@ export type TextFontFeature = 'normal' | 'tabular-nums';
35
18
  })
36
19
  export class Text {
37
20
  @Prop() variant: TextVariant = 'text-body-medium';
21
+ /**
22
+ * Heavier weight + tighter letter-spacing for the variant.
23
+ * `false` (default): regular weight (caption stays medium).
24
+ * `true`: display bold, title/caption semibold, body medium.
25
+ */
26
+ @Prop() emphasis: boolean = false;
38
27
  @Prop() color: TextColor | undefined;
39
28
  @Prop() decoration: TextDecoration | undefined;
40
29
  @Prop() italic: boolean = false;
@@ -45,6 +34,8 @@ export class Text {
45
34
  @Prop() as: TextElement = 'p';
46
35
  /** Maps to `for` attribute on <label> elements. */
47
36
  @Prop() for: string | undefined;
37
+ /** Forwarded to the inner element (e.g. aria-labelledby targets). */
38
+ @Prop() textId: string | undefined;
48
39
 
49
40
  render() {
50
41
  // Polymorphic element: TSX treats a variable tag as a component, so a
@@ -54,35 +45,37 @@ export class Text {
54
45
  const isCustomColor = (c: TextColor) => typeof c === 'string' && c.startsWith('var(--');
55
46
 
56
47
  const cls: Record<string, boolean> = {
57
- [this.variant]: true,
58
- 'text': true,
59
- 'text--nowrap': this.wrap === 'nowrap',
60
- 'text--balance': this.wrap === 'balance',
61
- 'text--pretty': this.wrap === 'pretty',
62
- 'text--truncate-1': this.lineTruncation === 1 && this.wrap !== 'nowrap',
63
- 'text--truncate-2': this.lineTruncation === 2 && this.wrap !== 'nowrap',
64
- 'text--truncate-3': this.lineTruncation === 3 && this.wrap !== 'nowrap',
65
- 'text--truncate-4': this.lineTruncation === 4 && this.wrap !== 'nowrap',
66
- 'text--truncate-5': this.lineTruncation === 5 && this.wrap !== 'nowrap',
67
- 'text--color-primary': this.color === 'primary',
68
- 'text--color-secondary': this.color === 'secondary',
69
- 'text--color-tertiary': this.color === 'tertiary',
70
- 'text--color-brand': this.color === 'brand',
71
- 'text--color-negative': this.color === 'negative',
72
- 'text--color-positive': this.color === 'positive',
73
- 'text--color-warning': this.color === 'warning',
74
- 'text--color-caution': this.color === 'caution',
75
- 'text--color-ai': this.color === 'ai',
76
- 'text--color-on-strong': this.color === 'on-strong',
77
- 'text--color-on-bold': this.color === 'on-bold',
78
- 'text--color-inherit': this.color === 'inherit',
79
- 'text--decoration-underline': this.decoration === 'underline',
80
- 'text--decoration-dotted-underline': this.decoration === 'dotted-underline',
81
- 'text--italic': this.italic,
82
- 'text--align-left': this.align === 'left',
83
- 'text--align-center': this.align === 'center',
84
- 'text--align-right': this.align === 'right',
85
- 'text--font-feature-tabular-nums': this.fontFeature === 'tabular-nums',
48
+ 'ds-text': true,
49
+ [textVariantClass(this.variant)]: true,
50
+ 'ds-text--emphasis': this.emphasis,
51
+ 'ds-text--regular': !this.emphasis,
52
+ 'ds-text--nowrap': this.wrap === 'nowrap',
53
+ 'ds-text--balance': this.wrap === 'balance',
54
+ 'ds-text--pretty': this.wrap === 'pretty',
55
+ 'ds-text--truncate-1': this.lineTruncation === 1 && this.wrap !== 'nowrap',
56
+ 'ds-text--truncate-2': this.lineTruncation === 2 && this.wrap !== 'nowrap',
57
+ 'ds-text--truncate-3': this.lineTruncation === 3 && this.wrap !== 'nowrap',
58
+ 'ds-text--truncate-4': this.lineTruncation === 4 && this.wrap !== 'nowrap',
59
+ 'ds-text--truncate-5': this.lineTruncation === 5 && this.wrap !== 'nowrap',
60
+ 'ds-text--color-primary': this.color === 'primary',
61
+ 'ds-text--color-secondary': this.color === 'secondary',
62
+ 'ds-text--color-tertiary': this.color === 'tertiary',
63
+ 'ds-text--color-brand': this.color === 'brand',
64
+ 'ds-text--color-negative': this.color === 'negative',
65
+ 'ds-text--color-positive': this.color === 'positive',
66
+ 'ds-text--color-warning': this.color === 'warning',
67
+ 'ds-text--color-caution': this.color === 'caution',
68
+ 'ds-text--color-ai': this.color === 'ai',
69
+ 'ds-text--color-on-strong': this.color === 'on-strong',
70
+ 'ds-text--color-on-bold': this.color === 'on-bold',
71
+ 'ds-text--color-inherit': this.color === 'inherit',
72
+ 'ds-text--decoration-underline': this.decoration === 'underline',
73
+ 'ds-text--decoration-dotted-underline': this.decoration === 'dotted-underline',
74
+ 'ds-text--italic': this.italic,
75
+ 'ds-text--align-left': this.align === 'left',
76
+ 'ds-text--align-center': this.align === 'center',
77
+ 'ds-text--align-right': this.align === 'right',
78
+ 'ds-text--font-feature-tabular-nums': this.fontFeature === 'tabular-nums',
86
79
  };
87
80
 
88
81
  const style = this.color && isCustomColor(this.color)
@@ -91,6 +84,7 @@ export class Text {
91
84
 
92
85
  const extraProps: Record<string, string> = {};
93
86
  if (this.as === 'label' && this.for) extraProps['for'] = this.for;
87
+ if (this.textId) extraProps['id'] = this.textId;
94
88
 
95
89
  return (
96
90
  <Host style={{ display: 'contents' }}>
@@ -1 +1,12 @@
1
- export type { TextVariant, TextColor, TextColorToken, TextDecoration, TextAlign, LineTruncation, TextWrap, TextElement } from './Text';
1
+ export type {
2
+ TextVariant,
3
+ TextColor,
4
+ TextColorToken,
5
+ TextDecoration,
6
+ TextAlign,
7
+ LineTruncation,
8
+ TextWrap,
9
+ TextElement,
10
+ TextFontFeature,
11
+ } from './text-types';
12
+ export { textVariantClass } from './text-utils';
@@ -0,0 +1,23 @@
1
+ export type TextVariant =
2
+ | 'text-display-medium'
3
+ | 'text-display-small'
4
+ | 'text-title-large'
5
+ | 'text-title-medium'
6
+ | 'text-title-small'
7
+ | 'text-body-large'
8
+ | 'text-body-medium'
9
+ | 'text-body-small'
10
+ | 'text-caption';
11
+
12
+ export type TextColorToken =
13
+ | 'primary' | 'secondary' | 'tertiary'
14
+ | 'brand' | 'negative' | 'positive' | 'warning' | 'caution' | 'ai'
15
+ | 'on-strong' | 'on-bold' | 'inherit';
16
+
17
+ export type TextColor = TextColorToken | `var(--${string})`;
18
+ export type TextDecoration = 'none' | 'underline' | 'dotted-underline';
19
+ export type TextAlign = 'left' | 'center' | 'right';
20
+ export type LineTruncation = 1 | 2 | 3 | 4 | 5 | 'none';
21
+ export type TextWrap = 'wrap' | 'nowrap' | 'balance' | 'pretty';
22
+ export type TextElement = 'p' | 'span' | 'div' | 'label' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
23
+ export type TextFontFeature = 'normal' | 'tabular-nums';
@@ -0,0 +1,6 @@
1
+ import type { TextVariant } from './text-types';
2
+
3
+ /** `text-body-medium` → `ds-text--body-medium` */
4
+ export function textVariantClass(variant: TextVariant): string {
5
+ return `ds-text--${variant.replace(/^text-/, '')}`;
6
+ }