@ds-mo/ui 2.11.2 → 2.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. package/README.md +13 -13
  2. package/dist/.build-stamp +1 -1
  3. package/dist/components/ds-app-shell.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-accordion.d.ts → ds-button-unfilled.d.ts} +4 -4
  10. package/dist/components/ds-button-unfilled.js +2 -0
  11. package/dist/components/{ds-card-data-viz.d.ts → ds-card-data-viz-donut.d.ts} +4 -4
  12. package/dist/components/ds-card-data-viz-donut.js +2 -0
  13. package/dist/components/ds-card-data-viz-donut.js.map +1 -0
  14. package/dist/components/ds-card-setting.js +1 -1
  15. package/dist/components/ds-card-setting.js.map +1 -1
  16. package/dist/components/{ds-fade.d.ts → ds-card.d.ts} +4 -4
  17. package/dist/components/ds-card.js +2 -0
  18. package/dist/components/ds-card.js.map +1 -0
  19. package/dist/components/ds-chart-bar.js +1 -1
  20. package/dist/components/ds-chart-bar.js.map +1 -1
  21. package/dist/components/ds-chart-donut.js +1 -1
  22. package/dist/components/ds-chart-donut.js.map +1 -1
  23. package/dist/components/ds-chart-legend.js +1 -1
  24. package/dist/components/ds-chart-legend.js.map +1 -1
  25. package/dist/components/ds-chart-line.js +1 -1
  26. package/dist/components/ds-checkbox.js +1 -1
  27. package/dist/components/ds-checkbox.js.map +1 -1
  28. package/dist/components/ds-chip.js +1 -1
  29. package/dist/components/ds-chip.js.map +1 -1
  30. package/dist/components/ds-empty-state.js +1 -1
  31. package/dist/components/ds-empty-state.js.map +1 -1
  32. package/dist/components/ds-field.js +1 -1
  33. package/dist/components/ds-icon.js +1 -1
  34. package/dist/components/ds-input.js +1 -1
  35. package/dist/components/ds-input.js.map +1 -1
  36. package/dist/components/ds-loader.js +1 -1
  37. package/dist/components/ds-loader.js.map +1 -1
  38. package/dist/components/ds-menu.js +1 -1
  39. package/dist/components/ds-modal.js +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-skeleton.js +1 -1
  53. package/dist/components/ds-skeleton.js.map +1 -1
  54. package/dist/components/ds-slider.js +1 -1
  55. package/dist/components/ds-slider.js.map +1 -1
  56. package/dist/components/ds-tab-group-nav.js +1 -1
  57. package/dist/components/ds-tab-group.js +1 -1
  58. package/dist/components/ds-tab-group.js.map +1 -1
  59. package/dist/components/ds-table.js +1 -1
  60. package/dist/components/ds-table.js.map +1 -1
  61. package/dist/components/ds-tag.js +1 -1
  62. package/dist/components/ds-tag.js.map +1 -1
  63. package/dist/components/ds-text.js +1 -1
  64. package/dist/components/ds-toggle.js +1 -1
  65. package/dist/components/ds-toggle.js.map +1 -1
  66. package/dist/components/ds-tooltip-data-viz.js +1 -1
  67. package/dist/components/ds-tooltip-data-viz.js.map +1 -1
  68. package/dist/components/ds-tooltip.js +1 -1
  69. package/dist/components/ds-tooltip.js.map +1 -1
  70. package/dist/components/p-1m8r0wFg.js +2 -0
  71. package/dist/components/p-1m8r0wFg.js.map +1 -0
  72. package/dist/components/p-3FLHei19.js +2 -0
  73. package/dist/components/p-3FLHei19.js.map +1 -0
  74. package/dist/components/p-B2_D4IDN.js +2 -0
  75. package/dist/components/p-B2_D4IDN.js.map +1 -0
  76. package/dist/components/p-B5NcWtpp.js +2 -0
  77. package/dist/components/p-B5NcWtpp.js.map +1 -0
  78. package/dist/components/{p-8Nt92j1-.js → p-B82KZX9D.js} +2 -2
  79. package/dist/components/p-BQq26pt9.js.map +1 -1
  80. package/dist/components/p-B_g8X0eh.js +2 -0
  81. package/dist/components/p-B_g8X0eh.js.map +1 -0
  82. package/dist/components/{p-DdFUTZ3y.js → p-Be3PHv34.js} +2 -2
  83. package/dist/components/p-CQmf2CeW.js +2 -0
  84. package/dist/components/p-CQmf2CeW.js.map +1 -0
  85. package/dist/components/{p-DOU4cbpc.js → p-CtwNUCnp.js} +2 -2
  86. package/dist/components/p-CuRjYmBk.js +2 -0
  87. package/dist/components/p-CuRjYmBk.js.map +1 -0
  88. package/dist/components/p-CwARVsZQ.js +2 -0
  89. package/dist/components/p-CwARVsZQ.js.map +1 -0
  90. package/dist/components/p-DohXlNCJ.js +2 -0
  91. package/dist/components/p-DohXlNCJ.js.map +1 -0
  92. package/dist/components/p-DuFm-ieS.js +2 -0
  93. package/dist/components/p-DuFm-ieS.js.map +1 -0
  94. package/dist/components/p-EK1hOP19.js.map +1 -1
  95. package/dist/lib/nav/index.js +3 -0
  96. package/dist/lib/nav/index.js.map +2 -2
  97. package/dist/lib/utils/control-width.d.ts +4 -0
  98. package/dist/lib/utils/index.d.ts +2 -0
  99. package/dist/lib/utils/index.js +20 -1
  100. package/dist/lib/utils/index.js.map +3 -3
  101. package/dist/lib/utils/token-defaults.d.ts +7 -0
  102. package/dist/types/components/ButtonFilled/ButtonFilled.d.ts +21 -3
  103. package/dist/types/components/ButtonFilled/index.d.ts +1 -1
  104. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +70 -0
  105. package/dist/types/components/ButtonUnfilled/index.d.ts +2 -0
  106. package/dist/types/components/Card/Card.d.ts +20 -0
  107. package/dist/types/components/Card/index.d.ts +2 -0
  108. package/dist/types/components/CardDataVizDonut/CardDataVizDonut.d.ts +26 -0
  109. package/dist/types/components/CardDataVizDonut/index.d.ts +2 -0
  110. package/dist/types/components/CardSetting/CardSetting.d.ts +7 -2
  111. package/dist/types/components/ChartDonut/ChartDonut.d.ts +31 -1
  112. package/dist/types/components/Checkbox/Checkbox.d.ts +1 -1
  113. package/dist/types/components/Chip/Chip.d.ts +18 -14
  114. package/dist/types/components/Chip/index.d.ts +1 -1
  115. package/dist/types/components/Input/Input.d.ts +1 -1
  116. package/dist/types/components/Pagination/Pagination.d.ts +1 -1
  117. package/dist/types/components/PanelNav/PanelNav.d.ts +2 -0
  118. package/dist/types/components/PanelTools/panel-tools-types.d.ts +1 -1
  119. package/dist/types/components/RadioGroup/RadioGroup.d.ts +2 -2
  120. package/dist/types/components/Select/Select.d.ts +34 -2
  121. package/dist/types/components/Select/index.d.ts +2 -0
  122. package/dist/types/components/ShellGradientSwatch/ShellGradientSwatch.d.ts +1 -1
  123. package/dist/types/components/Slider/Slider.d.ts +1 -1
  124. package/dist/types/components/TabGroup/TabGroup.d.ts +1 -1
  125. package/dist/types/components/TabGroup/tab-item-utils.d.ts +2 -1
  126. package/dist/types/components/TabGroupNav/TabGroupNav.d.ts +1 -1
  127. package/dist/types/components/Tag/Tag.d.ts +0 -2
  128. package/dist/types/components/Tag/index.d.ts +1 -1
  129. package/dist/types/components/Toggle/Toggle.d.ts +1 -1
  130. package/dist/types/components/Tooltip/Tooltip.d.ts +25 -6
  131. package/dist/types/components/TooltipDataViz/TooltipDataViz.d.ts +18 -0
  132. package/dist/types/components.d.ts +474 -576
  133. package/dist/types/utils/control-width.d.ts +5 -0
  134. package/dist/types/utils/index.d.ts +2 -0
  135. package/dist/types/utils/token-defaults.d.ts +7 -0
  136. package/package.json +7 -4
  137. package/src/angular/index.ts +3 -9
  138. package/src/angular/proxies.ts +62 -215
  139. package/src/react/components.ts +3 -9
  140. package/src/react/ds-button-unfilled.ts +33 -0
  141. package/src/react/ds-card-data-viz-donut.ts +27 -0
  142. package/src/react/{ds-fade.ts → ds-card.ts} +7 -7
  143. package/src/react/ds-chip.ts +2 -10
  144. package/src/wc/components/BarNav/BarNav.tsx +3 -2
  145. package/src/wc/components/BarNav/bar-nav-tabs-menu-utils.ts +1 -1
  146. package/src/wc/components/ButtonFilled/ButtonFilled.tsx +97 -11
  147. package/src/wc/components/ButtonFilled/index.ts +7 -1
  148. package/src/wc/components/ButtonUnfilled/ButtonUnfilled.tsx +230 -0
  149. package/src/wc/components/ButtonUnfilled/index.ts +7 -0
  150. package/src/wc/components/Card/Card.tsx +79 -0
  151. package/src/wc/components/Card/index.ts +1 -0
  152. package/src/wc/components/{CardDataViz/CardDataViz.tsx → CardDataVizDonut/CardDataVizDonut.tsx} +47 -41
  153. package/src/wc/components/CardDataVizDonut/index.ts +1 -0
  154. package/src/wc/components/CardSetting/CardSetting.tsx +21 -36
  155. package/src/wc/components/ChartDonut/ChartDonut.tsx +159 -11
  156. package/src/wc/components/ChartLegend/ChartLegend.tsx +3 -0
  157. package/src/wc/components/Checkbox/Checkbox.tsx +5 -5
  158. package/src/wc/components/Chip/Chip.tsx +50 -67
  159. package/src/wc/components/Chip/index.ts +1 -1
  160. package/src/wc/components/Input/Input.tsx +4 -4
  161. package/src/wc/components/Menu/Menu.tsx +7 -4
  162. package/src/wc/components/Pagination/Pagination.tsx +6 -6
  163. package/src/wc/components/PanelNav/PanelNav.tsx +77 -48
  164. package/src/wc/components/PanelTools/PanelTools.tsx +19 -16
  165. package/src/wc/components/PanelTools/panel-tools-types.ts +1 -1
  166. package/src/wc/components/PanelTools/panel-tools-utils.ts +1 -1
  167. package/src/wc/components/RadioGroup/RadioGroup.tsx +7 -7
  168. package/src/wc/components/Select/Select.tsx +145 -64
  169. package/src/wc/components/Select/index.ts +1 -0
  170. package/src/wc/components/ShellGradientSwatch/ShellGradientSwatch.tsx +4 -3
  171. package/src/wc/components/Slider/Slider.tsx +7 -3
  172. package/src/wc/components/TabGroup/TabGroup.tsx +13 -7
  173. package/src/wc/components/TabGroup/tab-item-utils.ts +2 -1
  174. package/src/wc/components/TabGroupNav/TabGroupNav.tsx +14 -13
  175. package/src/wc/components/Tag/Tag.tsx +25 -24
  176. package/src/wc/components/Tag/index.ts +1 -1
  177. package/src/wc/components/Toggle/Toggle.tsx +6 -6
  178. package/src/wc/components/Tooltip/Tooltip.tsx +166 -64
  179. package/src/wc/components/TooltipDataViz/TooltipDataViz.tsx +57 -2
  180. package/src/wc/components.d.ts +474 -579
  181. package/src/wc/utils/control-density.css +42 -0
  182. package/src/wc/utils/control-inactive.css +20 -0
  183. package/src/wc/utils/control-width.css +28 -0
  184. package/src/wc/utils/control-width.ts +10 -0
  185. package/src/wc/utils/index.ts +2 -0
  186. package/src/wc/utils/interaction-fill.css +162 -0
  187. package/src/wc/utils/scroll-edge-fade.css +5 -0
  188. package/src/wc/utils/token-defaults.ts +10 -0
  189. package/dist/components/ds-accordion.js +0 -2
  190. package/dist/components/ds-accordion.js.map +0 -1
  191. package/dist/components/ds-breadcrumb.d.ts +0 -11
  192. package/dist/components/ds-breadcrumb.js +0 -2
  193. package/dist/components/ds-breadcrumb.js.map +0 -1
  194. package/dist/components/ds-button-unfilled-icon.d.ts +0 -11
  195. package/dist/components/ds-button-unfilled-icon.js +0 -2
  196. package/dist/components/ds-card-data-viz.js +0 -2
  197. package/dist/components/ds-card-data-viz.js.map +0 -1
  198. package/dist/components/ds-fade.js +0 -2
  199. package/dist/components/ds-fade.js.map +0 -1
  200. package/dist/components/ds-header.d.ts +0 -11
  201. package/dist/components/ds-header.js +0 -2
  202. package/dist/components/ds-header.js.map +0 -1
  203. package/dist/components/ds-scrollbar.d.ts +0 -11
  204. package/dist/components/ds-scrollbar.js +0 -2
  205. package/dist/components/ds-scrollbar.js.map +0 -1
  206. package/dist/components/ds-surface.d.ts +0 -11
  207. package/dist/components/ds-surface.js +0 -2
  208. package/dist/components/ds-surface.js.map +0 -1
  209. package/dist/components/ds-toast-provider.d.ts +0 -11
  210. package/dist/components/ds-toast-provider.js +0 -2
  211. package/dist/components/ds-toast-provider.js.map +0 -1
  212. package/dist/components/p-BMQbEIrQ.js +0 -2
  213. package/dist/components/p-BMQbEIrQ.js.map +0 -1
  214. package/dist/components/p-BSFgy5r6.js +0 -2
  215. package/dist/components/p-BSFgy5r6.js.map +0 -1
  216. package/dist/components/p-CBUIn8dk.js +0 -2
  217. package/dist/components/p-CBUIn8dk.js.map +0 -1
  218. package/dist/components/p-ChVwCVHy.js +0 -2
  219. package/dist/components/p-ChVwCVHy.js.map +0 -1
  220. package/dist/components/p-CpNIQXz6.js +0 -2
  221. package/dist/components/p-CpNIQXz6.js.map +0 -1
  222. package/dist/components/p-CvgHQfvT.js +0 -2
  223. package/dist/components/p-CvgHQfvT.js.map +0 -1
  224. package/dist/components/p-bDf6yBQd.js +0 -2
  225. package/dist/components/p-bDf6yBQd.js.map +0 -1
  226. package/dist/types/components/Accordion/Accordion.d.ts +0 -28
  227. package/dist/types/components/Breadcrumb/Breadcrumb.d.ts +0 -16
  228. package/dist/types/components/ButtonUnfilledIcon/ButtonUnfilledIcon.d.ts +0 -45
  229. package/dist/types/components/ButtonUnfilledIcon/index.d.ts +0 -2
  230. package/dist/types/components/CardDataViz/CardDataViz.d.ts +0 -22
  231. package/dist/types/components/CardDataViz/index.d.ts +0 -2
  232. package/dist/types/components/Fade/Fade.d.ts +0 -22
  233. package/dist/types/components/Fade/index.d.ts +0 -2
  234. package/dist/types/components/Header/Header.d.ts +0 -7
  235. package/dist/types/components/Scrollbar/Scrollbar.d.ts +0 -27
  236. package/dist/types/components/Surface/Surface.d.ts +0 -22
  237. package/dist/types/components/Toast/Toast.d.ts +0 -16
  238. package/dist/types/components/Toast/toast-service.d.ts +0 -24
  239. package/src/react/ds-accordion.ts +0 -27
  240. package/src/react/ds-breadcrumb.ts +0 -27
  241. package/src/react/ds-button-unfilled-icon.ts +0 -33
  242. package/src/react/ds-card-data-viz.ts +0 -26
  243. package/src/react/ds-header.ts +0 -26
  244. package/src/react/ds-scrollbar.ts +0 -26
  245. package/src/react/ds-surface.ts +0 -26
  246. package/src/react/ds-toast-provider.ts +0 -26
  247. package/src/wc/components/Accordion/Accordion.tsx +0 -144
  248. package/src/wc/components/Breadcrumb/Breadcrumb.tsx +0 -61
  249. package/src/wc/components/ButtonUnfilledIcon/ButtonUnfilledIcon.tsx +0 -129
  250. package/src/wc/components/ButtonUnfilledIcon/index.ts +0 -1
  251. package/src/wc/components/CardDataViz/index.ts +0 -1
  252. package/src/wc/components/Fade/Fade.tsx +0 -58
  253. package/src/wc/components/Fade/index.ts +0 -1
  254. package/src/wc/components/Header/Header.tsx +0 -33
  255. package/src/wc/components/Scrollbar/Scrollbar.tsx +0 -189
  256. package/src/wc/components/Surface/Surface.tsx +0 -81
  257. package/src/wc/components/Toast/Toast.tsx +0 -179
  258. package/src/wc/components/Toast/toast-service.ts +0 -67
  259. /package/dist/components/{ds-button-unfilled-icon.js.map → ds-button-unfilled.js.map} +0 -0
  260. /package/dist/components/{p-8Nt92j1-.js.map → p-B82KZX9D.js.map} +0 -0
  261. /package/dist/components/{p-DdFUTZ3y.js.map → p-Be3PHv34.js.map} +0 -0
  262. /package/dist/components/{p-DOU4cbpc.js.map → p-CtwNUCnp.js.map} +0 -0
@@ -12,15 +12,15 @@ import { createComponent } from '@stencil/react-output-target/runtime';
12
12
  import React from 'react';
13
13
 
14
14
  import type { Components } from "@ds-mo/ui/dist/components";
15
- import { DsFade as DsFadeElement, defineCustomElement as defineDsFade } from "@ds-mo/ui/dist/components/ds-fade.js";
15
+ import { DsCard as DsCardElement, defineCustomElement as defineDsCard } from "@ds-mo/ui/dist/components/ds-card.js";
16
16
 
17
- export type DsFadeEvents = NonNullable<unknown>;
17
+ export type DsCardEvents = NonNullable<unknown>;
18
18
 
19
- export const DsFade: StencilReactComponent<DsFadeElement, DsFadeEvents, Components.DsFade> = /*@__PURE__*/ createComponent<DsFadeElement, DsFadeEvents, Components.DsFade>({
20
- tagName: 'ds-fade',
21
- elementClass: DsFadeElement,
19
+ export const DsCard: StencilReactComponent<DsCardElement, DsCardEvents, Components.DsCard> = /*@__PURE__*/ createComponent<DsCardElement, DsCardEvents, Components.DsCard>({
20
+ tagName: 'ds-card',
21
+ elementClass: DsCardElement,
22
22
  // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
23
23
  react: React,
24
- events: {} as DsFadeEvents,
25
- defineCustomElement: defineDsFade
24
+ events: {} as DsCardEvents,
25
+ defineCustomElement: defineDsCard
26
26
  });
@@ -15,21 +15,13 @@ import { type DsChipCustomEvent } from "@ds-mo/ui";
15
15
  import type { Components } from "@ds-mo/ui/dist/components";
16
16
  import { DsChip as DsChipElement, defineCustomElement as defineDsChip } from "@ds-mo/ui/dist/components/ds-chip.js";
17
17
 
18
- export type DsChipEvents = {
19
- onDsRemove: EventName<DsChipCustomEvent<void>>,
20
- onDsClick: EventName<DsChipCustomEvent<void>>,
21
- onDsPressedChange: EventName<DsChipCustomEvent<boolean>>
22
- };
18
+ export type DsChipEvents = { onDsRemove: EventName<DsChipCustomEvent<void>> };
23
19
 
24
20
  export const DsChip: StencilReactComponent<DsChipElement, DsChipEvents, Components.DsChip> = /*@__PURE__*/ createComponent<DsChipElement, DsChipEvents, Components.DsChip>({
25
21
  tagName: 'ds-chip',
26
22
  elementClass: DsChipElement,
27
23
  // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
28
24
  react: React,
29
- events: {
30
- onDsRemove: 'dsRemove',
31
- onDsClick: 'dsClick',
32
- onDsPressedChange: 'dsPressedChange'
33
- } as DsChipEvents,
25
+ events: { onDsRemove: 'dsRemove' } as DsChipEvents,
34
26
  defineCustomElement: defineDsChip
35
27
  });
@@ -687,15 +687,16 @@ export class BarNav {
687
687
  )}
688
688
 
689
689
  {hasTabs && this.hasOverflowTabs && (
690
- <ds-button-unfilled-icon
690
+ <ds-button-unfilled variant="icon"
691
691
  class={{
692
692
  'bar-nav__overflow-trigger': true,
693
693
  }}
694
694
  icon="Ellipses"
695
695
  isActive={this.menuOpen}
696
696
  activeFill={false}
697
+ hasBorder={false}
697
698
  focusTabIndex={this.overflowRovingFocused ? 0 : -1}
698
- ref={(el?: HTMLDsButtonUnfilledIconElement) => {
699
+ ref={(el?: HTMLDsButtonUnfilledElement) => {
699
700
  this.triggerEl = (el as (HTMLElement & { setFocus?: () => Promise<void> })) ?? null;
700
701
  }}
701
702
  haspopup="menu"
@@ -24,7 +24,7 @@ export function tabsToMenuSections(tabs: TabItem[], selectedId: string): MenuSec
24
24
  label: item.label,
25
25
  value: item.id,
26
26
  isSelected: item.id === selectedId,
27
- isInactive: item.disabled,
27
+ isInactive: item.isInactive,
28
28
  });
29
29
  }
30
30
 
@@ -1,4 +1,5 @@
1
1
  import { Component, Element, Event, EventEmitter, h, Host, Method, Prop } from '@stencil/core';
2
+ import { controlWidthClass, type ControlWidth } from '../../utils/control-width';
2
3
 
3
4
  export type ButtonFilledIntent =
4
5
  | 'neutral'
@@ -13,6 +14,29 @@ export type ButtonFilledIntent =
13
14
 
14
15
  export type ButtonFilledContrast = 'bold' | 'strong' | 'medium' | 'faint';
15
16
 
17
+ export type ButtonFilledVariant = 'icon' | 'label' | 'icon-label';
18
+
19
+ export type ButtonFilledSize = 'md' | 'sm' | 'xs';
20
+
21
+ export type ButtonFilledWidth = ControlWidth;
22
+
23
+ /** Emphasis text per control-density size (buttons use emphasis, unlike Tag). */
24
+ const TEXT_VARIANT: Record<ButtonFilledSize, string> = {
25
+ md: 'text-body-medium-emphasis',
26
+ sm: 'text-body-small-emphasis',
27
+ xs: 'text-caption-emphasis',
28
+ };
29
+
30
+ /**
31
+ * `ds-icon` size prop matching control-density icon metrics
32
+ * (md→20 / sm→16 / xs→12 via `--dimension-iconography-*`).
33
+ */
34
+ const ICON_SIZE: Record<ButtonFilledSize, 'md' | 'sm' | 'xs'> = {
35
+ md: 'md',
36
+ sm: 'sm',
37
+ xs: 'xs',
38
+ };
39
+
16
40
  @Component({
17
41
  tag: 'ds-button-filled',
18
42
  styleUrl: 'ButtonFilled.css',
@@ -21,7 +45,22 @@ export type ButtonFilledContrast = 'bold' | 'strong' | 'medium' | 'faint';
21
45
  export class ButtonFilled {
22
46
  @Element() el!: HTMLElement;
23
47
 
24
- /** Icon name passed to <ds-icon>. */
48
+ /**
49
+ * Content layout. Default is label-only; pass `icon` for icon-only chrome
50
+ * (nav / tool rails) or `icon-label` for leading icon + text.
51
+ */
52
+ @Prop() variant: ButtonFilledVariant = 'label';
53
+
54
+ /** Control density (height, padding, icon, type). */
55
+ @Prop() size: ButtonFilledSize = 'md';
56
+
57
+ /** Width fit — hug content (default) or fill the parent. */
58
+ @Prop() width: ButtonFilledWidth = 'hug';
59
+
60
+ /** Visible text for `label` / `icon-label` variants. */
61
+ @Prop() label: string = '';
62
+
63
+ /** Icon name passed to <ds-icon> for `icon` / `icon-label` variants. */
25
64
  @Prop() icon: string = '';
26
65
 
27
66
  /** Semantic colour intent. */
@@ -34,12 +73,12 @@ export class ButtonFilled {
34
73
  @Prop() contrast: ButtonFilledContrast = 'bold';
35
74
 
36
75
  /** Disables interaction. */
37
- @Prop() inactive: boolean = false;
76
+ @Prop() isInactive: boolean = false;
38
77
 
39
78
  /** Native button type. */
40
79
  @Prop() type: 'button' | 'submit' | 'reset' = 'button';
41
80
 
42
- @Prop({ attribute: 'aria-label' }) ariaLabel: string = 'action';
81
+ @Prop({ attribute: 'aria-label' }) ariaLabel: string | undefined;
43
82
 
44
83
  @Event() dsClick!: EventEmitter<MouseEvent>;
45
84
 
@@ -51,34 +90,81 @@ export class ButtonFilled {
51
90
  }
52
91
 
53
92
  private handleClick = (event: MouseEvent) => {
54
- if (this.inactive) return;
93
+ if (this.isInactive) return;
55
94
  this.dsClick.emit(event);
56
95
  };
57
96
 
97
+ private get showIcon(): boolean {
98
+ return this.variant === 'icon' || this.variant === 'icon-label';
99
+ }
100
+
101
+ private get showLabel(): boolean {
102
+ return this.variant === 'label' || this.variant === 'icon-label';
103
+ }
104
+
105
+ private get accessibleName(): string | undefined {
106
+ if (this.ariaLabel) return this.ariaLabel;
107
+ if (this.showLabel && this.label) return undefined;
108
+ if (this.variant === 'icon') return this.icon || 'action';
109
+ return this.label || 'action';
110
+ }
111
+
58
112
  render() {
113
+ const textVariant = TEXT_VARIANT[this.size];
114
+ const iconSize = ICON_SIZE[this.size];
115
+
59
116
  const cls: Record<string, boolean> = {
60
117
  'button-filled': true,
61
118
  'ds-focus-ring-inset': true,
62
- 'button-filled--inactive': this.inactive,
119
+ 'ds-interaction-fill': !this.isInactive,
120
+ /* Bold is the default filled contrast — on-bold interaction tokens. */
121
+ 'ds-interaction-fill--on-bold': this.contrast === 'bold',
122
+ 'ds-interaction-fill--on-strong': this.contrast === 'strong',
123
+ 'ds-interaction-fill--on-medium': this.contrast === 'medium',
124
+ /* faint → default app interaction tokens (no --on-*). */
125
+ 'ds-control-inactive': this.isInactive,
126
+ 'ds-control--md': this.size === 'md',
127
+ 'ds-control--sm': this.size === 'sm',
128
+ 'ds-control--xs': this.size === 'xs',
129
+ 'button-filled--icon': this.variant === 'icon',
130
+ 'button-filled--label': this.variant === 'label',
131
+ 'button-filled--icon-label': this.variant === 'icon-label',
63
132
  [`button-filled--intent-${this.intent}`]: true,
64
133
  [`button-filled--contrast-${this.contrast}`]: this.contrast !== 'bold',
65
134
  };
66
135
 
67
136
  return (
68
- <Host tabIndex={-1}>
137
+ <Host
138
+ class={{
139
+ 'button-filled-host': true,
140
+ 'button-filled-host--icon': this.variant === 'icon',
141
+ 'ds-control--md': this.size === 'md',
142
+ 'ds-control--sm': this.size === 'sm',
143
+ 'ds-control--xs': this.size === 'xs',
144
+ ...controlWidthClass(this.width),
145
+ }}
146
+ tabIndex={-1}
147
+ >
69
148
  <button
70
149
  ref={el => {
71
150
  this.buttonEl = el ?? null;
72
151
  }}
73
152
  type={this.type}
74
153
  class={cls}
75
- disabled={this.inactive}
76
- aria-label={this.ariaLabel}
154
+ disabled={this.isInactive}
155
+ aria-label={this.accessibleName}
77
156
  onClick={this.handleClick}
78
157
  >
79
- <span class="button-filled__icon-wrap">
80
- <ds-icon name={this.icon} size="md" color="inherit" />
81
- </span>
158
+ {this.showIcon && (
159
+ <span class="button-filled__icon-wrap ds-interaction-fill__content">
160
+ <ds-icon name={this.icon} size={iconSize} color="inherit" />
161
+ </span>
162
+ )}
163
+ {this.showLabel && (
164
+ <span class={{ 'button-filled__label': true, [textVariant]: true, 'ds-interaction-fill__content': true }}>
165
+ {this.label}
166
+ </span>
167
+ )}
82
168
  </button>
83
169
  </Host>
84
170
  );
@@ -1 +1,7 @@
1
- export type { ButtonFilledContrast, ButtonFilledIntent } from './ButtonFilled';
1
+ export type {
2
+ ButtonFilledContrast,
3
+ ButtonFilledIntent,
4
+ ButtonFilledSize,
5
+ ButtonFilledVariant,
6
+ ButtonFilledWidth,
7
+ } from './ButtonFilled';
@@ -0,0 +1,230 @@
1
+ import { Component, Element, Event, EventEmitter, h, Host, Method, Prop } from '@stencil/core';
2
+ import { controlWidthClass, type ControlWidth } from '../../utils/control-width';
3
+
4
+ export type ButtonUnfilledOnBackgroundContrast = 'default' | 'medium' | 'bold' | 'strong';
5
+
6
+ export type ButtonUnfilledBackground = 'always-dark' | 'navigation';
7
+
8
+ export type ButtonUnfilledVariant = 'icon' | 'label' | 'icon-label';
9
+
10
+ export type ButtonUnfilledSize = 'md' | 'sm' | 'xs';
11
+
12
+ export type ButtonUnfilledWidth = ControlWidth;
13
+
14
+ /** Emphasis text per control-density size (buttons use emphasis, unlike Tag). */
15
+ const TEXT_VARIANT: Record<ButtonUnfilledSize, string> = {
16
+ md: 'text-body-medium-emphasis',
17
+ sm: 'text-body-small-emphasis',
18
+ xs: 'text-caption-emphasis',
19
+ };
20
+
21
+ /**
22
+ * `ds-icon` size prop matching control-density icon metrics
23
+ * (md→20 / sm→16 / xs→12 via `--dimension-iconography-*`).
24
+ */
25
+ const ICON_SIZE: Record<ButtonUnfilledSize, 'md' | 'sm' | 'xs'> = {
26
+ md: 'md',
27
+ sm: 'sm',
28
+ xs: 'xs',
29
+ };
30
+
31
+ @Component({
32
+ tag: 'ds-button-unfilled',
33
+ styleUrl: 'ButtonUnfilled.css',
34
+ scoped: true,
35
+ })
36
+ export class ButtonUnfilled {
37
+ @Element() el!: HTMLElement;
38
+
39
+ /**
40
+ * Content layout. Default is label-only; pass `icon` for icon-only chrome
41
+ * (nav / tool rails) or `icon-label` for leading icon + text.
42
+ */
43
+ @Prop() variant: ButtonUnfilledVariant = 'label';
44
+
45
+ /** Control density (height, padding, icon, type). */
46
+ @Prop() size: ButtonUnfilledSize = 'md';
47
+
48
+ /** Width fit — hug content (default) or fill the parent. */
49
+ @Prop() width: ButtonUnfilledWidth = 'hug';
50
+
51
+ /** Visible text for `label` / `icon-label` variants. */
52
+ @Prop() label: string = '';
53
+
54
+ /** Icon name passed to <ds-icon> for `icon` / `icon-label` variants. */
55
+ @Prop() icon: string = '';
56
+
57
+ /** Active/selected visual state. Always promotes foreground to primary. */
58
+ @Prop() isActive: boolean = false;
59
+
60
+ /**
61
+ * When active, render the selected interaction fill.
62
+ * Default `true` for general UI. Shell chrome (nav / tool rails) should pass
63
+ * `false` so selection is foreground-only (primary color, no fill).
64
+ */
65
+ @Prop() activeFill: boolean = true;
66
+
67
+ /** Show a 1px secondary inset border. Default on; shell chrome can pass `false`. */
68
+ @Prop() hasBorder: boolean = true;
69
+
70
+ /** Show a notification dot at the top-right of the icon zone (icon variant only). */
71
+ @Prop() dot: boolean = false;
72
+
73
+ /** Disables interaction. */
74
+ @Prop() isInactive: boolean = false;
75
+
76
+ /** Native button type. */
77
+ @Prop() type: 'button' | 'submit' | 'reset' = 'button';
78
+
79
+ /**
80
+ * Foreground and interaction tokens when the button sits on a contrasting parent
81
+ * background (default, medium, bold, or strong).
82
+ */
83
+ @Prop({ attribute: 'on-background-contrast' })
84
+ backgroundContrast?: ButtonUnfilledOnBackgroundContrast;
85
+
86
+ /** Parent surface context for navigation and always-dark chrome. */
87
+ @Prop() background: ButtonUnfilledBackground | undefined;
88
+
89
+ @Prop({ attribute: 'aria-label' }) ariaLabel: string | undefined;
90
+ @Prop() controls: string | undefined;
91
+ @Prop() expanded: boolean | undefined;
92
+ @Prop() haspopup: string | undefined;
93
+ @Prop() pressed: boolean | undefined;
94
+
95
+ /**
96
+ * Native `tabindex` for roving keyboard groups in shell chrome.
97
+ * Omit for the default button tab stop (`0`).
98
+ */
99
+ @Prop({ attribute: 'tab-index' }) focusTabIndex?: number;
100
+
101
+ @Event() dsClick!: EventEmitter<MouseEvent>;
102
+ @Event() dsChange!: EventEmitter<boolean>;
103
+
104
+ private buttonEl: HTMLButtonElement | null = null;
105
+
106
+ @Method()
107
+ async setFocus() {
108
+ this.buttonEl?.focus();
109
+ }
110
+
111
+ private handleClick = (event: MouseEvent) => {
112
+ if (this.isInactive) return;
113
+ this.dsClick.emit(event);
114
+ this.dsChange.emit(!this.isActive);
115
+ };
116
+
117
+ private effectiveContrast(): ButtonUnfilledOnBackgroundContrast {
118
+ return this.backgroundContrast ?? 'default';
119
+ }
120
+
121
+ private get showIcon(): boolean {
122
+ return this.variant === 'icon' || this.variant === 'icon-label';
123
+ }
124
+
125
+ private get showLabel(): boolean {
126
+ return this.variant === 'label' || this.variant === 'icon-label';
127
+ }
128
+
129
+ private get showDot(): boolean {
130
+ return this.variant === 'icon' && this.dot;
131
+ }
132
+
133
+ /** Knock-out ring: selected fill → active wash; otherwise surface token. */
134
+ private get dotRing(): string {
135
+ if (this.isActive && this.activeFill) {
136
+ return 'var(--ds-interaction-active)';
137
+ }
138
+ return 'var(--ds-button-unfilled-dot-ring)';
139
+ }
140
+
141
+ private get accessibleName(): string | undefined {
142
+ if (this.ariaLabel) return this.ariaLabel;
143
+ if (this.showLabel && this.label) return undefined;
144
+ if (this.variant === 'icon') return this.icon || 'action';
145
+ return this.label || 'action';
146
+ }
147
+
148
+ render() {
149
+ const bg = this.background;
150
+ const contrast = this.effectiveContrast();
151
+ const textVariant = TEXT_VARIANT[this.size];
152
+ const iconSize = ICON_SIZE[this.size];
153
+
154
+ const cls: Record<string, boolean> = {
155
+ 'button-unfilled': true,
156
+ 'ds-focus-ring-inset': true,
157
+ 'ds-interaction-fill': true,
158
+ 'ds-interaction-fill--selected': this.isActive && this.activeFill && !this.isInactive,
159
+ 'ds-interaction-fill--on-medium': contrast === 'medium',
160
+ 'ds-interaction-fill--on-bold': contrast === 'bold',
161
+ 'ds-interaction-fill--on-strong': contrast === 'strong',
162
+ 'ds-interaction-fill--on-always-dark': bg === 'always-dark',
163
+ 'ds-interaction-fill--on-navigation': bg === 'navigation',
164
+ 'button-unfilled--active': this.isActive,
165
+ 'button-unfilled--bordered': this.hasBorder,
166
+ 'ds-control-inactive': this.isInactive,
167
+ 'ds-control--md': this.size === 'md',
168
+ 'ds-control--sm': this.size === 'sm',
169
+ 'ds-control--xs': this.size === 'xs',
170
+ 'button-unfilled--icon': this.variant === 'icon',
171
+ 'button-unfilled--label': this.variant === 'label',
172
+ 'button-unfilled--icon-label': this.variant === 'icon-label',
173
+ 'button-unfilled--contrast-medium': contrast === 'medium',
174
+ 'button-unfilled--contrast-bold': contrast === 'bold',
175
+ 'button-unfilled--contrast-strong': contrast === 'strong',
176
+ 'button-unfilled--on-always-dark': bg === 'always-dark',
177
+ 'button-unfilled--on-navigation': bg === 'navigation',
178
+ };
179
+
180
+ return (
181
+ <Host
182
+ class={{
183
+ 'button-unfilled-host': true,
184
+ 'button-unfilled-host--icon': this.variant === 'icon',
185
+ 'ds-control--md': this.size === 'md',
186
+ 'ds-control--sm': this.size === 'sm',
187
+ 'ds-control--xs': this.size === 'xs',
188
+ ...controlWidthClass(this.width),
189
+ }}
190
+ tabIndex={-1}
191
+ >
192
+ <button
193
+ ref={el => {
194
+ this.buttonEl = el ?? null;
195
+ }}
196
+ type={this.type}
197
+ class={cls}
198
+ disabled={this.isInactive}
199
+ tabIndex={this.focusTabIndex ?? 0}
200
+ aria-label={this.accessibleName}
201
+ aria-controls={this.controls}
202
+ aria-expanded={this.expanded === undefined ? undefined : String(this.expanded)}
203
+ aria-haspopup={this.haspopup}
204
+ aria-pressed={this.pressed === undefined ? undefined : String(this.pressed)}
205
+ onClick={this.handleClick}
206
+ >
207
+ {this.showIcon && (
208
+ <span class="button-unfilled__icon-wrap ds-interaction-fill__content">
209
+ <ds-icon name={this.icon} size={iconSize} color="inherit" />
210
+ {this.showDot && (
211
+ <ds-badge
212
+ class="button-unfilled__dot"
213
+ variant="dot"
214
+ background={this.dotRing}
215
+ label=""
216
+ aria-hidden="true"
217
+ />
218
+ )}
219
+ </span>
220
+ )}
221
+ {this.showLabel && (
222
+ <span class={{ 'button-unfilled__label': true, [textVariant]: true, 'ds-interaction-fill__content': true }}>
223
+ {this.label}
224
+ </span>
225
+ )}
226
+ </button>
227
+ </Host>
228
+ );
229
+ }
230
+ }
@@ -0,0 +1,7 @@
1
+ export type {
2
+ ButtonUnfilledBackground,
3
+ ButtonUnfilledOnBackgroundContrast,
4
+ ButtonUnfilledSize,
5
+ ButtonUnfilledVariant,
6
+ ButtonUnfilledWidth,
7
+ } from './ButtonUnfilled';
@@ -0,0 +1,79 @@
1
+ import { Component, h, Host, Prop } from '@stencil/core';
2
+
3
+ export type CardWidth = 'sm' | 'md' | 'lg';
4
+
5
+ /** Visual chrome recipe — default app surface, or settings edit wash. */
6
+ export type CardAppearance = 'default' | 'editing';
7
+
8
+ const CARD_WIDTH_VARS: Record<CardWidth, string> = {
9
+ sm: 'var(--dimension-card-width-sm)',
10
+ md: 'var(--dimension-card-width-md)',
11
+ lg: 'var(--dimension-card-width-lg)',
12
+ };
13
+
14
+ const CARD_HEIGHT_VARS: Record<CardWidth, string> = {
15
+ sm: 'var(--dimension-card-height-sm)',
16
+ md: 'var(--dimension-card-height-md)',
17
+ lg: 'var(--dimension-card-height-lg)',
18
+ };
19
+
20
+ const FAINT_BRAND_TITLE_COLOR = 'var(--color-foreground-faint-brand)';
21
+
22
+ /**
23
+ * Shared card chrome — width + matching min-height tokens, header (title + actions),
24
+ * and a flex body that fills leftover space. Compose this from settings / data-viz cards.
25
+ */
26
+ @Component({
27
+ tag: 'ds-card',
28
+ styleUrl: 'Card.css',
29
+ scoped: true,
30
+ })
31
+ export class Card {
32
+ /** Section heading shown in the card header. */
33
+ @Prop() heading!: string;
34
+
35
+ /**
36
+ * Card width token (`sm` / `md` / `lg`). Also sets host `min-height` to the
37
+ * matching `--dimension-card-height-*` so empty bodies still fill the card.
38
+ */
39
+ @Prop() cardWidth: CardWidth = 'md';
40
+
41
+ /** Chrome recipe — `editing` applies the settings edit wash. */
42
+ @Prop() appearance: CardAppearance = 'default';
43
+
44
+ render() {
45
+ const editing = this.appearance === 'editing';
46
+
47
+ return (
48
+ <Host
49
+ class={{
50
+ card: true,
51
+ 'card--editing': editing,
52
+ }}
53
+ style={{
54
+ '--_card-width': CARD_WIDTH_VARS[this.cardWidth],
55
+ '--_card-min-height': CARD_HEIGHT_VARS[this.cardWidth],
56
+ }}
57
+ >
58
+ <header class="card__header">
59
+ <div class="card__title-wrap">
60
+ <ds-text
61
+ class="card__title"
62
+ variant="text-title-small"
63
+ color={editing ? FAINT_BRAND_TITLE_COLOR : 'primary'}
64
+ as="h2"
65
+ >
66
+ {this.heading}
67
+ </ds-text>
68
+ </div>
69
+ <div class="card__actions">
70
+ <slot name="actions" />
71
+ </div>
72
+ </header>
73
+ <div class="card__body">
74
+ <slot />
75
+ </div>
76
+ </Host>
77
+ );
78
+ }
79
+ }
@@ -0,0 +1 @@
1
+ export type { CardWidth, CardAppearance } from './Card';