@sondor-technology/sondor-components 1.0.0-1165-initial-setup.11 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/package.json +2 -3
  2. package/src/components/alert/alert.ts +100 -100
  3. package/src/components/badge/badge.ts +96 -96
  4. package/src/components/breadcrumb/breadcrumb.ts +98 -98
  5. package/src/components/button/button.ts +281 -281
  6. package/src/components/button-group/button-group.ts +67 -67
  7. package/src/components/card/card.ts +52 -52
  8. package/src/components/checkbox/checkbox.ts +238 -238
  9. package/src/components/code-block/code-block.ts +256 -256
  10. package/src/components/content-card/content-card.ts +133 -133
  11. package/src/components/divider/divider.ts +68 -68
  12. package/src/components/drawer/drawer.ts +217 -217
  13. package/src/components/field/field.ts +30 -30
  14. package/src/components/footer/footer.ts +58 -58
  15. package/src/components/form/form-step.ts +32 -32
  16. package/src/components/form/form.ts +376 -376
  17. package/src/components/grid/grid-row.ts +75 -75
  18. package/src/components/grid/grid.ts +36 -36
  19. package/src/components/icon/icon-paths.ts +124 -124
  20. package/src/components/icon/icon.ts +82 -82
  21. package/src/components/input/input.ts +248 -248
  22. package/src/components/link/link.ts +97 -97
  23. package/src/components/metadata/metadata.ts +66 -66
  24. package/src/components/modal/modal.ts +158 -158
  25. package/src/components/page-layout/page-layout.ts +704 -704
  26. package/src/components/radio/radio.ts +142 -142
  27. package/src/components/radio-group/radio-group.ts +157 -157
  28. package/src/components/router/router.ts +46 -46
  29. package/src/components/select/select.ts +161 -161
  30. package/src/components/skeleton/skeleton.ts +67 -67
  31. package/src/components/switch/switch.ts +181 -181
  32. package/src/components/table/data-table.ts +556 -556
  33. package/src/components/table/table.ts +153 -153
  34. package/src/components/tabs/tab-panel.ts +30 -30
  35. package/src/components/tabs/tab.ts +76 -76
  36. package/src/components/tabs/tabs.ts +88 -88
  37. package/src/components/textarea/textarea.ts +215 -215
  38. package/src/components/theme-toggle/theme-toggle.ts +131 -131
  39. package/src/components/vertical-nav/vertical-nav-group.ts +96 -96
  40. package/src/components/vertical-nav/vertical-nav-item.ts +49 -49
  41. package/src/styles/globals.css +58 -58
  42. package/src/styles/index.css +80 -80
  43. package/src/styles/reset.ts +50 -50
  44. package/src/styles/theme.css +58 -58
  45. package/src/styles/typography.css +25 -25
  46. package/tsconfig.json +15 -15
  47. package/README.md +0 -8
  48. package/dist/components/alert/alert.d.ts +0 -13
  49. package/dist/components/alert/alert.d.ts.map +0 -1
  50. package/dist/components/alert/alert.js +0 -105
  51. package/dist/components/badge/badge.d.ts +0 -13
  52. package/dist/components/badge/badge.d.ts.map +0 -1
  53. package/dist/components/badge/badge.js +0 -101
  54. package/dist/components/breadcrumb/breadcrumb.d.ts +0 -19
  55. package/dist/components/breadcrumb/breadcrumb.d.ts.map +0 -1
  56. package/dist/components/breadcrumb/breadcrumb.js +0 -99
  57. package/dist/components/button/button.d.ts +0 -23
  58. package/dist/components/button/button.d.ts.map +0 -1
  59. package/dist/components/button/button.js +0 -304
  60. package/dist/components/button-group/button-group.d.ts +0 -6
  61. package/dist/components/button-group/button-group.d.ts.map +0 -1
  62. package/dist/components/button-group/button-group.js +0 -74
  63. package/dist/components/card/card.d.ts +0 -11
  64. package/dist/components/card/card.d.ts.map +0 -1
  65. package/dist/components/card/card.js +0 -54
  66. package/dist/components/checkbox/checkbox.d.ts +0 -28
  67. package/dist/components/checkbox/checkbox.d.ts.map +0 -1
  68. package/dist/components/checkbox/checkbox.js +0 -247
  69. package/dist/components/code-block/code-block.d.ts +0 -20
  70. package/dist/components/code-block/code-block.d.ts.map +0 -1
  71. package/dist/components/code-block/code-block.js +0 -260
  72. package/dist/components/content-card/content-card.d.ts +0 -13
  73. package/dist/components/content-card/content-card.d.ts.map +0 -1
  74. package/dist/components/content-card/content-card.js +0 -140
  75. package/dist/components/divider/divider.d.ts +0 -16
  76. package/dist/components/divider/divider.d.ts.map +0 -1
  77. package/dist/components/divider/divider.js +0 -82
  78. package/dist/components/drawer/drawer.d.ts +0 -22
  79. package/dist/components/drawer/drawer.d.ts.map +0 -1
  80. package/dist/components/drawer/drawer.js +0 -226
  81. package/dist/components/field/field.d.ts +0 -11
  82. package/dist/components/field/field.d.ts.map +0 -1
  83. package/dist/components/field/field.js +0 -32
  84. package/dist/components/footer/footer.d.ts +0 -6
  85. package/dist/components/footer/footer.d.ts.map +0 -1
  86. package/dist/components/footer/footer.js +0 -65
  87. package/dist/components/form/form-step.d.ts +0 -13
  88. package/dist/components/form/form-step.d.ts.map +0 -1
  89. package/dist/components/form/form-step.js +0 -41
  90. package/dist/components/form/form.d.ts +0 -25
  91. package/dist/components/form/form.d.ts.map +0 -1
  92. package/dist/components/form/form.js +0 -358
  93. package/dist/components/grid/grid-row.d.ts +0 -17
  94. package/dist/components/grid/grid-row.d.ts.map +0 -1
  95. package/dist/components/grid/grid-row.js +0 -92
  96. package/dist/components/grid/grid.d.ts +0 -13
  97. package/dist/components/grid/grid.d.ts.map +0 -1
  98. package/dist/components/grid/grid.js +0 -42
  99. package/dist/components/icon/icon-paths.d.ts +0 -116
  100. package/dist/components/icon/icon-paths.d.ts.map +0 -1
  101. package/dist/components/icon/icon-paths.js +0 -121
  102. package/dist/components/icon/icon.d.ts +0 -16
  103. package/dist/components/icon/icon.d.ts.map +0 -1
  104. package/dist/components/icon/icon.js +0 -95
  105. package/dist/components/input/input.d.ts +0 -31
  106. package/dist/components/input/input.d.ts.map +0 -1
  107. package/dist/components/input/input.js +0 -268
  108. package/dist/components/link/link.d.ts +0 -16
  109. package/dist/components/link/link.d.ts.map +0 -1
  110. package/dist/components/link/link.js +0 -116
  111. package/dist/components/metadata/metadata.d.ts +0 -18
  112. package/dist/components/metadata/metadata.d.ts.map +0 -1
  113. package/dist/components/metadata/metadata.js +0 -71
  114. package/dist/components/modal/modal.d.ts +0 -24
  115. package/dist/components/modal/modal.d.ts.map +0 -1
  116. package/dist/components/modal/modal.js +0 -163
  117. package/dist/components/page-layout/page-layout.d.ts +0 -46
  118. package/dist/components/page-layout/page-layout.d.ts.map +0 -1
  119. package/dist/components/page-layout/page-layout.js +0 -697
  120. package/dist/components/radio/radio.d.ts +0 -16
  121. package/dist/components/radio/radio.d.ts.map +0 -1
  122. package/dist/components/radio/radio.js +0 -152
  123. package/dist/components/radio-group/radio-group.d.ts +0 -27
  124. package/dist/components/radio-group/radio-group.d.ts.map +0 -1
  125. package/dist/components/radio-group/radio-group.js +0 -161
  126. package/dist/components/router/router.d.ts +0 -7
  127. package/dist/components/router/router.d.ts.map +0 -1
  128. package/dist/components/router/router.js +0 -37
  129. package/dist/components/select/select.d.ts +0 -16
  130. package/dist/components/select/select.d.ts.map +0 -1
  131. package/dist/components/select/select.js +0 -172
  132. package/dist/components/skeleton/skeleton.d.ts +0 -17
  133. package/dist/components/skeleton/skeleton.d.ts.map +0 -1
  134. package/dist/components/skeleton/skeleton.js +0 -78
  135. package/dist/components/switch/switch.d.ts +0 -25
  136. package/dist/components/switch/switch.d.ts.map +0 -1
  137. package/dist/components/switch/switch.js +0 -185
  138. package/dist/components/table/data-table.d.ts +0 -72
  139. package/dist/components/table/data-table.d.ts.map +0 -1
  140. package/dist/components/table/data-table.js +0 -551
  141. package/dist/components/table/table.d.ts +0 -22
  142. package/dist/components/table/table.d.ts.map +0 -1
  143. package/dist/components/table/table.js +0 -167
  144. package/dist/components/tabs/tab-panel.d.ts +0 -8
  145. package/dist/components/tabs/tab-panel.d.ts.map +0 -1
  146. package/dist/components/tabs/tab-panel.js +0 -46
  147. package/dist/components/tabs/tab.d.ts +0 -9
  148. package/dist/components/tabs/tab.d.ts.map +0 -1
  149. package/dist/components/tabs/tab.js +0 -91
  150. package/dist/components/tabs/tabs.d.ts +0 -14
  151. package/dist/components/tabs/tabs.d.ts.map +0 -1
  152. package/dist/components/tabs/tabs.js +0 -85
  153. package/dist/components/textarea/textarea.d.ts +0 -36
  154. package/dist/components/textarea/textarea.d.ts.map +0 -1
  155. package/dist/components/textarea/textarea.js +0 -231
  156. package/dist/components/theme-toggle/theme-toggle.d.ts +0 -15
  157. package/dist/components/theme-toggle/theme-toggle.d.ts.map +0 -1
  158. package/dist/components/theme-toggle/theme-toggle.js +0 -130
  159. package/dist/components/vertical-nav/vertical-nav-group.d.ts +0 -9
  160. package/dist/components/vertical-nav/vertical-nav-group.d.ts.map +0 -1
  161. package/dist/components/vertical-nav/vertical-nav-group.js +0 -111
  162. package/dist/components/vertical-nav/vertical-nav-item.d.ts +0 -8
  163. package/dist/components/vertical-nav/vertical-nav-item.d.ts.map +0 -1
  164. package/dist/components/vertical-nav/vertical-nav-item.js +0 -65
  165. package/dist/styles/index.css +0 -171
  166. package/dist/styles/reset.d.ts +0 -2
  167. package/dist/styles/reset.d.ts.map +0 -1
  168. package/dist/styles/reset.js +0 -50
@@ -1,281 +1,281 @@
1
- import {LitElement, html, css, nothing} from "lit";
2
- import {customElement, property} from "lit/decorators.js";
3
- import {resetStyles} from "../../styles/reset.js";
4
-
5
- export type ButtonVariant = "primary" | "secondary" | "outline";
6
- export type ButtonSize = "sm" | "md" | "lg";
7
- export type ButtonColor = "primary" | "error" | "success" | "warning" | "info";
8
-
9
- @customElement("st-button")
10
- export class StButton extends LitElement {
11
- @property({type: String}) href?: string;
12
- @property({type: String}) target: "_blank" | "_self" = "_self";
13
- @property({type: Boolean, reflect: true}) disabled = false;
14
- @property({type: Boolean, reflect: true}) loading = false;
15
- @property({type: String, reflect: true}) variant: ButtonVariant = "primary";
16
- @property({type: String, reflect: true}) size: ButtonSize = "md";
17
- @property({type: String, reflect: true}) color: ButtonColor = "primary";
18
- @property({ type: Boolean, reflect: true }) active = false;
19
- @property({ type: String, attribute: 'aria-label' }) ariaLabel: string | null = null;
20
-
21
- static styles = [
22
- resetStyles,
23
- css`
24
- :host {
25
- /* ==========================================================
26
- 1. Base Palette (Defaults to Primary Theme)
27
- ========================================================== */
28
- --_palette-base: var(--st-color-primary);
29
- --_palette-hover: var(--st-color-primary-hover);
30
- --_palette-surface: var(--st-color-surface);
31
- --_palette-surface-hover: var(--st-color-border);
32
-
33
- --_palette-text-on-base: var(--st-color-surface);
34
- --_palette-text-on-surface: var(--st-color-text);
35
-
36
- /* Sizing Tokens */
37
- --_btn-padding: var(--st-spacing-sm) var(--st-spacing-md);
38
- --_btn-font-size: var(--st-font-size-sm);
39
- --_btn-radius: 4px;
40
- --_btn-gap: var(--st-spacing-sm);
41
-
42
- display: inline-block;
43
- }
44
-
45
- /* ==========================================================
46
- 2. Semantic Color Overrides (Swaps the active palette)
47
- ========================================================== */
48
- :host([color="error"]) {
49
- --_palette-base: var(--st-color-error);
50
- --_palette-hover: color-mix(in srgb, var(--st-color-error), black 15%);
51
- --_palette-surface: var(--st-color-error-bg);
52
- --_palette-surface-hover: color-mix(in srgb, var(--st-color-error-bg), black 10%);
53
- --_palette-text-on-base: var(--st-white); /* Force white text */
54
- --_palette-text-on-surface: var(--st-color-error);
55
- }
56
-
57
- :host([color="success"]) {
58
- --_palette-base: var(--st-color-success);
59
- --_palette-hover: color-mix(in srgb, var(--st-color-success), black 15%);
60
- --_palette-surface: var(--st-color-success-bg);
61
- --_palette-surface-hover: color-mix(in srgb, var(--st-color-success-bg), black 10%);
62
- --_palette-text-on-base: var(--st-white);
63
- --_palette-text-on-surface: var(--st-color-success);
64
- }
65
-
66
- :host([color="warning"]) {
67
- --_palette-base: var(--st-color-warning);
68
- --_palette-hover: color-mix(in srgb, var(--st-color-warning), black 15%);
69
- --_palette-surface: var(--st-color-warning-bg);
70
- --_palette-surface-hover: color-mix(in srgb, var(--st-color-warning-bg), black 10%);
71
- --_palette-text-on-base: var(--st-gray-900); /* Amber needs dark text for contrast */
72
- --_palette-text-on-surface: var(--st-color-warning);
73
- }
74
-
75
- :host([color="info"]) {
76
- --_palette-base: var(--st-color-info);
77
- --_palette-hover: color-mix(in srgb, var(--st-color-info), black 15%);
78
- --_palette-surface: var(--st-color-info-bg);
79
- --_palette-surface-hover: color-mix(in srgb, var(--st-color-info-bg), black 10%);
80
- --_palette-text-on-base: var(--st-white);
81
- --_palette-text-on-surface: var(--st-color-info);
82
- }
83
-
84
- /* ==========================================================
85
- 3. Visual Variants (Consumes the active palette)
86
- ========================================================== */
87
-
88
- /* Base (Primary / Solid) */
89
- :host {
90
- --_btn-bg: var(--_palette-base);
91
- --_btn-bg-hover: var(--_palette-hover);
92
- --_btn-text: var(--_palette-text-on-base);
93
- --_btn-border: transparent;
94
- }
95
-
96
- /* Secondary Variant */
97
- :host([variant="secondary"]) {
98
- --_btn-bg: var(--_palette-surface);
99
- --_btn-bg-hover: var(--_palette-surface-hover);
100
- --_btn-text: var(--_palette-text-on-surface);
101
- --_btn-border: transparent;
102
- }
103
-
104
- /* Outline Variant */
105
- :host([variant="outline"]) {
106
- --_btn-bg: transparent;
107
- --_btn-bg-hover: var(--_palette-surface);
108
- --_btn-text: var(--_palette-base);
109
- --_btn-border: var(--_palette-base);
110
- }
111
-
112
- /* ==========================================================
113
- 4. Size Variants
114
- ========================================================== */
115
- :host([size="sm"]) {
116
- --_btn-padding: var(--st-spacing-xs) var(--st-spacing-sm);
117
- --_btn-font-size: var(--st-font-size-xs);
118
- --_btn-radius: 2px;
119
- --_btn-gap: var(--st-spacing-xs);
120
- }
121
-
122
- :host([size="lg"]) {
123
- --_btn-padding: var(--st-spacing-md) var(--st-spacing-lg);
124
- --_btn-font-size: var(--st-font-size-base);
125
- --_btn-radius: 6px;
126
- --_btn-gap: var(--st-spacing-sm);
127
- }
128
-
129
- /* ==========================================================
130
- 5. Base Button Rules
131
- ========================================================== */
132
- .btn {
133
- display: inline-flex;
134
- align-items: center;
135
- justify-content: center;
136
- gap: var(--_btn-gap);
137
-
138
- background-color: var(--_btn-bg);
139
- color: var(--_btn-text);
140
- border: 1px solid var(--_btn-border);
141
- padding: var(--_btn-padding);
142
- font-size: var(--_btn-font-size);
143
- border-radius: var(--_btn-radius);
144
- line-height: 1;
145
-
146
- cursor: pointer;
147
- font-weight: var(--st-font-weight-medium);
148
- transition: all 0.2s ease;
149
- padding: 0.5rem 1rem;
150
-
151
- /* 1. Split the border radius into 4 independent corners */
152
- border-radius: var(--btn-radius-tl, var(--st-radius-md, 0.5rem))
153
- var(--btn-radius-tr, var(--st-radius-md, 0.5rem))
154
- var(--btn-radius-br, var(--st-radius-md, 0.5rem))
155
- var(--btn-radius-bl, var(--st-radius-md, 0.5rem));
156
-
157
- /* 2. Add a hook for the group wrapper to inject a divider line */
158
- box-shadow: var(--btn-divider, none);
159
-
160
- font-weight: 500;
161
- text-decoration: none;
162
- border: 1px solid transparent;
163
- }
164
-
165
- .btn:hover {
166
- color: var(--_btn-text);
167
- background-color: var(--_btn-bg-hover);
168
- }
169
-
170
- /* ==========================================================
171
- Logical Active States (Selected/Toggled)
172
- ========================================================== */
173
- :host([active]) .btn {
174
- filter: brightness(0.9);
175
- box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.2);
176
- border-color: transparent;
177
- color: var(--_btn-text);
178
- background-color: var(--_btn-bg-hover);
179
- }
180
-
181
- :host([active]) .btn[color="primary"] {
182
- filter: brightness(0.85);
183
- box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); /* Inset shadow gives a pressed look */
184
- }
185
-
186
- /* ==========================================================
187
- Focus State (Accessibility)
188
- ========================================================== */
189
- /* focus-visible ensures this only shows for keyboard navigation, not mouse clicks */
190
- .btn:focus-visible {
191
- outline: 2px solid var(--st-color-primary);
192
- outline-offset: 2px;
193
- z-index: 1; /* Pulls the focused button forward if it's in a button group */
194
- }
195
-
196
- /* ==========================================================
197
- Physical Active State (Mouse down)
198
- ========================================================== */
199
- .btn:active {
200
- transform: scale(0.98);
201
- }
202
-
203
- /* Disabled & Loading */
204
- :host([disabled]),
205
- :host([loading]) {
206
- pointer-events: none;
207
- }
208
-
209
- :host([disabled]) button {
210
- opacity: 0.5;
211
- cursor: not-allowed;
212
- }
213
-
214
- :host([loading]) button {
215
- opacity: 0.8;
216
- }
217
-
218
- /* Icons & Spinner */
219
- ::slotted(svg),
220
- svg.spinner {
221
- width: 1.25em;
222
- height: 1.25em;
223
- fill: currentColor;
224
- flex-shrink: 0;
225
- }
226
-
227
- svg.spinner {
228
- animation: st-spin 1s linear infinite;
229
- }
230
-
231
- @keyframes st-spin {
232
- from {
233
- transform: rotate(0deg);
234
- }
235
- to {
236
- transform: rotate(360deg);
237
- }
238
- }
239
- `,
240
- ];
241
-
242
- render() {
243
- const content = html`<slot></slot>`;
244
-
245
- if (this.href) {
246
- return html`<a href="${this.href}" target="${this.target}" class="btn" color="${this.color}" aria-label=${this.ariaLabel || nothing}
247
- >${content}</a
248
- >`;
249
- }
250
-
251
- return html`
252
- <button class="btn" ?disabled=${this.disabled || this.loading}>
253
- ${this.loading
254
- ? html`
255
- <svg class="spinner" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
256
- <path
257
- opacity="0.2"
258
- fill-rule="evenodd"
259
- clip-rule="evenodd"
260
- d="M12 19C15.866 19 19 15.866 19 12C19 8.13401 15.866 5 12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
261
- fill="currentColor"
262
- />
263
- <path
264
- d="M2 12C2 6.47715 6.47715 2 12 2V5C8.13401 5 5 8.13401 5 12H2Z"
265
- fill="currentColor"
266
- />
267
- </svg>
268
- `
269
- : html`<slot name="prefix"></slot>`}
270
- ${content}
271
- <slot name="suffix"></slot>
272
- </button>
273
- `;
274
- }
275
- }
276
-
277
- declare global {
278
- interface HTMLElementTagNameMap {
279
- "st-button": StButton;
280
- }
281
- }
1
+ import {LitElement, html, css, nothing} from "lit";
2
+ import {customElement, property} from "lit/decorators.js";
3
+ import {resetStyles} from "../../styles/reset.js";
4
+
5
+ export type ButtonVariant = "primary" | "secondary" | "outline";
6
+ export type ButtonSize = "sm" | "md" | "lg";
7
+ export type ButtonColor = "primary" | "error" | "success" | "warning" | "info";
8
+
9
+ @customElement("st-button")
10
+ export class StButton extends LitElement {
11
+ @property({type: String}) href?: string;
12
+ @property({type: String}) target: "_blank" | "_self" = "_self";
13
+ @property({type: Boolean, reflect: true}) disabled = false;
14
+ @property({type: Boolean, reflect: true}) loading = false;
15
+ @property({type: String, reflect: true}) variant: ButtonVariant = "primary";
16
+ @property({type: String, reflect: true}) size: ButtonSize = "md";
17
+ @property({type: String, reflect: true}) color: ButtonColor = "primary";
18
+ @property({ type: Boolean, reflect: true }) active = false;
19
+ @property({ type: String, attribute: 'aria-label' }) ariaLabel: string | null = null;
20
+
21
+ static styles = [
22
+ resetStyles,
23
+ css`
24
+ :host {
25
+ /* ==========================================================
26
+ 1. Base Palette (Defaults to Primary Theme)
27
+ ========================================================== */
28
+ --_palette-base: var(--st-color-primary);
29
+ --_palette-hover: var(--st-color-primary-hover);
30
+ --_palette-surface: var(--st-color-surface);
31
+ --_palette-surface-hover: var(--st-color-border);
32
+
33
+ --_palette-text-on-base: var(--st-color-surface);
34
+ --_palette-text-on-surface: var(--st-color-text);
35
+
36
+ /* Sizing Tokens */
37
+ --_btn-padding: var(--st-spacing-sm) var(--st-spacing-md);
38
+ --_btn-font-size: var(--st-font-size-sm);
39
+ --_btn-radius: 4px;
40
+ --_btn-gap: var(--st-spacing-sm);
41
+
42
+ display: inline-block;
43
+ }
44
+
45
+ /* ==========================================================
46
+ 2. Semantic Color Overrides (Swaps the active palette)
47
+ ========================================================== */
48
+ :host([color="error"]) {
49
+ --_palette-base: var(--st-color-error);
50
+ --_palette-hover: color-mix(in srgb, var(--st-color-error), black 15%);
51
+ --_palette-surface: var(--st-color-error-bg);
52
+ --_palette-surface-hover: color-mix(in srgb, var(--st-color-error-bg), black 10%);
53
+ --_palette-text-on-base: var(--st-white); /* Force white text */
54
+ --_palette-text-on-surface: var(--st-color-error);
55
+ }
56
+
57
+ :host([color="success"]) {
58
+ --_palette-base: var(--st-color-success);
59
+ --_palette-hover: color-mix(in srgb, var(--st-color-success), black 15%);
60
+ --_palette-surface: var(--st-color-success-bg);
61
+ --_palette-surface-hover: color-mix(in srgb, var(--st-color-success-bg), black 10%);
62
+ --_palette-text-on-base: var(--st-white);
63
+ --_palette-text-on-surface: var(--st-color-success);
64
+ }
65
+
66
+ :host([color="warning"]) {
67
+ --_palette-base: var(--st-color-warning);
68
+ --_palette-hover: color-mix(in srgb, var(--st-color-warning), black 15%);
69
+ --_palette-surface: var(--st-color-warning-bg);
70
+ --_palette-surface-hover: color-mix(in srgb, var(--st-color-warning-bg), black 10%);
71
+ --_palette-text-on-base: var(--st-gray-900); /* Amber needs dark text for contrast */
72
+ --_palette-text-on-surface: var(--st-color-warning);
73
+ }
74
+
75
+ :host([color="info"]) {
76
+ --_palette-base: var(--st-color-info);
77
+ --_palette-hover: color-mix(in srgb, var(--st-color-info), black 15%);
78
+ --_palette-surface: var(--st-color-info-bg);
79
+ --_palette-surface-hover: color-mix(in srgb, var(--st-color-info-bg), black 10%);
80
+ --_palette-text-on-base: var(--st-white);
81
+ --_palette-text-on-surface: var(--st-color-info);
82
+ }
83
+
84
+ /* ==========================================================
85
+ 3. Visual Variants (Consumes the active palette)
86
+ ========================================================== */
87
+
88
+ /* Base (Primary / Solid) */
89
+ :host {
90
+ --_btn-bg: var(--_palette-base);
91
+ --_btn-bg-hover: var(--_palette-hover);
92
+ --_btn-text: var(--_palette-text-on-base);
93
+ --_btn-border: transparent;
94
+ }
95
+
96
+ /* Secondary Variant */
97
+ :host([variant="secondary"]) {
98
+ --_btn-bg: var(--_palette-surface);
99
+ --_btn-bg-hover: var(--_palette-surface-hover);
100
+ --_btn-text: var(--_palette-text-on-surface);
101
+ --_btn-border: transparent;
102
+ }
103
+
104
+ /* Outline Variant */
105
+ :host([variant="outline"]) {
106
+ --_btn-bg: transparent;
107
+ --_btn-bg-hover: var(--_palette-surface);
108
+ --_btn-text: var(--_palette-base);
109
+ --_btn-border: var(--_palette-base);
110
+ }
111
+
112
+ /* ==========================================================
113
+ 4. Size Variants
114
+ ========================================================== */
115
+ :host([size="sm"]) {
116
+ --_btn-padding: var(--st-spacing-xs) var(--st-spacing-sm);
117
+ --_btn-font-size: var(--st-font-size-xs);
118
+ --_btn-radius: 2px;
119
+ --_btn-gap: var(--st-spacing-xs);
120
+ }
121
+
122
+ :host([size="lg"]) {
123
+ --_btn-padding: var(--st-spacing-md) var(--st-spacing-lg);
124
+ --_btn-font-size: var(--st-font-size-base);
125
+ --_btn-radius: 6px;
126
+ --_btn-gap: var(--st-spacing-sm);
127
+ }
128
+
129
+ /* ==========================================================
130
+ 5. Base Button Rules
131
+ ========================================================== */
132
+ .btn {
133
+ display: inline-flex;
134
+ align-items: center;
135
+ justify-content: center;
136
+ gap: var(--_btn-gap);
137
+
138
+ background-color: var(--_btn-bg);
139
+ color: var(--_btn-text);
140
+ border: 1px solid var(--_btn-border);
141
+ padding: var(--_btn-padding);
142
+ font-size: var(--_btn-font-size);
143
+ border-radius: var(--_btn-radius);
144
+ line-height: 1;
145
+
146
+ cursor: pointer;
147
+ font-weight: var(--st-font-weight-medium);
148
+ transition: all 0.2s ease;
149
+ padding: 0.5rem 1rem;
150
+
151
+ /* 1. Split the border radius into 4 independent corners */
152
+ border-radius: var(--btn-radius-tl, var(--st-radius-md, 0.5rem))
153
+ var(--btn-radius-tr, var(--st-radius-md, 0.5rem))
154
+ var(--btn-radius-br, var(--st-radius-md, 0.5rem))
155
+ var(--btn-radius-bl, var(--st-radius-md, 0.5rem));
156
+
157
+ /* 2. Add a hook for the group wrapper to inject a divider line */
158
+ box-shadow: var(--btn-divider, none);
159
+
160
+ font-weight: 500;
161
+ text-decoration: none;
162
+ border: 1px solid transparent;
163
+ }
164
+
165
+ .btn:hover {
166
+ color: var(--_btn-text);
167
+ background-color: var(--_btn-bg-hover);
168
+ }
169
+
170
+ /* ==========================================================
171
+ Logical Active States (Selected/Toggled)
172
+ ========================================================== */
173
+ :host([active]) .btn {
174
+ filter: brightness(0.9);
175
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.2);
176
+ border-color: transparent;
177
+ color: var(--_btn-text);
178
+ background-color: var(--_btn-bg-hover);
179
+ }
180
+
181
+ :host([active]) .btn[color="primary"] {
182
+ filter: brightness(0.85);
183
+ box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2); /* Inset shadow gives a pressed look */
184
+ }
185
+
186
+ /* ==========================================================
187
+ Focus State (Accessibility)
188
+ ========================================================== */
189
+ /* focus-visible ensures this only shows for keyboard navigation, not mouse clicks */
190
+ .btn:focus-visible {
191
+ outline: 2px solid var(--st-color-primary);
192
+ outline-offset: 2px;
193
+ z-index: 1; /* Pulls the focused button forward if it's in a button group */
194
+ }
195
+
196
+ /* ==========================================================
197
+ Physical Active State (Mouse down)
198
+ ========================================================== */
199
+ .btn:active {
200
+ transform: scale(0.98);
201
+ }
202
+
203
+ /* Disabled & Loading */
204
+ :host([disabled]),
205
+ :host([loading]) {
206
+ pointer-events: none;
207
+ }
208
+
209
+ :host([disabled]) button {
210
+ opacity: 0.5;
211
+ cursor: not-allowed;
212
+ }
213
+
214
+ :host([loading]) button {
215
+ opacity: 0.8;
216
+ }
217
+
218
+ /* Icons & Spinner */
219
+ ::slotted(svg),
220
+ svg.spinner {
221
+ width: 1.25em;
222
+ height: 1.25em;
223
+ fill: currentColor;
224
+ flex-shrink: 0;
225
+ }
226
+
227
+ svg.spinner {
228
+ animation: st-spin 1s linear infinite;
229
+ }
230
+
231
+ @keyframes st-spin {
232
+ from {
233
+ transform: rotate(0deg);
234
+ }
235
+ to {
236
+ transform: rotate(360deg);
237
+ }
238
+ }
239
+ `,
240
+ ];
241
+
242
+ render() {
243
+ const content = html`<slot></slot>`;
244
+
245
+ if (this.href) {
246
+ return html`<a href="${this.href}" target="${this.target}" class="btn" color="${this.color}" aria-label=${this.ariaLabel || nothing}
247
+ >${content}</a
248
+ >`;
249
+ }
250
+
251
+ return html`
252
+ <button class="btn" ?disabled=${this.disabled || this.loading}>
253
+ ${this.loading
254
+ ? html`
255
+ <svg class="spinner" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
256
+ <path
257
+ opacity="0.2"
258
+ fill-rule="evenodd"
259
+ clip-rule="evenodd"
260
+ d="M12 19C15.866 19 19 15.866 19 12C19 8.13401 15.866 5 12 5C8.13401 5 5 8.13401 5 12C5 15.866 8.13401 19 12 19ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z"
261
+ fill="currentColor"
262
+ />
263
+ <path
264
+ d="M2 12C2 6.47715 6.47715 2 12 2V5C8.13401 5 5 8.13401 5 12H2Z"
265
+ fill="currentColor"
266
+ />
267
+ </svg>
268
+ `
269
+ : html`<slot name="prefix"></slot>`}
270
+ ${content}
271
+ <slot name="suffix"></slot>
272
+ </button>
273
+ `;
274
+ }
275
+ }
276
+
277
+ declare global {
278
+ interface HTMLElementTagNameMap {
279
+ "st-button": StButton;
280
+ }
281
+ }