@ds-mo/ui 14.6.0 → 14.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/dist/.package-ready.json +1 -1
  2. package/dist/agent-patterns.json +6 -6
  3. package/dist/agent.json +49 -19
  4. package/dist/angular/ds-menu.d.ts +7 -1
  5. package/dist/angular/ds-menu.js +5 -2
  6. package/dist/angular/ds-table.d.ts +4 -1
  7. package/dist/angular/ds-table.js +7 -4
  8. package/dist/components/ds-agent-questionnaire.js +1 -1
  9. package/dist/components/ds-agent-response.js +1 -1
  10. package/dist/components/ds-banner.js +1 -1
  11. package/dist/components/ds-bar-nav.js +1 -1
  12. package/dist/components/ds-bar-title.js +1 -1
  13. package/dist/components/ds-bar-workflow.js +1 -1
  14. package/dist/components/ds-bar-workflow.js.map +1 -1
  15. package/dist/components/ds-button-unfilled.js +1 -1
  16. package/dist/components/ds-card-chart.js +1 -1
  17. package/dist/components/ds-card-setting.js +1 -1
  18. package/dist/components/ds-code-block.js +1 -1
  19. package/dist/components/ds-conversation-list-item.js +1 -1
  20. package/dist/components/ds-conversation-list-item.js.map +1 -1
  21. package/dist/components/ds-filter-menu.js +1 -1
  22. package/dist/components/ds-filter-menu.js.map +1 -1
  23. package/dist/components/ds-input.js +1 -1
  24. package/dist/components/ds-markdown.js +1 -1
  25. package/dist/components/ds-menu.js +1 -1
  26. package/dist/components/ds-message-actions.js +1 -1
  27. package/dist/components/ds-message-composer.js +1 -1
  28. package/dist/components/ds-message-scroller.js +1 -1
  29. package/dist/components/ds-mobile-header.js +1 -1
  30. package/dist/components/ds-mobile-section-switcher.js +1 -1
  31. package/dist/components/ds-mobile-sheet-nav.js +1 -1
  32. package/dist/components/ds-modal.js +1 -1
  33. package/dist/components/ds-pagination.js +1 -1
  34. package/dist/components/ds-panel-nav.js +1 -1
  35. package/dist/components/ds-panel-tool-header.js +1 -1
  36. package/dist/components/ds-panel-tool-search.js +1 -1
  37. package/dist/components/ds-panel-tools.js +1 -1
  38. package/dist/components/ds-select.js +1 -1
  39. package/dist/components/ds-shell-app.js +1 -1
  40. package/dist/components/ds-shell-tools.js +1 -1
  41. package/dist/components/ds-table.js +1 -1
  42. package/dist/components/ds-table.js.map +1 -1
  43. package/dist/components/ds-toast.js +1 -1
  44. package/dist/components/{p-BGQUiJuJ.js → p--VFa9x3k.js} +2 -2
  45. package/dist/components/{p-C7-ylLcB.js → p-B5um-ps9.js} +2 -2
  46. package/dist/components/{p-K_vg9Eng.js → p-BAebDW3a.js} +2 -2
  47. package/dist/components/p-BKWgofxz.js +2 -0
  48. package/dist/components/p-BKWgofxz.js.map +1 -0
  49. package/dist/components/{p-DL12lNtv.js → p-BmqfTAXM.js} +2 -2
  50. package/dist/components/{p-CDEME0Uc.js → p-C-L4InQ0.js} +2 -2
  51. package/dist/components/{p-BykcjUd6.js → p-C1jsgfeh.js} +2 -2
  52. package/dist/components/{p-BFDKKBYh.js → p-CoQSB3tl.js} +2 -2
  53. package/dist/components/{p-DJ-n-gyr.js → p-CvwtYbmh.js} +2 -2
  54. package/dist/components/{p-os90t2-f.js → p-D5VglrfF.js} +2 -2
  55. package/dist/components/{p-BX-R5EhL.js → p-D5bPuNiF.js} +2 -2
  56. package/dist/components/{p-CCpJcSTE.js → p-DOC4RaAy.js} +2 -2
  57. package/dist/components/{p-C5230yJY.js → p-DQUxg6Si.js} +2 -2
  58. package/dist/components/{p-DTf90AyI.js → p-bQm3gfr1.js} +2 -2
  59. package/dist/components/{p-CTTDiW33.js → p-c_5SXjwx.js} +2 -2
  60. package/dist/components/p-c_5SXjwx.js.map +1 -0
  61. package/dist/components/p-mLRtp5A4.js +2 -0
  62. package/dist/components/{p-3r4TfcZX.js.map → p-mLRtp5A4.js.map} +1 -1
  63. package/dist/docs/components.json +154 -3
  64. package/dist/mcp-data/registry/button-unfilled.json +6 -6
  65. package/dist/mcp-data/registry/menu.json +40 -12
  66. package/dist/mcp-data/registry/registry.json +48 -18
  67. package/dist/mcp-data/registry/table.json +81 -9
  68. package/dist/react/ds-menu.d.ts +2 -1
  69. package/dist/react/ds-menu.js +2 -1
  70. package/dist/react/ds-table.d.ts +2 -1
  71. package/dist/react/ds-table.js +2 -1
  72. package/dist/styles/table.css +22 -1
  73. package/dist/types/components/ButtonUnfilled/ButtonUnfilled.d.ts +4 -2
  74. package/dist/types/components/Menu/Menu.d.ts +18 -1
  75. package/dist/types/components/Menu/menu-reorder.d.ts +21 -0
  76. package/dist/types/components/Menu/menu-types.d.ts +12 -0
  77. package/dist/types/components/Table/Table.d.ts +28 -1
  78. package/dist/types/components/Table/index.d.ts +1 -1
  79. package/dist/types/components/Table/table-column-customizer.d.ts +33 -0
  80. package/dist/types/components/Table/table-types.d.ts +5 -0
  81. package/dist/types/components.d.ts +44 -6
  82. package/package.json +1 -1
  83. package/dist/components/p-3r4TfcZX.js +0 -2
  84. package/dist/components/p-CRi7P5gQ.js +0 -2
  85. package/dist/components/p-CRi7P5gQ.js.map +0 -1
  86. package/dist/components/p-CTTDiW33.js.map +0 -1
  87. /package/dist/components/{p-BGQUiJuJ.js.map → p--VFa9x3k.js.map} +0 -0
  88. /package/dist/components/{p-C7-ylLcB.js.map → p-B5um-ps9.js.map} +0 -0
  89. /package/dist/components/{p-K_vg9Eng.js.map → p-BAebDW3a.js.map} +0 -0
  90. /package/dist/components/{p-DL12lNtv.js.map → p-BmqfTAXM.js.map} +0 -0
  91. /package/dist/components/{p-CDEME0Uc.js.map → p-C-L4InQ0.js.map} +0 -0
  92. /package/dist/components/{p-BykcjUd6.js.map → p-C1jsgfeh.js.map} +0 -0
  93. /package/dist/components/{p-BFDKKBYh.js.map → p-CoQSB3tl.js.map} +0 -0
  94. /package/dist/components/{p-DJ-n-gyr.js.map → p-CvwtYbmh.js.map} +0 -0
  95. /package/dist/components/{p-os90t2-f.js.map → p-D5VglrfF.js.map} +0 -0
  96. /package/dist/components/{p-BX-R5EhL.js.map → p-D5bPuNiF.js.map} +0 -0
  97. /package/dist/components/{p-CCpJcSTE.js.map → p-DOC4RaAy.js.map} +0 -0
  98. /package/dist/components/{p-C5230yJY.js.map → p-DQUxg6Si.js.map} +0 -0
  99. /package/dist/components/{p-DTf90AyI.js.map → p-bQm3gfr1.js.map} +0 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "timestamp": "2026-08-20T20:20:24",
2
+ "timestamp": "2026-08-20T23:50:18",
3
3
  "compiler": {
4
4
  "name": "@stencil/core",
5
5
  "version": "4.43.5",
@@ -2896,6 +2896,7 @@
2896
2896
  "ds-menu": [
2897
2897
  "ds-text",
2898
2898
  "ds-swatch-picker",
2899
+ "ds-icon",
2899
2900
  "ds-tag",
2900
2901
  "ds-badge",
2901
2902
  "ds-switch"
@@ -3538,6 +3539,7 @@
3538
3539
  "ds-menu": [
3539
3540
  "ds-text",
3540
3541
  "ds-swatch-picker",
3542
+ "ds-icon",
3541
3543
  "ds-tag",
3542
3544
  "ds-badge",
3543
3545
  "ds-switch"
@@ -3977,6 +3979,7 @@
3977
3979
  "ds-menu": [
3978
3980
  "ds-text",
3979
3981
  "ds-swatch-picker",
3982
+ "ds-icon",
3980
3983
  "ds-tag",
3981
3984
  "ds-badge",
3982
3985
  "ds-switch"
@@ -5272,7 +5275,7 @@
5272
5275
  "mutable": false,
5273
5276
  "attr": "has-menu",
5274
5277
  "reflectToAttr": false,
5275
- "docs": "Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\nboth menu-button shapes:\n\n- `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n the affordance.\n- `icon` — the button *is* a menu, i.e. the overflow / more-options control.\n No chevron is added, so the glyph must convey it on its own; use `Ellipses`.\n\nUse `haspopup` directly for non-menu popups.",
5278
+ "docs": "Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\nboth menu-button shapes:\n\n- `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n the affordance.\n- `icon` — the button *is* a menu. No chevron is added, so the glyph must\n convey the menu on its own. Use `Ellipses` for generic more-options;\n use a specific icon when the menu has a named purpose, such as\n `Preferences` for Customize table.\n\nUse `haspopup` directly for non-menu popups.",
5276
5279
  "docsTags": [
5277
5280
  {
5278
5281
  "name": "default",
@@ -10540,6 +10543,7 @@
10540
10543
  "ds-empty-state",
10541
10544
  "ds-filter-menu",
10542
10545
  "ds-input",
10546
+ "ds-menu",
10543
10547
  "ds-message-composer",
10544
10548
  "ds-mobile-bar-nav",
10545
10549
  "ds-mobile-sheet-nav",
@@ -10591,6 +10595,9 @@
10591
10595
  "ds-input": [
10592
10596
  "ds-icon"
10593
10597
  ],
10598
+ "ds-menu": [
10599
+ "ds-icon"
10600
+ ],
10594
10601
  "ds-message-composer": [
10595
10602
  "ds-icon"
10596
10603
  ],
@@ -12513,6 +12520,27 @@
12513
12520
  "docs": "",
12514
12521
  "docsTags": []
12515
12522
  },
12523
+ {
12524
+ "event": "dsReorder",
12525
+ "detail": "MenuReorderDetail",
12526
+ "bubbles": true,
12527
+ "complexType": {
12528
+ "original": "MenuReorderDetail",
12529
+ "resolved": "MenuReorderDetail",
12530
+ "references": {
12531
+ "MenuReorderDetail": {
12532
+ "location": "import",
12533
+ "path": "./menu-types",
12534
+ "id": "src/wc/components/Menu/menu-types.ts::MenuReorderDetail",
12535
+ "referenceLocation": "MenuReorderDetail"
12536
+ }
12537
+ }
12538
+ },
12539
+ "cancelable": true,
12540
+ "composed": true,
12541
+ "docs": "Emitted after a pointer drop or keyboard move; Menu never mutates item order.",
12542
+ "docsTags": []
12543
+ },
12516
12544
  {
12517
12545
  "event": "dsSelect",
12518
12546
  "detail": "MenuItemData",
@@ -12569,6 +12597,7 @@
12569
12597
  "dependencies": [
12570
12598
  "ds-text",
12571
12599
  "ds-swatch-picker",
12600
+ "ds-icon",
12572
12601
  "ds-tag",
12573
12602
  "ds-badge",
12574
12603
  "ds-switch"
@@ -12577,6 +12606,7 @@
12577
12606
  "ds-menu": [
12578
12607
  "ds-text",
12579
12608
  "ds-swatch-picker",
12609
+ "ds-icon",
12580
12610
  "ds-tag",
12581
12611
  "ds-badge",
12582
12612
  "ds-switch"
@@ -14863,6 +14893,7 @@
14863
14893
  "ds-menu": [
14864
14894
  "ds-text",
14865
14895
  "ds-swatch-picker",
14896
+ "ds-icon",
14866
14897
  "ds-tag",
14867
14898
  "ds-badge",
14868
14899
  "ds-switch"
@@ -15021,6 +15052,7 @@
15021
15052
  "ds-menu": [
15022
15053
  "ds-text",
15023
15054
  "ds-swatch-picker",
15055
+ "ds-icon",
15024
15056
  "ds-tag",
15025
15057
  "ds-badge",
15026
15058
  "ds-switch"
@@ -21446,6 +21478,7 @@
21446
21478
  "ds-menu": [
21447
21479
  "ds-text",
21448
21480
  "ds-swatch-picker",
21481
+ "ds-icon",
21449
21482
  "ds-tag",
21450
21483
  "ds-badge",
21451
21484
  "ds-switch"
@@ -22528,6 +22561,7 @@
22528
22561
  "ds-menu": [
22529
22562
  "ds-text",
22530
22563
  "ds-swatch-picker",
22564
+ "ds-icon",
22531
22565
  "ds-tag",
22532
22566
  "ds-badge",
22533
22567
  "ds-switch"
@@ -24887,6 +24921,63 @@
24887
24921
  "getter": false,
24888
24922
  "setter": false
24889
24923
  },
24924
+ {
24925
+ "name": "columnCustomizer",
24926
+ "type": "boolean",
24927
+ "complexType": {
24928
+ "original": "boolean",
24929
+ "resolved": "boolean",
24930
+ "references": {}
24931
+ },
24932
+ "mutable": false,
24933
+ "attr": "column-customizer",
24934
+ "reflectToAttr": false,
24935
+ "docs": "Opt in to the table-owned column customizer. The `columns` prop remains the\ncatalog; hidden and ordered columns are controlled separately. The trigger\nopens the shared Menu of live show/hide switch rows.",
24936
+ "docsTags": [
24937
+ {
24938
+ "name": "default",
24939
+ "text": "false"
24940
+ }
24941
+ ],
24942
+ "default": "false",
24943
+ "values": [
24944
+ {
24945
+ "type": "boolean"
24946
+ }
24947
+ ],
24948
+ "optional": false,
24949
+ "required": false,
24950
+ "getter": false,
24951
+ "setter": false
24952
+ },
24953
+ {
24954
+ "name": "columnOrder",
24955
+ "type": "string[]",
24956
+ "complexType": {
24957
+ "original": "string[]",
24958
+ "resolved": "string[]",
24959
+ "references": {}
24960
+ },
24961
+ "mutable": false,
24962
+ "reflectToAttr": false,
24963
+ "docs": "Controlled data-column identities in display order. Omitted ids append in catalog order.",
24964
+ "docsTags": [
24965
+ {
24966
+ "name": "default",
24967
+ "text": "[]"
24968
+ }
24969
+ ],
24970
+ "default": "[]",
24971
+ "values": [
24972
+ {
24973
+ "type": "string[]"
24974
+ }
24975
+ ],
24976
+ "optional": false,
24977
+ "required": false,
24978
+ "getter": false,
24979
+ "setter": false
24980
+ },
24890
24981
  {
24891
24982
  "name": "columns",
24892
24983
  "type": "TableColumn[]",
@@ -25526,6 +25617,34 @@
25526
25617
  "getter": false,
25527
25618
  "setter": false
25528
25619
  },
25620
+ {
25621
+ "name": "hiddenColumnIds",
25622
+ "type": "string[]",
25623
+ "complexType": {
25624
+ "original": "string[]",
25625
+ "resolved": "string[]",
25626
+ "references": {}
25627
+ },
25628
+ "mutable": false,
25629
+ "reflectToAttr": false,
25630
+ "docs": "Controlled hidden data-column identities. Action ids are ignored.",
25631
+ "docsTags": [
25632
+ {
25633
+ "name": "default",
25634
+ "text": "[]"
25635
+ }
25636
+ ],
25637
+ "default": "[]",
25638
+ "values": [
25639
+ {
25640
+ "type": "string[]"
25641
+ }
25642
+ ],
25643
+ "optional": false,
25644
+ "required": false,
25645
+ "getter": false,
25646
+ "setter": false
25647
+ },
25529
25648
  {
25530
25649
  "name": "loadIdentity",
25531
25650
  "type": "number | string",
@@ -26264,6 +26383,27 @@
26264
26383
  "docs": "",
26265
26384
  "docsTags": []
26266
26385
  },
26386
+ {
26387
+ "event": "dsColumnsConfigChange",
26388
+ "detail": "TableColumnsConfigChangeDetail",
26389
+ "bubbles": true,
26390
+ "complexType": {
26391
+ "original": "TableColumnsConfigChangeDetail",
26392
+ "resolved": "TableColumnsConfigChangeDetail",
26393
+ "references": {
26394
+ "TableColumnsConfigChangeDetail": {
26395
+ "location": "import",
26396
+ "path": "./table-types",
26397
+ "id": "src/wc/components/Table/table-types.ts::TableColumnsConfigChangeDetail",
26398
+ "referenceLocation": "TableColumnsConfigChangeDetail"
26399
+ }
26400
+ }
26401
+ },
26402
+ "cancelable": true,
26403
+ "composed": true,
26404
+ "docs": "",
26405
+ "docsTags": []
26406
+ },
26267
26407
  {
26268
26408
  "event": "dsGroupCollapseChange",
26269
26409
  "detail": "TableGroupCollapseChangeDetail",
@@ -26448,6 +26588,7 @@
26448
26588
  "ds-menu": [
26449
26589
  "ds-text",
26450
26590
  "ds-swatch-picker",
26591
+ "ds-icon",
26451
26592
  "ds-tag",
26452
26593
  "ds-badge",
26453
26594
  "ds-switch"
@@ -29281,7 +29422,7 @@
29281
29422
  "path": "src/wc/utils/index.ts"
29282
29423
  },
29283
29424
  "src/wc/components/Menu/menu-types.ts::MenuItemData": {
29284
- "declaration": "export interface MenuItemData {\n label: string;\n value?: string;\n subtext?: string;\n /** Show a supplemental brand notification dot. */\n dot?: boolean;\n /** Show a non-interactive tag at the trailing edge of the row. */\n tag?: MenuItemTagData;\n isSelected?: boolean;\n isInactive?: boolean;\n isDestructive?: boolean;\n /** Render a compact switch indicator; the menu row owns interaction. */\n showSwitch?: boolean;\n switchValue?: boolean;\n}",
29425
+ "declaration": "export interface MenuItemData {\n label: string;\n value?: string;\n subtext?: string;\n /** Leading decorative icon. Ignored when `reorderable` is true. */\n icon?: string;\n /** Show a supplemental brand notification dot. */\n dot?: boolean;\n /** Show a non-interactive tag at the trailing edge of the row. */\n tag?: MenuItemTagData;\n isSelected?: boolean;\n isInactive?: boolean;\n isDestructive?: boolean;\n /** Render a compact switch indicator; the menu row owns interaction. */\n showSwitch?: boolean;\n switchValue?: boolean;\n /** Prefix a drag handle and allow pointer and keyboard reorder within the contiguous reorderable run. */\n reorderable?: boolean;\n}",
29285
29426
  "docstring": "",
29286
29427
  "path": "src/wc/components/Menu/menu-types.ts"
29287
29428
  },
@@ -29315,6 +29456,11 @@
29315
29456
  "docstring": "",
29316
29457
  "path": "src/wc/utils/index.ts"
29317
29458
  },
29459
+ "src/wc/components/Menu/menu-types.ts::MenuReorderDetail": {
29460
+ "declaration": "export interface MenuReorderDetail {\n item: MenuItemData;\n fromIndex: number;\n toIndex: number;\n sectionIndex: number;\n items: MenuItemData[];\n}",
29461
+ "docstring": "Next section item order after a pointer or keyboard reorder.",
29462
+ "path": "src/wc/components/Menu/menu-types.ts"
29463
+ },
29318
29464
  "src/wc/components/MessageBubble/MessageBubble.tsx::MessageBubbleVariant": {
29319
29465
  "declaration": "export type MessageBubbleVariant = 'user' | 'received';",
29320
29466
  "docstring": "",
@@ -29925,6 +30071,11 @@
29925
30071
  "docstring": "",
29926
30072
  "path": "src/wc/components/Table/table-types.ts"
29927
30073
  },
30074
+ "src/wc/components/Table/table-types.ts::TableColumnsConfigChangeDetail": {
30075
+ "declaration": "export interface TableColumnsConfigChangeDetail {\n hiddenColumnIds: string[];\n columnOrder: string[];\n}",
30076
+ "docstring": "Controlled show/hide and data-column order for the table-owned customizer.",
30077
+ "path": "src/wc/components/Table/table-types.ts"
30078
+ },
29928
30079
  "src/wc/toast/index.ts::ToastManager": {
29929
30080
  "declaration": "any",
29930
30081
  "docstring": "",
@@ -54,7 +54,7 @@
54
54
  "accessibility": [
55
55
  "Provide an explicit accessible name for every icon-only action.",
56
56
  "Set hasMenu when the button triggers a Menu; it implies aria-haspopup of menu. Pass controls with the Menu id and expanded from the same open state given to Menu. Expanded popup triggers hold only the pressed wash while open, without changing their resting foreground; expanded disclosure controls without popup semantics retain the normal resting appearance.",
57
- "Give an icon-only menu button an accessible name that states the role, such as More options, because no visible label or chevron carries it.",
57
+ "Give an icon-only menu button an accessible name that states the role, such as More options or Customize table, because no visible label or chevron carries it.",
58
58
  "Use haspopup directly for a non-menu popup such as a listbox or dialog; those cases get no chevron.",
59
59
  "Use pressed only for a genuine toggle button; it supplies aria-pressed and dsChange intent. Use isActive only for owner-controlled visual emphasis inside a composite whose selection semantics live on the owner.",
60
60
  "Treat notification dots as supplemental unread or status information; never use a dot as the sole state, meaning, or accessible name.",
@@ -74,8 +74,8 @@
74
74
  "Rounded changes only the control radius to the half-radius treatment; it does not change hierarchy, size, variant, or interaction semantics.",
75
75
  "Physical press scaling is on by default. Disable it only when an owning composite must keep child or background geometry fixed; hover and pressed interaction washes remain available.",
76
76
  "Icon and icon-label loading replace the icon in place. Label-only loading centers the loader while preserving the button's measured width.",
77
- "hasMenu covers two distinct menu-button shapes and the variant selects between them. With label or icon-label the action has a menu, and a trailing chevron carries the affordance. With icon the button is a menu, meaning the overflow or more-options control, and no chevron is added.",
78
- "Because the icon-only shape has no chevron, its glyph must convey the menu on its own; use Ellipses. Never pair hasMenu with an icon-only glyph that does not read as a menu.",
77
+ "hasMenu covers two distinct menu-button shapes and the variant selects between them. With label or icon-label the action has a menu, and a trailing chevron carries the affordance. With icon the button is a menu and no chevron is added.",
78
+ "Because the icon-only shape has no chevron, its glyph must convey the menu on its own. Use Ellipses for a generic more-options or overflow control. Use a specific icon when the menu has a named purpose, such as Preferences for Customize table.",
79
79
  "An open popup is a transient pressed state rather than a selected one. While expanded is true and haspopup or hasMenu identifies a popup, the pressed wash is held for the popup's complete rendered lifecycle and survives hover without promoting foreground or selected fill, including when chrome opts out of selected fills with activeFill set to false. Expanded disclosure buttons without popup semantics remain visually neutral."
80
80
  ],
81
81
  "responsiveBehavior": [
@@ -177,7 +177,7 @@
177
177
  "default": "false",
178
178
  "required": false,
179
179
  "mutable": false,
180
- "description": "Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\nboth menu-button shapes:\n\n- `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n the affordance.\n- `icon` — the button *is* a menu, i.e. the overflow / more-options control.\n No chevron is added, so the glyph must convey it on its own; use `Ellipses`.\n\nUse `haspopup` directly for non-menu popups."
180
+ "description": "Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\nboth menu-button shapes:\n\n- `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n the affordance.\n- `icon` — the button *is* a menu. No chevron is added, so the glyph must\n convey the menu on its own. Use `Ellipses` for generic more-options;\n use a specific icon when the menu has a named purpose, such as\n `Preferences` for Customize table.\n\nUse `haspopup` directly for non-menu popups."
181
181
  },
182
182
  "haspopup": {
183
183
  "type": "ButtonUnfilledPopup | undefined",
@@ -411,7 +411,7 @@
411
411
  "default": "false",
412
412
  "required": false,
413
413
  "mutable": false,
414
- "description": "Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\nboth menu-button shapes:\n\n- `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n the affordance.\n- `icon` — the button *is* a menu, i.e. the overflow / more-options control.\n No chevron is added, so the glyph must convey it on its own; use `Ellipses`.\n\nUse `haspopup` directly for non-menu popups."
414
+ "description": "Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\nboth menu-button shapes:\n\n- `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n the affordance.\n- `icon` — the button *is* a menu. No chevron is added, so the glyph must\n convey the menu on its own. Use `Ellipses` for generic more-options;\n use a specific icon when the menu has a named purpose, such as\n `Preferences` for Customize table.\n\nUse `haspopup` directly for non-menu popups."
415
415
  },
416
416
  "haspopup": {
417
417
  "type": "ButtonUnfilledPopup | undefined",
@@ -617,7 +617,7 @@
617
617
  },
618
618
  {
619
619
  "path": "src/wc/components/ButtonUnfilled/ButtonUnfilled.tsx",
620
- "content": "import { Component, Element, Event, EventEmitter, h, Host, Method, Prop } from '@stencil/core';\nimport { controlWidthClass } from '../../utils';\nimport { beginElevatedControlPress } from '../../utils/control-press';\nimport { renderButtonContent } from '../../utils/button-render';\nimport type { ControlInsetDepth } from '../../utils/control-text';\nimport type {\n ButtonPopup,\n ButtonSize,\n ButtonVariant,\n ButtonWidth,\n} from '../../utils/button-types';\n\nexport type ButtonUnfilledBackground =\n | 'faint'\n | 'medium'\n | 'bold'\n | 'strong'\n | 'translucent'\n | 'inverted'\n | 'media'\n | 'always-dark';\n\nexport type ButtonUnfilledVariant = ButtonVariant;\nexport type ButtonUnfilledSize = ButtonSize;\nexport type ButtonUnfilledWidth = ButtonWidth;\nexport type ButtonUnfilledPopup = ButtonPopup;\n\n@Component({\n tag: 'ds-button-unfilled',\n styleUrl: 'ButtonUnfilled.css',\n scoped: true,\n})\nexport class ButtonUnfilled {\n @Element() el!: HTMLElement;\n\n /**\n * Content layout. Default is label-only; pass `icon` for icon-only chrome\n * (nav / tool rails) or `icon-label` for leading icon + text.\n */\n @Prop() variant: ButtonUnfilledVariant = 'label';\n\n /** Control density (height, padding, icon, type). */\n @Prop() size: ButtonUnfilledSize = 'md';\n\n /** Use reduced outer geometry when nested inside a control of the same size. */\n @Prop() isInset: boolean = false;\n\n /** Single removes 4px overall; double removes 8px overall (xs stays single). */\n @Prop() insetDepth: ControlInsetDepth = 'single';\n\n /** Width fit — hug content (default) or fill the parent. */\n @Prop() width: ButtonUnfilledWidth = 'hug';\n\n /** Visible text for `label` / `icon-label` variants. */\n @Prop() label: string = '';\n\n /** Icon name passed to <ds-icon> for `icon` / `icon-label` variants. */\n @Prop() icon: string = '';\n\n /**\n * Owner-controlled visual emphasis inside a composite. This does not add\n * toggle semantics and does not emit dsChange.\n */\n @Prop() isActive: boolean = false;\n\n /**\n * When active, render the selected interaction fill.\n * Default `true` for general UI. Shell chrome (nav / tool rails) should pass\n * `false` so selection is foreground-only (primary color, no fill).\n */\n @Prop() activeFill: boolean = true;\n\n /** Show a 1px secondary inset border. Default on; shell chrome can pass `false`. */\n @Prop() hasBorder: boolean = true;\n\n /** Use the half-radius treatment instead of the default control radius. */\n @Prop() rounded: boolean = false;\n\n /**\n * Scale down during a physical pointer press.\n * Disable when an owning composite requires fixed child or background geometry.\n */\n @Prop() pressScale: boolean = true;\n\n /** Show a notification dot at the top-right of the icon zone (icon variant only). */\n @Prop() dot: boolean = false;\n\n /** Disables interaction. */\n @Prop() isInactive: boolean = false;\n\n /** Shows an inline loader and prevents interaction without applying inactive opacity. */\n @Prop() isLoading: boolean = false;\n\n /** Native button type. */\n @Prop() type: 'button' | 'submit' | 'reset' = 'button';\n\n /** Actual parent surface context. Omit on primary and secondary surfaces. */\n @Prop() background: ButtonUnfilledBackground | undefined;\n\n /** Accessible name override. Required for icon-only buttons. */\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n @Prop() controls: string | undefined;\n /**\n * Controlled disclosure or popup state forwarded to `aria-expanded`.\n * Popup triggers hold only the pressed wash while open; their resting\n * foreground is unchanged. Ordinary disclosures remain visually neutral.\n */\n @Prop() expanded: boolean | undefined;\n @Prop() haspopup: ButtonUnfilledPopup | undefined;\n /**\n * Controlled state for a genuine toggle button. Adds aria-pressed, promotes\n * active styling, and makes activation emit dsChange with the requested state.\n */\n @Prop() pressed: boolean | undefined;\n\n /**\n * Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\n * both menu-button shapes:\n *\n * - `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n * the affordance.\n * - `icon` — the button *is* a menu, i.e. the overflow / more-options control.\n * No chevron is added, so the glyph must convey it on its own; use `Ellipses`.\n *\n * Use `haspopup` directly for non-menu popups.\n */\n @Prop() hasMenu: boolean = false;\n\n /**\n * Native `tabindex` for roving keyboard groups in shell chrome.\n * Omit for the default button tab stop (`0`).\n */\n @Prop({ attribute: 'tab-index' }) focusTabIndex?: number;\n\n @Event() dsClick!: EventEmitter<MouseEvent>;\n @Event() dsChange!: EventEmitter<boolean>;\n\n private buttonEl: HTMLButtonElement | null = null;\n\n @Method()\n async setFocus() {\n this.buttonEl?.focus();\n }\n\n private handleClick = (event: MouseEvent) => {\n if (this.isInactive || this.isLoading) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n this.dsClick.emit(event);\n if (this.pressed !== undefined) this.dsChange.emit(!this.pressed);\n };\n\n private get showDot(): boolean {\n return this.variant === 'icon' && this.dot && !this.isLoading;\n }\n\n private get resolvedHaspopup(): ButtonUnfilledPopup | undefined {\n return this.haspopup ?? (this.hasMenu ? 'menu' : undefined);\n }\n\n private get doubleInset(): boolean {\n return this.isInset && this.insetDepth === 'double' && this.size !== 'xs';\n }\n\n /** Only popup triggers hold a pressed visual while expanded. */\n private get expandedPopup(): boolean {\n return this.expanded === true && this.resolvedHaspopup !== undefined && !this.isInactive;\n }\n\n private get visuallyActive(): boolean {\n return this.isActive || this.pressed === true;\n }\n\n /** Knock-out ring: selected fill → active wash; otherwise surface token. */\n private get dotRing(): string {\n if ((this.isActive || this.pressed === true) && this.activeFill) {\n return 'var(--ds-interaction-active)';\n }\n return 'var(--ds-button-unfilled-dot-ring)';\n }\n\n private get accessibleName(): string | undefined {\n if (this.ariaLabel) return this.ariaLabel;\n if (this.isLoading && this.variant === 'label' && this.label) return this.label;\n return undefined;\n }\n\n render() {\n const bg = this.background;\n const cls: Record<string, boolean> = {\n 'button-unfilled': true,\n 'ds-button': true,\n 'ds-focus-ring-inset': true,\n 'ds-control-press-scale': this.pressScale,\n 'ds-interaction-fill': true,\n 'ds-interaction-fill--selected':\n (this.isActive || this.pressed === true) &&\n this.activeFill &&\n !this.isInactive,\n 'ds-interaction-fill--on-faint': bg === 'faint',\n 'ds-interaction-fill--on-medium': bg === 'medium',\n 'ds-interaction-fill--on-bold': bg === 'bold',\n 'ds-interaction-fill--on-strong': bg === 'strong',\n 'ds-interaction-fill--on-translucent': bg === 'translucent',\n 'ds-interaction-fill--on-inverted': bg === 'inverted',\n 'ds-interaction-fill--on-media': bg === 'media',\n 'ds-interaction-fill--on-always-dark': bg === 'always-dark',\n 'button-unfilled--active': this.visuallyActive,\n 'button-unfilled--expanded': this.expandedPopup,\n 'ds-button--expanded': this.expandedPopup,\n 'button-unfilled--bordered': this.hasBorder,\n 'ds-button--bordered': this.hasBorder,\n 'button-unfilled--rounded': this.rounded,\n 'ds-button--rounded': this.rounded,\n 'ds-control-inactive': this.isInactive,\n 'ds-control--lg': this.size === 'lg',\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n 'ds-control--inset': this.isInset && !this.doubleInset,\n 'ds-control--inset-double': this.doubleInset,\n 'ds-control-frame': true,\n 'button-unfilled--icon': this.variant === 'icon',\n 'ds-button--icon': this.variant === 'icon',\n 'button-unfilled--label': this.variant === 'label',\n 'button-unfilled--icon-label': this.variant === 'icon-label',\n 'button-unfilled--background-faint': bg === 'faint',\n 'button-unfilled--background-medium': bg === 'medium',\n 'button-unfilled--background-bold': bg === 'bold',\n 'button-unfilled--background-strong': bg === 'strong',\n 'button-unfilled--background-translucent': bg === 'translucent',\n 'button-unfilled--background-inverted': bg === 'inverted',\n 'button-unfilled--background-media': bg === 'media',\n 'button-unfilled--on-always-dark': bg === 'always-dark',\n };\n\n return (\n <Host\n class={{\n 'button-unfilled-host': true,\n 'button-unfilled-host--icon': this.variant === 'icon',\n 'ds-button-host--icon': this.variant === 'icon',\n 'ds-control--lg': this.size === 'lg',\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n 'ds-control--inset': this.isInset && !this.doubleInset,\n 'ds-control--inset-double': this.doubleInset,\n ...controlWidthClass(this.width),\n }}\n tabIndex={-1}\n >\n <button\n ref={el => {\n this.buttonEl = el ?? null;\n }}\n type={this.type}\n class={cls}\n disabled={this.isInactive}\n tabIndex={this.focusTabIndex ?? 0}\n aria-label={this.accessibleName}\n aria-busy={this.isLoading ? 'true' : undefined}\n aria-disabled={this.isLoading ? 'true' : undefined}\n aria-controls={this.controls}\n aria-expanded={this.expanded === undefined ? undefined : String(this.expanded)}\n aria-haspopup={this.resolvedHaspopup}\n aria-pressed={this.pressed === undefined ? undefined : String(this.pressed)}\n onPointerDown={event =>\n beginElevatedControlPress(\n event,\n this.pressScale && !this.isInactive && !this.isLoading,\n )\n }\n onClick={this.handleClick}\n >\n {renderButtonContent({\n namespace: 'button-unfilled',\n variant: this.variant,\n size: this.size,\n label: this.label,\n icon: this.icon,\n hasMenu: this.hasMenu,\n isLoading: this.isLoading,\n dot: {\n visible: this.showDot,\n background: this.dotRing,\n },\n })}\n </button>\n </Host>\n );\n }\n}\n",
620
+ "content": "import { Component, Element, Event, EventEmitter, h, Host, Method, Prop } from '@stencil/core';\nimport { controlWidthClass } from '../../utils';\nimport { beginElevatedControlPress } from '../../utils/control-press';\nimport { renderButtonContent } from '../../utils/button-render';\nimport type { ControlInsetDepth } from '../../utils/control-text';\nimport type {\n ButtonPopup,\n ButtonSize,\n ButtonVariant,\n ButtonWidth,\n} from '../../utils/button-types';\n\nexport type ButtonUnfilledBackground =\n | 'faint'\n | 'medium'\n | 'bold'\n | 'strong'\n | 'translucent'\n | 'inverted'\n | 'media'\n | 'always-dark';\n\nexport type ButtonUnfilledVariant = ButtonVariant;\nexport type ButtonUnfilledSize = ButtonSize;\nexport type ButtonUnfilledWidth = ButtonWidth;\nexport type ButtonUnfilledPopup = ButtonPopup;\n\n@Component({\n tag: 'ds-button-unfilled',\n styleUrl: 'ButtonUnfilled.css',\n scoped: true,\n})\nexport class ButtonUnfilled {\n @Element() el!: HTMLElement;\n\n /**\n * Content layout. Default is label-only; pass `icon` for icon-only chrome\n * (nav / tool rails) or `icon-label` for leading icon + text.\n */\n @Prop() variant: ButtonUnfilledVariant = 'label';\n\n /** Control density (height, padding, icon, type). */\n @Prop() size: ButtonUnfilledSize = 'md';\n\n /** Use reduced outer geometry when nested inside a control of the same size. */\n @Prop() isInset: boolean = false;\n\n /** Single removes 4px overall; double removes 8px overall (xs stays single). */\n @Prop() insetDepth: ControlInsetDepth = 'single';\n\n /** Width fit — hug content (default) or fill the parent. */\n @Prop() width: ButtonUnfilledWidth = 'hug';\n\n /** Visible text for `label` / `icon-label` variants. */\n @Prop() label: string = '';\n\n /** Icon name passed to <ds-icon> for `icon` / `icon-label` variants. */\n @Prop() icon: string = '';\n\n /**\n * Owner-controlled visual emphasis inside a composite. This does not add\n * toggle semantics and does not emit dsChange.\n */\n @Prop() isActive: boolean = false;\n\n /**\n * When active, render the selected interaction fill.\n * Default `true` for general UI. Shell chrome (nav / tool rails) should pass\n * `false` so selection is foreground-only (primary color, no fill).\n */\n @Prop() activeFill: boolean = true;\n\n /** Show a 1px secondary inset border. Default on; shell chrome can pass `false`. */\n @Prop() hasBorder: boolean = true;\n\n /** Use the half-radius treatment instead of the default control radius. */\n @Prop() rounded: boolean = false;\n\n /**\n * Scale down during a physical pointer press.\n * Disable when an owning composite requires fixed child or background geometry.\n */\n @Prop() pressScale: boolean = true;\n\n /** Show a notification dot at the top-right of the icon zone (icon variant only). */\n @Prop() dot: boolean = false;\n\n /** Disables interaction. */\n @Prop() isInactive: boolean = false;\n\n /** Shows an inline loader and prevents interaction without applying inactive opacity. */\n @Prop() isLoading: boolean = false;\n\n /** Native button type. */\n @Prop() type: 'button' | 'submit' | 'reset' = 'button';\n\n /** Actual parent surface context. Omit on primary and secondary surfaces. */\n @Prop() background: ButtonUnfilledBackground | undefined;\n\n /** Accessible name override. Required for icon-only buttons. */\n @Prop({ attribute: 'aria-label' }) ariaLabel: string | null = null;\n @Prop() controls: string | undefined;\n /**\n * Controlled disclosure or popup state forwarded to `aria-expanded`.\n * Popup triggers hold only the pressed wash while open; their resting\n * foreground is unchanged. Ordinary disclosures remain visually neutral.\n */\n @Prop() expanded: boolean | undefined;\n @Prop() haspopup: ButtonUnfilledPopup | undefined;\n /**\n * Controlled state for a genuine toggle button. Adds aria-pressed, promotes\n * active styling, and makes activation emit dsChange with the requested state.\n */\n @Prop() pressed: boolean | undefined;\n\n /**\n * Mark the button as a Menu trigger. Implies `aria-haspopup=\"menu\"` and covers\n * both menu-button shapes:\n *\n * - `label` / `icon-label` — the action *has* a menu; a trailing chevron carries\n * the affordance.\n * - `icon` — the button *is* a menu. No chevron is added, so the glyph must\n * convey the menu on its own. Use `Ellipses` for generic more-options;\n * use a specific icon when the menu has a named purpose, such as\n * `Preferences` for Customize table.\n *\n * Use `haspopup` directly for non-menu popups.\n */\n @Prop() hasMenu: boolean = false;\n\n /**\n * Native `tabindex` for roving keyboard groups in shell chrome.\n * Omit for the default button tab stop (`0`).\n */\n @Prop({ attribute: 'tab-index' }) focusTabIndex?: number;\n\n @Event() dsClick!: EventEmitter<MouseEvent>;\n @Event() dsChange!: EventEmitter<boolean>;\n\n private buttonEl: HTMLButtonElement | null = null;\n\n @Method()\n async setFocus() {\n this.buttonEl?.focus();\n }\n\n private handleClick = (event: MouseEvent) => {\n if (this.isInactive || this.isLoading) {\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n this.dsClick.emit(event);\n if (this.pressed !== undefined) this.dsChange.emit(!this.pressed);\n };\n\n private get showDot(): boolean {\n return this.variant === 'icon' && this.dot && !this.isLoading;\n }\n\n private get resolvedHaspopup(): ButtonUnfilledPopup | undefined {\n return this.haspopup ?? (this.hasMenu ? 'menu' : undefined);\n }\n\n private get doubleInset(): boolean {\n return this.isInset && this.insetDepth === 'double' && this.size !== 'xs';\n }\n\n /** Only popup triggers hold a pressed visual while expanded. */\n private get expandedPopup(): boolean {\n return this.expanded === true && this.resolvedHaspopup !== undefined && !this.isInactive;\n }\n\n private get visuallyActive(): boolean {\n return this.isActive || this.pressed === true;\n }\n\n /** Knock-out ring: selected fill → active wash; otherwise surface token. */\n private get dotRing(): string {\n if ((this.isActive || this.pressed === true) && this.activeFill) {\n return 'var(--ds-interaction-active)';\n }\n return 'var(--ds-button-unfilled-dot-ring)';\n }\n\n private get accessibleName(): string | undefined {\n if (this.ariaLabel) return this.ariaLabel;\n if (this.isLoading && this.variant === 'label' && this.label) return this.label;\n return undefined;\n }\n\n render() {\n const bg = this.background;\n const cls: Record<string, boolean> = {\n 'button-unfilled': true,\n 'ds-button': true,\n 'ds-focus-ring-inset': true,\n 'ds-control-press-scale': this.pressScale,\n 'ds-interaction-fill': true,\n 'ds-interaction-fill--selected':\n (this.isActive || this.pressed === true) &&\n this.activeFill &&\n !this.isInactive,\n 'ds-interaction-fill--on-faint': bg === 'faint',\n 'ds-interaction-fill--on-medium': bg === 'medium',\n 'ds-interaction-fill--on-bold': bg === 'bold',\n 'ds-interaction-fill--on-strong': bg === 'strong',\n 'ds-interaction-fill--on-translucent': bg === 'translucent',\n 'ds-interaction-fill--on-inverted': bg === 'inverted',\n 'ds-interaction-fill--on-media': bg === 'media',\n 'ds-interaction-fill--on-always-dark': bg === 'always-dark',\n 'button-unfilled--active': this.visuallyActive,\n 'button-unfilled--expanded': this.expandedPopup,\n 'ds-button--expanded': this.expandedPopup,\n 'button-unfilled--bordered': this.hasBorder,\n 'ds-button--bordered': this.hasBorder,\n 'button-unfilled--rounded': this.rounded,\n 'ds-button--rounded': this.rounded,\n 'ds-control-inactive': this.isInactive,\n 'ds-control--lg': this.size === 'lg',\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n 'ds-control--inset': this.isInset && !this.doubleInset,\n 'ds-control--inset-double': this.doubleInset,\n 'ds-control-frame': true,\n 'button-unfilled--icon': this.variant === 'icon',\n 'ds-button--icon': this.variant === 'icon',\n 'button-unfilled--label': this.variant === 'label',\n 'button-unfilled--icon-label': this.variant === 'icon-label',\n 'button-unfilled--background-faint': bg === 'faint',\n 'button-unfilled--background-medium': bg === 'medium',\n 'button-unfilled--background-bold': bg === 'bold',\n 'button-unfilled--background-strong': bg === 'strong',\n 'button-unfilled--background-translucent': bg === 'translucent',\n 'button-unfilled--background-inverted': bg === 'inverted',\n 'button-unfilled--background-media': bg === 'media',\n 'button-unfilled--on-always-dark': bg === 'always-dark',\n };\n\n return (\n <Host\n class={{\n 'button-unfilled-host': true,\n 'button-unfilled-host--icon': this.variant === 'icon',\n 'ds-button-host--icon': this.variant === 'icon',\n 'ds-control--lg': this.size === 'lg',\n 'ds-control--md': this.size === 'md',\n 'ds-control--sm': this.size === 'sm',\n 'ds-control--xs': this.size === 'xs',\n 'ds-control--inset': this.isInset && !this.doubleInset,\n 'ds-control--inset-double': this.doubleInset,\n ...controlWidthClass(this.width),\n }}\n tabIndex={-1}\n >\n <button\n ref={el => {\n this.buttonEl = el ?? null;\n }}\n type={this.type}\n class={cls}\n disabled={this.isInactive}\n tabIndex={this.focusTabIndex ?? 0}\n aria-label={this.accessibleName}\n aria-busy={this.isLoading ? 'true' : undefined}\n aria-disabled={this.isLoading ? 'true' : undefined}\n aria-controls={this.controls}\n aria-expanded={this.expanded === undefined ? undefined : String(this.expanded)}\n aria-haspopup={this.resolvedHaspopup}\n aria-pressed={this.pressed === undefined ? undefined : String(this.pressed)}\n onPointerDown={event =>\n beginElevatedControlPress(\n event,\n this.pressScale && !this.isInactive && !this.isLoading,\n )\n }\n onClick={this.handleClick}\n >\n {renderButtonContent({\n namespace: 'button-unfilled',\n variant: this.variant,\n size: this.size,\n label: this.label,\n icon: this.icon,\n hasMenu: this.hasMenu,\n isLoading: this.isLoading,\n dot: {\n visible: this.showDot,\n background: this.dotRing,\n },\n })}\n </button>\n </Host>\n );\n }\n}\n",
621
621
  "type": "registry:ui"
622
622
  }
623
623
  ]