@mcp-b/web-components 0.2.22 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +93 -30
  2. package/dist/{alert-dialog-D25Oi_TS.js → alert-dialog-CGUwj_0U.js} +1 -1
  3. package/dist/{button-gg3JJxQZ.js → button-BbabhtKj.js} +121 -77
  4. package/dist/{button-BQofnUt4.d.ts → button-c5YKsC69.d.ts} +6 -3
  5. package/dist/{checkbox-DoFcDEKB.d.ts → checkbox-BtoypUxD.d.ts} +0 -6
  6. package/dist/{checkbox-C96lUDIM.js → checkbox-C97tlcf2.js} +11 -43
  7. package/dist/{color-input-Gae_-9w-.js → color-input-Dtp1v7A-.js} +14 -54
  8. package/dist/{color-input-Bky89xg_.d.ts → color-input-S29ZHwHE.d.ts} +0 -5
  9. package/dist/{color-picker-BYyZavkT.js → color-picker-Mnpc5u6E.js} +8 -4
  10. package/dist/{combobox-iERnTD3A.js → combobox-D4ji7M2B.js} +12 -33
  11. package/dist/{combobox-item-D2H1CMxC.d.ts → combobox-item-BnBtZyhw.d.ts} +3 -6
  12. package/dist/{comparison-B1-nMwmp.d.ts → comparison-CRvbwS7X.d.ts} +1 -0
  13. package/dist/{comparison-HJ1Zedhs.js → comparison-DQUpvkmg.js} +11 -3
  14. package/dist/components/alert-dialog/alert-dialog.js +1 -1
  15. package/dist/components/button/button.d.ts +1 -1
  16. package/dist/components/button/button.js +1 -1
  17. package/dist/components/carousel/carousel.js +1 -1
  18. package/dist/components/checkbox/checkbox.d.ts +1 -1
  19. package/dist/components/checkbox/checkbox.js +1 -1
  20. package/dist/components/color-input/color-input.d.ts +1 -1
  21. package/dist/components/color-input/color-input.js +1 -1
  22. package/dist/components/color-picker/color-picker.js +1 -1
  23. package/dist/components/combobox/combobox.d.ts +1 -1
  24. package/dist/components/combobox/combobox.js +1 -1
  25. package/dist/components/combobox-item/combobox-item.d.ts +1 -1
  26. package/dist/components/comparison/comparison.d.ts +1 -1
  27. package/dist/components/comparison/comparison.js +1 -1
  28. package/dist/components/copy/copy.js +4 -20
  29. package/dist/components/date/date.d.ts +1 -1
  30. package/dist/components/date/date.js +1 -1
  31. package/dist/components/dialog/dialog.js +1 -1
  32. package/dist/components/dropdown/dropdown.d.ts +1 -1
  33. package/dist/components/dropdown/dropdown.js +1 -1
  34. package/dist/components/expander/expander.js +1 -1
  35. package/dist/components/file-input/file-input.d.ts +1 -1
  36. package/dist/components/file-input/file-input.js +1 -1
  37. package/dist/components/filter-bar/filter-bar.js +1 -1
  38. package/dist/components/index.d.ts +24 -24
  39. package/dist/components/index.js +48 -48
  40. package/dist/components/infinite-scroller/infinite-scroller.js +1 -1
  41. package/dist/components/intersection-observer/intersection-observer.js +1 -1
  42. package/dist/components/listbox/listbox.d.ts +1 -1
  43. package/dist/components/listbox/listbox.js +1 -1
  44. package/dist/components/mutation-observer/mutation-observer.js +1 -1
  45. package/dist/components/navicon/navicon.js +1 -1
  46. package/dist/components/number/number.js +1 -1
  47. package/dist/components/number-field/number-field.d.ts +1 -1
  48. package/dist/components/number-field/number-field.js +1 -1
  49. package/dist/components/pagination/pagination.js +1 -1
  50. package/dist/components/popover/popover.js +1 -1
  51. package/dist/components/preview-card/preview-card.js +1 -1
  52. package/dist/components/radio/radio.d.ts +1 -1
  53. package/dist/components/radio/radio.js +1 -1
  54. package/dist/components/radio-item/radio-item.js +1 -1
  55. package/dist/components/rating/rating.d.ts +1 -1
  56. package/dist/components/rating/rating.js +1 -1
  57. package/dist/components/resize-observer/resize-observer.js +1 -1
  58. package/dist/components/scroller/scroller.js +1 -1
  59. package/dist/components/search-list/search-list.d.ts +1 -1
  60. package/dist/components/search-list/search-list.js +1 -1
  61. package/dist/components/select/select.d.ts +1 -1
  62. package/dist/components/select/select.js +1 -1
  63. package/dist/components/share/share.js +1 -1
  64. package/dist/components/slide-activator/slide-activator.d.ts +1 -1
  65. package/dist/components/slide-activator/slide-activator.js +1 -1
  66. package/dist/components/slider/slider.d.ts +1 -1
  67. package/dist/components/slider/slider.js +1 -1
  68. package/dist/components/spinner/spinner.js +1 -1
  69. package/dist/components/splitter/splitter.d.ts +1 -1
  70. package/dist/components/splitter/splitter.js +1 -1
  71. package/dist/components/switch/switch.d.ts +1 -1
  72. package/dist/components/switch/switch.js +1 -1
  73. package/dist/components/tab-list/tab-list.js +1 -1
  74. package/dist/components/text-area/text-area.d.ts +1 -1
  75. package/dist/components/text-area/text-area.js +1 -1
  76. package/dist/components/text-field/text-field.d.ts +1 -1
  77. package/dist/components/text-field/text-field.js +1 -1
  78. package/dist/components/timed-content/timed-content.js +1 -1
  79. package/dist/components/toast/toast.d.ts +1 -1
  80. package/dist/components/toast/toast.js +1 -1
  81. package/dist/components/toast-item/toast-item.js +1 -1
  82. package/dist/components/toggle-icon/toggle-icon.d.ts +1 -1
  83. package/dist/components/toggle-icon/toggle-icon.js +1 -1
  84. package/dist/components/toggle-tag/toggle-tag.d.ts +1 -1
  85. package/dist/components/toggle-tag/toggle-tag.js +1 -1
  86. package/dist/components/tooltip/tooltip.js +1 -1
  87. package/dist/components/transition-group/transition-group.d.ts +1 -1
  88. package/dist/components/transition-group/transition-group.js +1 -1
  89. package/dist/components/zoomable-frame/zoomable-frame.js +1 -1
  90. package/dist/{date-6M6wfa8L.d.ts → date-DtaTBM71.d.ts} +1 -1
  91. package/dist/docs/custom-elements.json +126 -171
  92. package/dist/{dropdown-DM4tlF_p.js → dropdown-BPOpCp59.js} +58 -34
  93. package/dist/{dropdown-Bo00Vlr5.d.ts → dropdown-C5ldJu4g.d.ts} +5 -1
  94. package/dist/{localize-322EtXNX.d.ts → en-ss05iPjS.d.ts} +4 -1
  95. package/dist/{file-input-vZFm22Lo.js → file-input-B4VfcfTD.js} +17 -33
  96. package/dist/{file-input-D2D6YC0B.d.ts → file-input-CgsTcC1R.d.ts} +0 -5
  97. package/dist/{filter-bar-DJuDlx5f.js → filter-bar-DhQSMr3S.js} +1 -1
  98. package/dist/index.d.ts +25 -27
  99. package/dist/index.js +49 -52
  100. package/dist/{infinite-scroller-BmmtnWNt.js → infinite-scroller-DjeMswwE.js} +2 -2
  101. package/dist/{intersection-observer-B6TciOAQ.js → intersection-observer-Db0-7ZvZ.js} +1 -1
  102. package/dist/{listbox-B0geidHW.js → listbox-BGHw-rUd.js} +13 -28
  103. package/dist/{listbox-DD4ujIJe.d.ts → listbox-DKoMIQA6.d.ts} +3 -5
  104. package/dist/{mutation-observer-DS8EBuOp.js → mutation-observer-DkhonHyD.js} +1 -1
  105. package/dist/{number-field-odk4lKXM.d.ts → number-field-T0rzObq9.d.ts} +0 -5
  106. package/dist/{number-field-BGH7JtNf.js → number-field-yME3rRZT.js} +44 -55
  107. package/dist/{popover-DJBrJ0za.js → popover-lsI6gqNk.js} +9 -32
  108. package/dist/{preview-card-C7H1FPfd.js → preview-card-D1msvOWP.js} +1 -1
  109. package/dist/{radio-8UZAUYXt.js → radio-4Cok4gJI.js} +11 -28
  110. package/dist/{radio-CieMa4zU.d.ts → radio-B4fz924Q.d.ts} +1 -4
  111. package/dist/{radio-item-BlhFgXsU.js → radio-item-DpP3GBPV.js} +2 -3
  112. package/dist/{rating-4xNsWumY.d.ts → rating-8BLXhAVl.d.ts} +1 -3
  113. package/dist/{rating-C1BcJDIO.js → rating-CSn-nU2R.js} +24 -34
  114. package/dist/{resize-observer-DcrLhddo.js → resize-observer-Dg9Cm9e5.js} +1 -1
  115. package/dist/{search-list-Clmrg8EV.js → search-list-BffPIgnw.js} +19 -10
  116. package/dist/{search-list-n0GYO7rh.d.ts → search-list-Cd3--X7Q.d.ts} +11 -1
  117. package/dist/{select-CkZK2jJn.d.ts → select-6H_sN4A2.d.ts} +0 -5
  118. package/dist/{select-DLIaRnA4.js → select-B6nkY6E-.js} +7 -43
  119. package/dist/{share-bsgXZCl7.js → share-C7dB9NYf.js} +3 -19
  120. package/dist/{slide-activator-D7bBz69E.d.ts → slide-activator-CB0Ztk_u.d.ts} +1 -0
  121. package/dist/{slide-activator-Dm1EvZtL.js → slide-activator-Dkv5_KPl.js} +10 -3
  122. package/dist/{slider-B90Il7x3.js → slider-DY-GuC8T.js} +35 -46
  123. package/dist/{slider-B0FVsV1o.d.ts → slider-uQQ-T_kn.d.ts} +2 -3
  124. package/dist/{splitter-MnD4In9H.js → splitter-DzC0hXGN.js} +14 -3
  125. package/dist/{splitter-DBDJAzsp.d.ts → splitter-KQVgGdvP.d.ts} +1 -0
  126. package/dist/{switch-Cief9M59.d.ts → switch-BUfFo074.d.ts} +0 -6
  127. package/dist/{switch-D0hWr37A.js → switch-Chij-EaQ.js} +11 -43
  128. package/dist/{tab-list-B_Ye_Oj9.js → tab-list-CVOUSpAh.js} +2 -2
  129. package/dist/{text-area-B_mjCE9W.d.ts → text-area-DFMKyk8y.d.ts} +0 -3
  130. package/dist/{text-area-Czixaz-_.js → text-area-DZVghSkO.js} +14 -51
  131. package/dist/{text-field-BClWMp6q.d.ts → text-field-DepP1gei.d.ts} +0 -5
  132. package/dist/{text-field-Cznb4Afc.js → text-field-gX5RovkE.js} +11 -52
  133. package/dist/{timed-content-pvEP4l5V.js → timed-content-D00na-5r.js} +1 -0
  134. package/dist/{toast-cEBVK9NQ.d.ts → toast-CpyA3GYM.d.ts} +1 -1
  135. package/dist/{toast-DgkBQzQC.js → toast-CxfaWFY_.js} +2 -2
  136. package/dist/{toggle-icon-4oLDeEt4.js → toggle-icon-B3fZuslO.js} +9 -31
  137. package/dist/{toggle-icon-DlwMMWZL.d.ts → toggle-icon-sTLCOruF.d.ts} +0 -5
  138. package/dist/{toggle-tag-1sfTFJtg.js → toggle-tag--Gkp-CJJ.js} +7 -35
  139. package/dist/{toggle-tag-IVvMGT4R.d.ts → toggle-tag-DDBa6hAg.d.ts} +0 -5
  140. package/dist/{tooltip-DbyoPFNe.js → tooltip-bSXNhG9l.js} +9 -32
  141. package/dist/{transition-group-3hnAnwSd.js → transition-group-8PmQx0A5.js} +23 -4
  142. package/dist/{transition-group-DD_CjSNC.d.ts → transition-group-D134iT1k.d.ts} +8 -0
  143. package/dist/translations/en.d.ts +1 -5
  144. package/dist/translations/en.js +3 -6
  145. package/dist/translations/es.d.ts +1 -1
  146. package/dist/translations/es.js +2 -5
  147. package/dist/types/custom-element-jsx.d.ts +26 -10
  148. package/dist/utilities/anchored-surface.d.ts +36 -0
  149. package/dist/utilities/anchored-surface.js +46 -0
  150. package/dist/utilities/copy-feedback.d.ts +16 -0
  151. package/dist/utilities/copy-feedback.js +33 -0
  152. package/dist/utilities/form-validity.d.ts +28 -0
  153. package/dist/utilities/form-validity.js +33 -0
  154. package/dist/utilities/localize.d.ts +1 -1
  155. package/dist/utilities/localize.js +1 -0
  156. package/package.json +3 -2
  157. package/dist/{carousel-XopKISBQ.js → carousel-DpIqPTuO.js} +1 -1
  158. package/dist/{date-CJPmOdi9.js → date-CFIR88pX.js} +1 -1
  159. package/dist/{dialog-Cx46HMaZ.js → dialog-Ddvyn2d_.js} +1 -1
  160. package/dist/{expander-Bwvxj6Oa.js → expander-CMV4QCha.js} +1 -1
  161. package/dist/{navicon-_yMHY27-.js → navicon-B-5pY9gq.js} +1 -1
  162. package/dist/{number-BNtNXNF3.js → number-BYBxfOGw.js} +1 -1
  163. package/dist/{pagination-CrTQnuNW.js → pagination-VOzVTV8p.js} +1 -1
  164. package/dist/{scroller-LYgBVyfY.js → scroller-DZATZlDa.js} +1 -1
  165. package/dist/{spinner-C04Dmc0H.js → spinner-C9lQARtQ.js} +1 -1
  166. package/dist/{toast-item-CGvz92Qk.js → toast-item-DzSPG25R.js} +1 -1
  167. package/dist/{zoomable-frame-DxcjLGcF.js → zoomable-frame-BrjVkNMX.js} +1 -1
package/README.md CHANGED
@@ -1,49 +1,112 @@
1
- # Sigvelo
1
+ # MCP-B Web Components
2
2
 
3
- Sigvelo is an open source user interface library for the modern Web. It features dozens of accessible, performant, and interoperable components along with an optional CSS reset to streamline development of websites and apps.
3
+ `@mcp-b/web-components` is the Lit renderer of the MCP-B design system. It shares
4
+ design tokens and deliberately shared control contracts with
5
+ `@mcp-b/react-components`, the default renderer for product UI. Lit also supports
6
+ framework-independent maps, editors, visualizations, and IFC surfaces through
7
+ the sibling domain packages.
4
8
 
5
- You might be curious to learn that Sigvelo's components aren't built with React, Vue, or any other framework. They're custom HTML elements, or [Web Components](https://developer.mozilla.org/en-US/docs/Web/API/Web_components), which means you can use them in plain ol' HTML pages as well as your favorite frameworks.
9
+ ## Use a component
6
10
 
7
- **There are two primary packages for this library:**
11
+ Install with `vp add @mcp-b/web-components`, then import the theme and the elements
12
+ you use:
8
13
 
9
- - [`@mcp-b/web-components`](https://www.npmjs.com/package/@mcp-b/web-components) - Use with frameworks and bundlers
10
- - [`@mcp-b/web-components-browser`](https://www.npmjs.com/package/@mcp-b/web-components-browser) - Use directly in the browser and on CDNs
14
+ ```ts
15
+ import "@mcp-b/web-components/themes/sigvelo.css";
16
+ import "@mcp-b/web-components/components/text-field/text-field.js";
17
+ import "@mcp-b/web-components/components/button/button.js";
18
+ ```
11
19
 
12
- ## What's in the box?
20
+ ```html
21
+ <form>
22
+ <sigvelo-text-field name="title" label="Title" required></sigvelo-text-field>
23
+ <sigvelo-button type="submit">Save</sigvelo-button>
24
+ </form>
25
+ ```
13
26
 
14
- - 🧰 A collection of high quality components for building beautiful, accessible, and consistent user interfaces
15
- - 🚀 An [optional] opinionated CSS reset to kick off new projects with beautiful base styles
16
- - 🎨 Extreme customizability using plain ol' CSS
17
- - 🐭 A built-in autoloader that detects components in your HTML — even ones you add dynamically — and loads them on the fly!
27
+ Individual entrypoints register their dependencies and default English copy.
28
+ The package root registers the entire core library; prefer individual imports
29
+ when you only need a few controls. Additional translations are opt-in:
18
30
 
19
- ## Where can I…?
31
+ ```ts
32
+ import "@mcp-b/web-components/translations/es.js";
33
+ document.documentElement.lang = "es";
34
+ ```
20
35
 
21
- - [Get started using Sigvelo](https://design-system.sigvelo.com/)
22
- - [Get help and support](https://design-system.sigvelo.com/support)
23
- - [Request a feature](https://github.com/omarkawach/sigvelo/discussions/categories/feature-requests)
24
- - [Report a bug](https://github.com/omarkawach/sigvelo/issues/new/choose)
25
- - [Ask for help](https://design-system.sigvelo.com/support)
26
- - [Star the project on GitHub](https://github.com/omarkawach/sigvelo/stargazers)
36
+ ## One token layer
27
37
 
28
- ## Developer instructions
38
+ The theme entrypoint loads `@mcp-b/design-tokens` through `@mcp-b/wc-support`.
39
+ It does not require React CSS or maintain a second palette.
29
40
 
30
- To launch the development server, use the following commands.
41
+ - No `data-theme` attribute means follow the operating system. Use
42
+ `data-theme="light"` or `data-theme="dark"` for an explicit root or subtree override.
43
+ - Set `data-preset` on the document root for an accent palette and `data-style`
44
+ for a design-language preset. Removing the attribute restores the default.
45
+ - Shared controls consume `--sigvelo-control-*` for their size, padding, icons,
46
+ and line height, and `--sigvelo-focus-*` for keyboard focus.
47
+ - Add a shared semantic token in `packages/design-tokens` only when an existing
48
+ token cannot express the need. Component-specific hooks remain local.
31
49
 
32
- ```sh
33
- npm i
34
- npm run start
35
- ```
50
+ React owns the contracts explicitly declared in
51
+ [`design-system.catalog.json`](./design-system.catalog.json). Other name
52
+ overlaps are review inventory, not a promise of API parity.
53
+
54
+ ## Compose with native boundaries
55
+
56
+ Use named slots for caller-owned content and documented `::part()` hooks for
57
+ internal styling. Inherited custom properties carry the shared theme through
58
+ shadow roots; document selectors do not style arbitrary internals. See
59
+ [Lit shadow DOM composition](https://lit.dev/docs/components/shadow-dom/) and
60
+ [Lit styling](https://lit.dev/docs/components/styles/).
61
+
62
+ Keep native buttons, links, inputs, and form association in the owning control.
63
+ An ancestor fieldset's disabled state must not overwrite a control's own
64
+ `disabled` attribute. Components must remain usable after disconnecting and
65
+ reconnecting; initialize per-connection resources and release them on disconnect.
66
+ See [Lit lifecycle](https://lit.dev/docs/components/lifecycle/).
36
67
 
37
- This will launch a browser showing the docs. The browser will reload as you make changes to the project. When you're ready to create a production build, use the following command.
68
+ Custom tags and events use the `sigvelo-` prefix. Dispatch user-facing events
69
+ through the shared event classes so bubbling, composition, and typed payloads
70
+ remain consistent. Avoid copying the stateful localization or runtime registries
71
+ into domain packages.
72
+
73
+ ## Package boundaries
74
+
75
+ | Package | Owns |
76
+ | -------------------------------------------------------------- | --------------------------------------------------------- |
77
+ | `design-tokens` | Shared tokens, themes, and presets |
78
+ | `wc-support` | Lit base classes, events, localization, and shared styles |
79
+ | `web-components` | Core elements and the shared Lit Storybook |
80
+ | `geo-support`, `geo-leaflet`, `geo-maplibre`, `geo-openlayers` | Shared map contracts and engine-specific renderers |
81
+ | `interactive-components`, `aec-components`, `viz-components` | Editors, IFC/3D, and charts |
82
+
83
+ Rendering engines stay peer dependencies of the packages that use them. Import
84
+ domain elements from their owning package; core controls do not require map or
85
+ 3D engines. Editors additionally load
86
+ `@mcp-b/interactive-components/themes/interactive.css` for their syntax tokens.
87
+
88
+ ## Develop and verify
89
+
90
+ From the repository root:
38
91
 
39
92
  ```sh
40
- npm run build
93
+ vp install
94
+ vp run @mcp-b/web-components#storybook
41
95
  ```
42
96
 
43
- The `dist` folder will contain the files you want.
44
-
45
- There are a number of commands you can use to lint and test the library. For a full list of them, run the following command.
97
+ This Storybook includes every Lit package and runs accessibility checks on its
98
+ stories. Root unit tests, React stories, and Lit stories are separate suites:
46
99
 
47
100
  ```sh
48
- npm run
101
+ vp run test:browser:ci
102
+ vp check
103
+ vp run audit:tokens
104
+ vp run audit:css-recipes
105
+ vp run audit:modern-web-guidance
106
+ vp run catalog:check
107
+ vp run validate:packages
49
108
  ```
109
+
110
+ The browser runner executes all three suites. Domain package test scripts
111
+ delegate to the shared Lit Storybook; they do not own standalone unit suites.
112
+ `wc-support` also has unit and browser regression tests.
@@ -1,5 +1,5 @@
1
1
  import { t as __decorate } from "./decorate-DcF3lt7P.js";
2
- import { t as SigveloDialog } from "./dialog-Cx46HMaZ.js";
2
+ import { t as SigveloDialog } from "./dialog-Ddvyn2d_.js";
3
3
  import { css, html } from "lit";
4
4
  import { property } from "lit/decorators.js";
5
5
  import hostStyles from "@mcp-b/wc-support/styles/host.styles";
@@ -1,6 +1,6 @@
1
1
  import "./icon-Df0H7LYB.js";
2
2
  import { t as __decorate } from "./decorate-DcF3lt7P.js";
3
- import "./spinner-C04Dmc0H.js";
3
+ import "./spinner-C9lQARtQ.js";
4
4
  import { css } from "lit";
5
5
  import { property } from "lit/decorators.js";
6
6
  import hostStyles from "@mcp-b/wc-support/styles/host.styles";
@@ -26,22 +26,24 @@ var button_styles_default = css`
26
26
  align-items: center;
27
27
  justify-content: center;
28
28
  width: 100%;
29
- gap: 0.4em;
29
+ gap: var(--sigvelo-density-compact-control-gap);
30
+ padding-block: 0;
30
31
  border: none;
31
32
  border-radius: var(--sigvelo-radius-md);
32
33
  background: none;
33
34
  font: inherit;
34
35
  font-weight: var(--sigvelo-font-weight-semibold);
36
+ line-height: var(--sigvelo-control-line-height-sm);
35
37
  text-decoration: none;
36
38
  vertical-align: middle;
37
39
  white-space: nowrap;
38
40
  cursor: inherit;
39
41
  touch-action: manipulation;
40
42
  transition:
41
- var(--sigvelo-motion-duration-interaction) color ease,
42
- var(--sigvelo-motion-duration-interaction) border-color ease,
43
- var(--sigvelo-motion-duration-interaction) background-color ease,
44
- var(--sigvelo-motion-duration-interaction) translate ease;
43
+ var(--sigvelo-motion-duration-interaction) color var(--sigvelo-motion-ease-change),
44
+ var(--sigvelo-motion-duration-interaction) border-color var(--sigvelo-motion-ease-change),
45
+ var(--sigvelo-motion-duration-interaction) background-color var(--sigvelo-motion-ease-change),
46
+ var(--sigvelo-motion-duration-presence) translate var(--sigvelo-ease-press);
45
47
  user-select: none;
46
48
  -webkit-user-select: none;
47
49
 
@@ -60,33 +62,48 @@ var button_styles_default = css`
60
62
 
61
63
  /* Sizes */
62
64
  &.xs {
63
- min-height: var(--sigvelo-control-height-xs);
64
- padding-inline: 0.85em;
65
+ --button-height: var(--sigvelo-control-height-xs);
66
+ --button-icon-size: var(--sigvelo-control-icon-size-xs);
67
+ min-height: var(--button-height);
68
+ padding-inline: var(--sigvelo-control-padding-inline-xs);
65
69
  font-size: var(--sigvelo-control-text-xs);
70
+ line-height: var(--sigvelo-control-line-height-xs);
66
71
  }
67
72
 
68
73
  &.sm {
69
- min-height: var(--sigvelo-control-height-sm);
70
- padding-inline: 1em;
74
+ --button-height: var(--sigvelo-control-height-sm);
75
+ --button-icon-size: var(--sigvelo-control-icon-size-sm);
76
+ min-height: var(--button-height);
77
+ padding-inline: var(--sigvelo-control-padding-inline-sm);
71
78
  font-size: var(--sigvelo-control-text-sm);
79
+ line-height: var(--sigvelo-control-line-height-sm);
72
80
  }
73
81
 
74
82
  &.md {
75
- min-height: var(--sigvelo-control-height-md);
76
- padding-inline: 1.25em;
83
+ --button-height: var(--sigvelo-control-height-md);
84
+ --button-icon-size: var(--sigvelo-control-icon-size-md);
85
+ min-height: var(--button-height);
86
+ padding-inline: var(--sigvelo-control-padding-inline-md);
77
87
  font-size: var(--sigvelo-control-text-md);
88
+ line-height: var(--sigvelo-control-line-height-md);
78
89
  }
79
90
 
80
91
  &.lg {
81
- min-height: var(--sigvelo-control-height-lg);
82
- padding-inline: 1.33em;
92
+ --button-height: var(--sigvelo-control-height-lg);
93
+ --button-icon-size: var(--sigvelo-control-icon-size-lg);
94
+ min-height: var(--button-height);
95
+ padding-inline: var(--sigvelo-control-padding-inline-lg);
83
96
  font-size: var(--sigvelo-control-text-lg);
97
+ line-height: var(--sigvelo-control-line-height-lg);
84
98
  }
85
99
 
86
100
  &.xl {
87
- min-height: var(--sigvelo-control-height-xl);
88
- padding-inline: 1.5em;
101
+ --button-height: var(--sigvelo-control-height-xl);
102
+ --button-icon-size: var(--sigvelo-control-icon-size-xl);
103
+ min-height: var(--button-height);
104
+ padding-inline: var(--sigvelo-control-padding-inline-xl);
89
105
  font-size: var(--sigvelo-control-text-xl);
106
+ line-height: var(--sigvelo-control-line-height-xl);
90
107
  }
91
108
 
92
109
  /* Normal buttons */
@@ -97,17 +114,14 @@ var button_styles_default = css`
97
114
  color: var(--sigvelo-color-neutral-text-on-subtle);
98
115
 
99
116
  @media (hover: hover) {
100
- &:hover:not(.disabled, [aria-pressed="true"]) {
101
- background-color: color-mix(in oklab, var(--sigvelo-color-neutral-bg-subtle), black 5%);
117
+ &:hover:not(.disabled, [aria-pressed="true"], :active) {
118
+ background-color: var(--sigvelo-color-neutral-bg-hover);
102
119
  }
103
120
  }
104
121
 
122
+ &:active:not(.disabled),
105
123
  &[aria-pressed="true"] {
106
- background-color: color-mix(
107
- in oklab,
108
- var(--sigvelo-color-neutral-bg-subtle),
109
- light-dark(black, white) 7.5%
110
- );
124
+ background-color: var(--sigvelo-color-neutral-bg-press);
111
125
  }
112
126
  }
113
127
 
@@ -117,17 +131,14 @@ var button_styles_default = css`
117
131
  color: var(--sigvelo-color-primary-text-on-bg);
118
132
 
119
133
  @media (hover: hover) {
120
- &:hover:not(.disabled, [aria-pressed="true"]) {
121
- background-color: color-mix(in oklab, var(--sigvelo-color-primary-bg), black 5%);
134
+ &:hover:not(.disabled, [aria-pressed="true"], :active) {
135
+ background-color: var(--sigvelo-color-primary-bg-hover);
122
136
  }
123
137
  }
124
138
 
139
+ &:active:not(.disabled),
125
140
  &[aria-pressed="true"] {
126
- background-color: color-mix(
127
- in oklab,
128
- var(--sigvelo-color-primary-bg),
129
- light-dark(black, white) 7.5%
130
- );
141
+ background-color: var(--sigvelo-color-primary-bg-press);
131
142
  }
132
143
  }
133
144
 
@@ -137,17 +148,14 @@ var button_styles_default = css`
137
148
  color: var(--sigvelo-color-danger-text-on-bg);
138
149
 
139
150
  @media (hover: hover) {
140
- &:hover:not(.disabled, [aria-pressed="true"]) {
141
- background-color: color-mix(in oklab, var(--sigvelo-color-danger-bg), black 5%);
151
+ &:hover:not(.disabled, [aria-pressed="true"], :active) {
152
+ background-color: var(--sigvelo-color-danger-bg-hover);
142
153
  }
143
154
  }
144
155
 
156
+ &:active:not(.disabled),
145
157
  &[aria-pressed="true"] {
146
- background-color: color-mix(
147
- in oklab,
148
- var(--sigvelo-color-danger-bg),
149
- light-dark(black, white) 7.5%
150
- );
158
+ background-color: var(--sigvelo-color-danger-bg-press);
151
159
  }
152
160
  }
153
161
  }
@@ -207,6 +215,16 @@ var button_styles_default = css`
207
215
  }
208
216
  }
209
217
 
218
+ &.ghost.destructive {
219
+ color: var(--sigvelo-color-danger-text);
220
+
221
+ @media (hover: hover) {
222
+ &:hover:not(.disabled) {
223
+ background-color: color-mix(in oklab, transparent, var(--sigvelo-color-danger-bg) 12.5%);
224
+ }
225
+ }
226
+ }
227
+
210
228
  /* Raised surface buttons */
211
229
  &.surface {
212
230
  background-color: var(--sigvelo-color-surface-raised);
@@ -232,25 +250,10 @@ var button_styles_default = css`
232
250
  }
233
251
  }
234
252
 
235
- /* Icon buttons */
253
+ /* Icon buttons share the control's height and icon size. */
236
254
  &.icon {
237
- padding-inline: 0.75em;
238
-
239
- &.xs {
240
- padding-inline: 0.525em;
241
- }
242
-
243
- &.sm {
244
- padding-inline: 0.65em;
245
- }
246
-
247
- &.lg {
248
- padding-inline: 0.675em;
249
- }
250
-
251
- &.xl {
252
- padding-inline: 0.55em;
253
- }
255
+ width: var(--button-height);
256
+ padding-inline: 0;
254
257
  }
255
258
 
256
259
  /* Pills */
@@ -285,7 +288,7 @@ var button_styles_default = css`
285
288
  cursor: not-allowed;
286
289
 
287
290
  #label {
288
- visibility: hidden;
291
+ opacity: 0;
289
292
  }
290
293
  }
291
294
 
@@ -301,8 +304,8 @@ var button_styles_default = css`
301
304
  font-size: 1.25em;
302
305
  }
303
306
 
304
- /* Visually hidden label */
305
- slot[name="label"] {
307
+ /* Opacity needs a box; the default slot display of contents ignores it. */
308
+ #label {
306
309
  display: inline;
307
310
  }
308
311
  }
@@ -341,15 +344,39 @@ var button_styles_default = css`
341
344
  margin-inline-start: calc(var(--sigvelo-border-width) * -2);
342
345
  }
343
346
 
347
+ @media (forced-colors: active) {
348
+ #button {
349
+ border: var(--sigvelo-border-style) var(--sigvelo-border-width) ButtonText;
350
+
351
+ &.ghost,
352
+ &.link {
353
+ border-color: transparent;
354
+ }
355
+
356
+ &.disabled:not(.loading),
357
+ &.disabled.loading {
358
+ border-color: GrayText;
359
+ color: GrayText;
360
+ opacity: 1;
361
+ }
362
+ }
363
+ }
364
+
365
+ @media (prefers-reduced-motion: reduce) {
366
+ #button:active:not(.disabled) {
367
+ translate: none;
368
+ }
369
+ }
370
+
344
371
  /* Icons */
345
372
  ::slotted(sigvelo-icon) {
346
- font-size: 1.25em;
373
+ font-size: var(--button-icon-size);
347
374
  stroke-width: 1.75px;
348
375
  }
349
376
 
350
377
  ::slotted(svg) {
351
- width: 1.25em;
352
- height: 1.25em;
378
+ width: var(--button-icon-size);
379
+ height: var(--button-icon-size);
353
380
  }
354
381
  `;
355
382
  //#endregion
@@ -440,7 +467,7 @@ var button_styles_default = css`
440
467
  * </sigvelo-button>
441
468
  * ```
442
469
  *
443
- * **Note:** Because link buttons become anchors, they cannot be used with `disabled` or `loading`.
470
+ * **Note:** Link buttons support `disabled`; `loading`, toggle state, and form actions apply only to buttons.
444
471
  *
445
472
  * @example Changing the width
446
473
  * To change a button's width, use the CSS `width` property.
@@ -637,16 +664,33 @@ var SigveloButton = class extends SigveloFormControlElement {
637
664
  this.styles = [hostStyles, button_styles_default];
638
665
  }
639
666
  get focusableAnchor() {
640
- return this.shadowRoot.querySelector("button");
667
+ return this.shadowRoot.querySelector("#button");
668
+ }
669
+ connectedCallback() {
670
+ super.connectedCallback();
671
+ this.syncLongPress();
672
+ }
673
+ disconnectedCallback() {
674
+ super.disconnectedCallback();
675
+ this.longPress?.stop();
641
676
  }
642
- firstUpdated() {
643
- const button = this.shadowRoot.getElementById("button");
644
- this.longPress = new LongPress(button, { eventName: "sigvelo-long-press" });
645
- this.longPress.start();
677
+ formDisabledCallback() {
678
+ super.formDisabledCallback();
679
+ this.syncLongPress();
680
+ }
681
+ syncLongPress() {
682
+ if (this.isConnected && !this.effectiveDisabled && !(this.loading && typeof this.href !== "string")) this.longPress?.start();
683
+ else this.longPress?.stop();
646
684
  }
647
685
  updated(changedProperties) {
648
- if (changedProperties.has("disabled")) this.customStates.set("disabled", this.disabled);
649
- if (changedProperties.has("loading")) this.customStates.set("loading", this.loading);
686
+ if (!this.longPress || changedProperties.has("href")) {
687
+ this.longPress?.stop();
688
+ this.longPress = new LongPress(this.focusableAnchor, { eventName: "sigvelo-long-press" });
689
+ }
690
+ this.syncLongPress();
691
+ if (changedProperties.has("disabled")) this.customStates.set("disabled", this.effectiveDisabled);
692
+ if (changedProperties.has("loading") || changedProperties.has("href")) this.customStates.set("loading", this.loading && typeof this.href !== "string");
693
+ if (changedProperties.has("toggle") || changedProperties.has("href") || changedProperties.has("type")) this.customStates.set("toggled", this.toggle === "on" && typeof this.href !== "string" && this.type !== "submit");
650
694
  }
651
695
  handleBlur() {
652
696
  this.customStates.set("focused", false);
@@ -657,15 +701,13 @@ var SigveloButton = class extends SigveloFormControlElement {
657
701
  this.dispatchEvent(new SigveloFocusEvent());
658
702
  }
659
703
  handleClick(event) {
660
- if (this.disabled || this.loading) {
704
+ if (this.effectiveDisabled || typeof this.href !== "string" && this.loading) {
661
705
  event.preventDefault();
662
706
  event.stopImmediatePropagation();
663
707
  return;
664
708
  }
665
- if (this.toggle !== void 0) {
666
- this.toggle = this.toggle === "on" ? "off" : "on";
667
- this.customStates.set("toggled", this.toggle === "on");
668
- }
709
+ if (typeof this.href === "string") return;
710
+ if (this.toggle !== void 0 && this.type !== "submit") this.toggle = this.toggle === "on" ? "off" : "on";
669
711
  if (this.type === "reset" && this.internals.form) {
670
712
  this.internals.form.reset();
671
713
  return;
@@ -699,7 +741,7 @@ var SigveloButton = class extends SigveloFormControlElement {
699
741
  }
700
742
  render() {
701
743
  const isLink = typeof this.href === "string";
702
- const isDisabled = this.disabled || !isLink && this.loading;
744
+ const isDisabled = this.effectiveDisabled || !isLink && this.loading;
703
745
  const isLoading = !isLink && this.loading;
704
746
  const isSubmit = this.type === "submit";
705
747
  const isToggle = this.toggle !== void 0 && !isLink && !isSubmit;
@@ -728,9 +770,11 @@ var SigveloButton = class extends SigveloFormControlElement {
728
770
  loading: isLoading
729
771
  })}
730
772
  type=${ifDefined(isLink ? void 0 : this.type)}
731
- ?disabled=${ifDefined(isLink ? void 0 : this.disabled)}
773
+ ?disabled=${!isLink && isDisabled}
774
+ aria-disabled=${ifDefined(isLink && isDisabled ? "true" : void 0)}
775
+ aria-busy=${ifDefined(isLoading ? "true" : void 0)}
732
776
  value=${ifDefined(isLink ? void 0 : this.value)}
733
- href=${ifDefined(isLink && !this.disabled ? this.href : void 0)}
777
+ href=${ifDefined(isLink && !this.effectiveDisabled ? this.href : void 0)}
734
778
  target=${ifDefined(isLink ? this.target : void 0)}
735
779
  download=${ifDefined(isLink ? this.download : void 0)}
736
780
  rel=${ifDefined(isLink && this.rel ? this.rel : void 0)}
@@ -88,7 +88,7 @@ import { SigveloFormControlElement } from "@mcp-b/wc-support/base/sigvelo-elemen
88
88
  * </sigvelo-button>
89
89
  * ```
90
90
  *
91
- * **Note:** Because link buttons become anchors, they cannot be used with `disabled` or `loading`.
91
+ * **Note:** Link buttons support `disabled`; `loading`, toggle state, and form actions apply only to buttons.
92
92
  *
93
93
  * @example Changing the width
94
94
  * To change a button's width, use the CSS `width` property.
@@ -272,7 +272,7 @@ declare class SigveloButton extends SigveloFormControlElement {
272
272
  static styles: CSSResultGroup;
273
273
  protected internals: ElementInternals;
274
274
  private longPress;
275
- protected get focusableAnchor(): HTMLButtonElement;
275
+ protected get focusableAnchor(): HTMLElement;
276
276
  /** Determines the button's variant. */
277
277
  variant: "normal" | "surface" | "outline" | "ghost" | "link";
278
278
  /** The semantic color intent of the button. */
@@ -338,7 +338,10 @@ declare class SigveloButton extends SigveloFormControlElement {
338
338
  * absorb the literals and offer no suggestions at all.
339
339
  */
340
340
  formTarget: "_self" | "_blank" | "_parent" | "_top" | (string & {}) | undefined;
341
- firstUpdated(): void;
341
+ connectedCallback(): void;
342
+ disconnectedCallback(): void;
343
+ formDisabledCallback(): void;
344
+ private syncLongPress;
342
345
  updated(changedProperties: PropertyValues<this>): void;
343
346
  private handleBlur;
344
347
  private handleFocus;
@@ -324,19 +324,13 @@ declare class SigveloCheckbox extends SigveloFormControlElement {
324
324
  * Makes the checkbox required. Form submission will not be allowed until the checkbox is checked.
325
325
  */
326
326
  required: boolean;
327
- connectedCallback(): void;
328
- disconnectedCallback(): void;
329
327
  updated(changedProperties: PropertyValues<this>): void;
330
- /** @internal Called when a containing fieldset is disabled. */
331
- formDisabledCallback(isDisabled: boolean): void;
332
328
  /** @internal Called when the form is reset. */
333
329
  formResetCallback(): void;
334
- private handleClick;
335
330
  private handleBlur;
336
331
  private handleChange;
337
332
  private handleInput;
338
333
  private handleFocus;
339
- private handleHostInvalid;
340
334
  /** Sets the form control's validity */
341
335
  private updateValidity;
342
336
  /** Sets focus to the checkbox. */