@justin_evo/evo-ui 1.1.0 → 1.2.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 (80) hide show
  1. package/README.md +3 -3
  2. package/dist/TopNav/TopNav.d.ts +19 -0
  3. package/dist/declarations.d.ts +6 -6
  4. package/dist/evo-ui.css +1 -1
  5. package/dist/index.cjs.js +1 -1
  6. package/dist/index.es.js +3301 -3197
  7. package/package.json +52 -52
  8. package/src/Alert/Alert.tsx +49 -49
  9. package/src/AutoComplete/AutoComplete.tsx +810 -810
  10. package/src/Badge/Badge.tsx +53 -53
  11. package/src/Breadcrumb/Breadcrumb.tsx +53 -53
  12. package/src/Button/Button.tsx +125 -125
  13. package/src/Card/Card.tsx +257 -257
  14. package/src/Checkbox/Checkbox.tsx +59 -59
  15. package/src/CommandPalette/CommandPalette.tsx +185 -185
  16. package/src/Container/Container.tsx +31 -31
  17. package/src/Divider/Divider.tsx +31 -31
  18. package/src/Form/Form.tsx +185 -185
  19. package/src/Grid/Grid.tsx +66 -66
  20. package/src/ImageCropper/ImageCropper.tsx +911 -911
  21. package/src/Input/Input.tsx +74 -74
  22. package/src/Modal/Modal.tsx +77 -77
  23. package/src/Nav/Nav.tsx +708 -708
  24. package/src/Notification/Notification.tsx +1503 -1503
  25. package/src/Pagination/Pagination.tsx +76 -76
  26. package/src/Radio/Radio.tsx +69 -69
  27. package/src/RichTextArea/RichTextArea.tsx +886 -869
  28. package/src/Select/Select.tsx +515 -515
  29. package/src/Skeleton/Skeleton.tsx +70 -70
  30. package/src/Stack/Stack.tsx +52 -52
  31. package/src/Table/Table.tsx +335 -335
  32. package/src/Tabs/Tabs.tsx +90 -90
  33. package/src/Theme/ThemeProvider.tsx +253 -253
  34. package/src/Theme/ThemeToggle.tsx +79 -79
  35. package/src/Toggle/Toggle.tsx +48 -48
  36. package/src/Tooltip/Tooltip.tsx +38 -38
  37. package/src/TopNav/TopNav.tsx +1163 -994
  38. package/src/TreeSelect/TreeSelect.tsx +825 -825
  39. package/src/css/alert.module.scss +93 -93
  40. package/src/css/autocomplete.module.scss +416 -416
  41. package/src/css/badge.module.scss +82 -82
  42. package/src/css/base/_color.scss +159 -159
  43. package/src/css/base/_theme.scss +237 -237
  44. package/src/css/base/_variables.scss +161 -161
  45. package/src/css/breadcrumb.module.scss +50 -50
  46. package/src/css/button.module.scss +385 -385
  47. package/src/css/card.module.scss +217 -217
  48. package/src/css/checkbox.module.scss +123 -120
  49. package/src/css/commandpalette.module.scss +211 -211
  50. package/src/css/container.module.scss +18 -18
  51. package/src/css/divider.module.scss +41 -41
  52. package/src/css/form.module.scss +245 -245
  53. package/src/css/imagecropper.module.scss +397 -397
  54. package/src/css/input.module.scss +89 -89
  55. package/src/css/modal.module.scss +105 -105
  56. package/src/css/nav.module.scss +494 -494
  57. package/src/css/notification.module.scss +691 -691
  58. package/src/css/pagination.module.scss +63 -63
  59. package/src/css/radio.module.scss +89 -89
  60. package/src/css/richtextarea.module.scss +307 -307
  61. package/src/css/select.module.scss +525 -525
  62. package/src/css/skeleton.module.scss +30 -30
  63. package/src/css/table.module.scss +386 -386
  64. package/src/css/tabs.module.scss +63 -63
  65. package/src/css/theme-toggle.module.scss +83 -83
  66. package/src/css/toggle.module.scss +54 -54
  67. package/src/css/tooltip.module.scss +97 -97
  68. package/src/css/topnav.module.scss +568 -396
  69. package/src/css/treeselect.module.scss +558 -558
  70. package/src/css/utilities/_borders.scss +111 -111
  71. package/src/css/utilities/_colors.scss +66 -66
  72. package/src/css/utilities/_effects.scss +216 -216
  73. package/src/css/utilities/_layout.scss +181 -181
  74. package/src/css/utilities/_position.scss +75 -75
  75. package/src/css/utilities/_sizing.scss +138 -138
  76. package/src/css/utilities/_spacing.scss +99 -99
  77. package/src/css/utilities/_typography.scss +121 -121
  78. package/src/css/utilities/index.scss +24 -24
  79. package/src/declarations.d.ts +6 -6
  80. package/src/index.ts +60 -60
@@ -1,385 +1,385 @@
1
- @use 'base/variables' as *;
2
- @use 'base/color' as *;
3
-
4
- // ==========================================================
5
- // EvoButton
6
- // ----------------------------------------------------------
7
- // Layout is built around three orthogonal axes:
8
- // 1. variant — solid / outline / ghost / soft
9
- // 2. severity — primary / secondary / danger / warning / success / info
10
- // 3. shape — default / rounded / square
11
- // Plus modifiers: size (sm/md/lg), fullWidth, iconOnly, loading.
12
- //
13
- // All sizing uses `rem` + `min-height` so the component stays
14
- // usable on touch screens (44px target for `lg`) without needing
15
- // explicit mobile media queries.
16
- // ==========================================================
17
-
18
- // --- Base button ---
19
- .button {
20
- display: inline-flex;
21
- align-items: center;
22
- justify-content: center;
23
- gap: 0.4rem;
24
- padding: $evo-btn-padding-y $evo-btn-padding-x;
25
- min-height: 2.25rem;
26
- max-width: 100%;
27
- font-family: inherit;
28
- font-size: $evo-btn-font-size;
29
- font-weight: $evo-btn-font-weight;
30
- line-height: $evo-btn-line-height;
31
- white-space: nowrap;
32
- vertical-align: middle;
33
- border: 2px solid transparent;
34
- border-radius: $evo-border-radius;
35
- background-color: transparent;
36
- color: inherit;
37
- cursor: pointer;
38
- user-select: none;
39
- text-decoration: none;
40
- appearance: none;
41
- -webkit-tap-highlight-color: transparent;
42
- touch-action: manipulation;
43
- transition: background-color $evo-btn-transition,
44
- border-color $evo-btn-transition,
45
- box-shadow $evo-btn-transition,
46
- color $evo-btn-transition;
47
-
48
- &:focus-visible {
49
- outline-width: $evo-btn-outline-width;
50
- outline-style: solid;
51
- outline-offset: $evo-btn-outline-offset;
52
- }
53
-
54
- &:disabled {
55
- opacity: $evo-btn-disabled-opacity;
56
- cursor: not-allowed;
57
- pointer-events: none;
58
- }
59
- }
60
-
61
- // --- Slots ---
62
- .label {
63
- min-width: 0;
64
- overflow: hidden;
65
- text-overflow: ellipsis;
66
- }
67
-
68
- .icon {
69
- display: inline-flex;
70
- align-items: center;
71
- justify-content: center;
72
- flex-shrink: 0;
73
- line-height: 1;
74
-
75
- // Normalize SVGs so consumers don't have to size them
76
- > svg {
77
- width: 1em;
78
- height: 1em;
79
- }
80
- }
81
-
82
- // --- Loading spinner (CSS-only, inherits currentColor) ---
83
- .spinner {
84
- display: inline-block;
85
- width: 1em;
86
- height: 1em;
87
- flex-shrink: 0;
88
- border: 2px solid currentColor;
89
- border-right-color: transparent;
90
- border-radius: 50%;
91
- animation: evo-btn-spin 0.6s linear infinite;
92
- }
93
-
94
- @keyframes evo-btn-spin {
95
- to { transform: rotate(360deg); }
96
- }
97
-
98
- // --- Size modifiers ---
99
- .sm {
100
- gap: 0.3rem;
101
- padding: $evo-btn-padding-y-sm $evo-btn-padding-x-sm;
102
- min-height: 1.75rem;
103
- font-size: $evo-btn-font-size-sm;
104
- border-radius: $evo-border-radius-sm;
105
- }
106
-
107
- .md { /* default */ }
108
-
109
- .lg {
110
- gap: 0.5rem;
111
- padding: $evo-btn-padding-y-lg $evo-btn-padding-x-lg;
112
- min-height: 2.75rem;
113
- font-size: $evo-btn-font-size-lg;
114
- border-radius: $evo-border-radius-lg;
115
- }
116
-
117
- // --- Shape modifiers (orthogonal to variant) ---
118
- .rounded {
119
- border-radius: $evo-border-radius-pill;
120
- }
121
-
122
- .square {
123
- padding: 0;
124
- aspect-ratio: 1 / 1;
125
- min-width: 2.25rem;
126
-
127
- &.sm { min-width: 1.75rem; }
128
- &.lg { min-width: 2.75rem; }
129
- }
130
-
131
- // --- Icon-only (auto-applied when there's no label/children) ---
132
- .iconOnly {
133
- padding-left: 0.5rem;
134
- padding-right: 0.5rem;
135
-
136
- &.sm { padding-left: 0.35rem; padding-right: 0.35rem; }
137
- &.lg { padding-left: 0.65rem; padding-right: 0.65rem; }
138
- }
139
-
140
- // --- Layout modifiers ---
141
- .fullWidth {
142
- display: flex;
143
- width: 100%;
144
- }
145
-
146
- // --- Variant base looks ---
147
- .solid { /* color set per-severity */ }
148
- .outline { background-color: transparent; }
149
- .ghost { background-color: transparent; border-color: transparent; }
150
- .soft { border-color: transparent; }
151
-
152
- // --- Severities ---
153
- .primary {
154
- &.solid {
155
- color: $evo-primary-fg;
156
- background-color: $evo-primary-color;
157
- border-color: $evo-primary-color;
158
-
159
- &:hover:not(:disabled) { background-color: $evo-primary-hover; border-color: $evo-primary-hover; }
160
- &:active:not(:disabled) { background-color: $evo-primary-active; border-color: $evo-primary-active; }
161
- &:focus-visible { outline-color: $evo-primary-focus; }
162
- }
163
-
164
- &.outline {
165
- color: $evo-primary-color;
166
- border-color: $evo-primary-color;
167
-
168
- &:hover:not(:disabled) { color: $evo-primary-fg; background-color: $evo-primary-color; }
169
- &:active:not(:disabled) { color: $evo-primary-fg; background-color: $evo-primary-hover; border-color: $evo-primary-hover; }
170
- &:focus-visible { outline-color: $evo-primary-focus; }
171
- }
172
-
173
- &.ghost {
174
- color: $evo-primary-color;
175
-
176
- &:hover:not(:disabled) { background-color: $evo-primary-soft; }
177
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-primary-color 22%, transparent); }
178
- &:focus-visible { outline-color: $evo-primary-focus; }
179
- }
180
-
181
- &.soft {
182
- color: $evo-primary-color;
183
- background-color: $evo-primary-soft;
184
-
185
- &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-primary-color 22%, transparent); }
186
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-primary-color 30%, transparent); }
187
- &:focus-visible { outline-color: $evo-primary-focus; }
188
- }
189
- }
190
-
191
- .secondary {
192
- &.solid {
193
- color: $evo-secondary-text;
194
- background-color: $evo-secondary-bg;
195
- border-color: $evo-secondary-border;
196
-
197
- &:hover:not(:disabled) { background-color: $evo-secondary-hover; border-color: $color-border-strong; color: $color-text-primary; }
198
- &:active:not(:disabled) { background-color: $evo-secondary-active; border-color: $color-border-strong; }
199
- &:focus-visible { outline-color: $evo-secondary-focus; }
200
- }
201
-
202
- &.outline {
203
- color: $evo-secondary-text;
204
- border-color: $evo-secondary-border;
205
-
206
- &:hover:not(:disabled) { background-color: $evo-secondary-bg; border-color: $color-border-strong; color: $color-text-primary; }
207
- &:active:not(:disabled) { background-color: $evo-secondary-hover; border-color: $color-border-strong; }
208
- &:focus-visible { outline-color: $evo-secondary-focus; }
209
- }
210
-
211
- &.ghost {
212
- color: $evo-secondary-text;
213
-
214
- &:hover:not(:disabled) { background-color: $evo-secondary-bg; color: $color-text-primary; }
215
- &:active:not(:disabled) { background-color: $evo-secondary-hover; }
216
- &:focus-visible { outline-color: $evo-secondary-focus; }
217
- }
218
-
219
- &.soft {
220
- color: $color-text-primary;
221
- background-color: $evo-secondary-bg;
222
-
223
- &:hover:not(:disabled) { background-color: $evo-secondary-hover; }
224
- &:active:not(:disabled) { background-color: $evo-secondary-active; }
225
- &:focus-visible { outline-color: $evo-secondary-focus; }
226
- }
227
- }
228
-
229
- .danger {
230
- &.solid {
231
- color: $evo-danger-fg;
232
- background-color: $evo-danger-color;
233
- border-color: $evo-danger-color;
234
-
235
- &:hover:not(:disabled) { background-color: $evo-danger-hover; border-color: $evo-danger-hover; }
236
- &:active:not(:disabled) { background-color: $evo-danger-active; border-color: $evo-danger-active; }
237
- &:focus-visible { outline-color: $evo-danger-focus; }
238
- }
239
-
240
- &.outline {
241
- color: $evo-danger-color;
242
- border-color: $evo-danger-color;
243
-
244
- &:hover:not(:disabled) { color: $evo-danger-fg; background-color: $evo-danger-color; }
245
- &:active:not(:disabled) { color: $evo-danger-fg; background-color: $evo-danger-hover; border-color: $evo-danger-hover; }
246
- &:focus-visible { outline-color: $evo-danger-focus; }
247
- }
248
-
249
- &.ghost {
250
- color: $evo-danger-color;
251
-
252
- &:hover:not(:disabled) { background-color: $evo-danger-soft; }
253
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-danger-color 22%, transparent); }
254
- &:focus-visible { outline-color: $evo-danger-focus; }
255
- }
256
-
257
- &.soft {
258
- color: $evo-danger-color;
259
- background-color: $evo-danger-soft;
260
-
261
- &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-danger-color 22%, transparent); }
262
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-danger-color 30%, transparent); }
263
- &:focus-visible { outline-color: $evo-danger-focus; }
264
- }
265
- }
266
-
267
- .warning {
268
- &.solid {
269
- color: $evo-warning-text;
270
- background-color: $evo-warning-color;
271
- border-color: $evo-warning-color;
272
-
273
- &:hover:not(:disabled) { background-color: $evo-warning-hover; border-color: $evo-warning-hover; }
274
- &:active:not(:disabled) { background-color: $evo-warning-active; border-color: $evo-warning-active; }
275
- &:focus-visible { outline-color: $evo-warning-focus; }
276
- }
277
-
278
- &.outline {
279
- color: $evo-warning-text;
280
- border-color: $evo-warning-color;
281
-
282
- &:hover:not(:disabled) { background-color: $evo-warning-color; }
283
- &:active:not(:disabled) { background-color: $evo-warning-hover; border-color: $evo-warning-hover; }
284
- &:focus-visible { outline-color: $evo-warning-focus; }
285
- }
286
-
287
- &.ghost {
288
- color: $evo-warning-text;
289
-
290
- &:hover:not(:disabled) { background-color: $evo-warning-soft; }
291
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-warning-color 22%, transparent); }
292
- &:focus-visible { outline-color: $evo-warning-focus; }
293
- }
294
-
295
- &.soft {
296
- color: $evo-warning-text;
297
- background-color: $evo-warning-soft;
298
-
299
- &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-warning-color 22%, transparent); }
300
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-warning-color 30%, transparent); }
301
- &:focus-visible { outline-color: $evo-warning-focus; }
302
- }
303
- }
304
-
305
- .success {
306
- &.solid {
307
- color: $evo-success-fg;
308
- background-color: $evo-success-color;
309
- border-color: $evo-success-color;
310
-
311
- &:hover:not(:disabled) { background-color: $evo-success-hover; border-color: $evo-success-hover; }
312
- &:active:not(:disabled) { background-color: $evo-success-active; border-color: $evo-success-active; }
313
- &:focus-visible { outline-color: $evo-success-focus; }
314
- }
315
-
316
- &.outline {
317
- color: $evo-success-color;
318
- border-color: $evo-success-color;
319
-
320
- &:hover:not(:disabled) { color: $evo-success-fg; background-color: $evo-success-color; }
321
- &:active:not(:disabled) { color: $evo-success-fg; background-color: $evo-success-hover; border-color: $evo-success-hover; }
322
- &:focus-visible { outline-color: $evo-success-focus; }
323
- }
324
-
325
- &.ghost {
326
- color: $evo-success-color;
327
-
328
- &:hover:not(:disabled) { background-color: $evo-success-soft; }
329
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-success-color 22%, transparent); }
330
- &:focus-visible { outline-color: $evo-success-focus; }
331
- }
332
-
333
- &.soft {
334
- color: $evo-success-color;
335
- background-color: $evo-success-soft;
336
-
337
- &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-success-color 22%, transparent); }
338
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-success-color 30%, transparent); }
339
- &:focus-visible { outline-color: $evo-success-focus; }
340
- }
341
- }
342
-
343
- .info {
344
- &.solid {
345
- color: $evo-info-fg;
346
- background-color: $evo-info-color;
347
- border-color: $evo-info-color;
348
-
349
- &:hover:not(:disabled) { background-color: $evo-info-hover; border-color: $evo-info-hover; }
350
- &:active:not(:disabled) { background-color: $evo-info-active; border-color: $evo-info-active; }
351
- &:focus-visible { outline-color: $evo-info-focus; }
352
- }
353
-
354
- &.outline {
355
- color: $evo-info-color;
356
- border-color: $evo-info-color;
357
-
358
- &:hover:not(:disabled) { color: $evo-info-fg; background-color: $evo-info-color; }
359
- &:active:not(:disabled) { color: $evo-info-fg; background-color: $evo-info-hover; border-color: $evo-info-hover; }
360
- &:focus-visible { outline-color: $evo-info-focus; }
361
- }
362
-
363
- &.ghost {
364
- color: $evo-info-color;
365
-
366
- &:hover:not(:disabled) { background-color: $evo-info-soft; }
367
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-info-color 22%, transparent); }
368
- &:focus-visible { outline-color: $evo-info-focus; }
369
- }
370
-
371
- &.soft {
372
- color: $evo-info-color;
373
- background-color: $evo-info-soft;
374
-
375
- &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-info-color 22%, transparent); }
376
- &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-info-color 30%, transparent); }
377
- &:focus-visible { outline-color: $evo-info-focus; }
378
- }
379
- }
380
-
381
- // Respect users who prefer reduced motion
382
- @media (prefers-reduced-motion: reduce) {
383
- .button { transition: none; }
384
- .spinner { animation-duration: 1.6s; }
385
- }
1
+ @use 'base/variables' as *;
2
+ @use 'base/color' as *;
3
+
4
+ // ==========================================================
5
+ // EvoButton
6
+ // ----------------------------------------------------------
7
+ // Layout is built around three orthogonal axes:
8
+ // 1. variant — solid / outline / ghost / soft
9
+ // 2. severity — primary / secondary / danger / warning / success / info
10
+ // 3. shape — default / rounded / square
11
+ // Plus modifiers: size (sm/md/lg), fullWidth, iconOnly, loading.
12
+ //
13
+ // All sizing uses `rem` + `min-height` so the component stays
14
+ // usable on touch screens (44px target for `lg`) without needing
15
+ // explicit mobile media queries.
16
+ // ==========================================================
17
+
18
+ // --- Base button ---
19
+ .button {
20
+ display: inline-flex;
21
+ align-items: center;
22
+ justify-content: center;
23
+ gap: 0.4rem;
24
+ padding: $evo-btn-padding-y $evo-btn-padding-x;
25
+ min-height: 2.25rem;
26
+ max-width: 100%;
27
+ font-family: inherit;
28
+ font-size: $evo-btn-font-size;
29
+ font-weight: $evo-btn-font-weight;
30
+ line-height: $evo-btn-line-height;
31
+ white-space: nowrap;
32
+ vertical-align: middle;
33
+ border: 2px solid transparent;
34
+ border-radius: $evo-border-radius;
35
+ background-color: transparent;
36
+ color: inherit;
37
+ cursor: pointer;
38
+ user-select: none;
39
+ text-decoration: none;
40
+ appearance: none;
41
+ -webkit-tap-highlight-color: transparent;
42
+ touch-action: manipulation;
43
+ transition: background-color $evo-btn-transition,
44
+ border-color $evo-btn-transition,
45
+ box-shadow $evo-btn-transition,
46
+ color $evo-btn-transition;
47
+
48
+ &:focus-visible {
49
+ outline-width: $evo-btn-outline-width;
50
+ outline-style: solid;
51
+ outline-offset: $evo-btn-outline-offset;
52
+ }
53
+
54
+ &:disabled {
55
+ opacity: $evo-btn-disabled-opacity;
56
+ cursor: not-allowed;
57
+ pointer-events: none;
58
+ }
59
+ }
60
+
61
+ // --- Slots ---
62
+ .label {
63
+ min-width: 0;
64
+ overflow: hidden;
65
+ text-overflow: ellipsis;
66
+ }
67
+
68
+ .icon {
69
+ display: inline-flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ flex-shrink: 0;
73
+ line-height: 1;
74
+
75
+ // Normalize SVGs so consumers don't have to size them
76
+ > svg {
77
+ width: 1em;
78
+ height: 1em;
79
+ }
80
+ }
81
+
82
+ // --- Loading spinner (CSS-only, inherits currentColor) ---
83
+ .spinner {
84
+ display: inline-block;
85
+ width: 1em;
86
+ height: 1em;
87
+ flex-shrink: 0;
88
+ border: 2px solid currentColor;
89
+ border-right-color: transparent;
90
+ border-radius: 50%;
91
+ animation: evo-btn-spin 0.6s linear infinite;
92
+ }
93
+
94
+ @keyframes evo-btn-spin {
95
+ to { transform: rotate(360deg); }
96
+ }
97
+
98
+ // --- Size modifiers ---
99
+ .sm {
100
+ gap: 0.3rem;
101
+ padding: $evo-btn-padding-y-sm $evo-btn-padding-x-sm;
102
+ min-height: 1.75rem;
103
+ font-size: $evo-btn-font-size-sm;
104
+ border-radius: $evo-border-radius-sm;
105
+ }
106
+
107
+ .md { /* default */ }
108
+
109
+ .lg {
110
+ gap: 0.5rem;
111
+ padding: $evo-btn-padding-y-lg $evo-btn-padding-x-lg;
112
+ min-height: 2.75rem;
113
+ font-size: $evo-btn-font-size-lg;
114
+ border-radius: $evo-border-radius-lg;
115
+ }
116
+
117
+ // --- Shape modifiers (orthogonal to variant) ---
118
+ .rounded {
119
+ border-radius: $evo-border-radius-pill;
120
+ }
121
+
122
+ .square {
123
+ padding: 0;
124
+ aspect-ratio: 1 / 1;
125
+ min-width: 2.25rem;
126
+
127
+ &.sm { min-width: 1.75rem; }
128
+ &.lg { min-width: 2.75rem; }
129
+ }
130
+
131
+ // --- Icon-only (auto-applied when there's no label/children) ---
132
+ .iconOnly {
133
+ padding-left: 0.5rem;
134
+ padding-right: 0.5rem;
135
+
136
+ &.sm { padding-left: 0.35rem; padding-right: 0.35rem; }
137
+ &.lg { padding-left: 0.65rem; padding-right: 0.65rem; }
138
+ }
139
+
140
+ // --- Layout modifiers ---
141
+ .fullWidth {
142
+ display: flex;
143
+ width: 100%;
144
+ }
145
+
146
+ // --- Variant base looks ---
147
+ .solid { /* color set per-severity */ }
148
+ .outline { background-color: transparent; }
149
+ .ghost { background-color: transparent; border-color: transparent; }
150
+ .soft { border-color: transparent; }
151
+
152
+ // --- Severities ---
153
+ .primary {
154
+ &.solid {
155
+ color: $evo-primary-fg;
156
+ background-color: $evo-primary-color;
157
+ border-color: $evo-primary-color;
158
+
159
+ &:hover:not(:disabled) { background-color: $evo-primary-hover; border-color: $evo-primary-hover; }
160
+ &:active:not(:disabled) { background-color: $evo-primary-active; border-color: $evo-primary-active; }
161
+ &:focus-visible { outline-color: $evo-primary-focus; }
162
+ }
163
+
164
+ &.outline {
165
+ color: $evo-primary-color;
166
+ border-color: $evo-primary-color;
167
+
168
+ &:hover:not(:disabled) { color: $evo-primary-fg; background-color: $evo-primary-color; }
169
+ &:active:not(:disabled) { color: $evo-primary-fg; background-color: $evo-primary-hover; border-color: $evo-primary-hover; }
170
+ &:focus-visible { outline-color: $evo-primary-focus; }
171
+ }
172
+
173
+ &.ghost {
174
+ color: $evo-primary-color;
175
+
176
+ &:hover:not(:disabled) { background-color: $evo-primary-soft; }
177
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-primary-color 22%, transparent); }
178
+ &:focus-visible { outline-color: $evo-primary-focus; }
179
+ }
180
+
181
+ &.soft {
182
+ color: $evo-primary-color;
183
+ background-color: $evo-primary-soft;
184
+
185
+ &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-primary-color 22%, transparent); }
186
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-primary-color 30%, transparent); }
187
+ &:focus-visible { outline-color: $evo-primary-focus; }
188
+ }
189
+ }
190
+
191
+ .secondary {
192
+ &.solid {
193
+ color: $evo-secondary-text;
194
+ background-color: $evo-secondary-bg;
195
+ border-color: $evo-secondary-border;
196
+
197
+ &:hover:not(:disabled) { background-color: $evo-secondary-hover; border-color: $color-border-strong; color: $color-text-primary; }
198
+ &:active:not(:disabled) { background-color: $evo-secondary-active; border-color: $color-border-strong; }
199
+ &:focus-visible { outline-color: $evo-secondary-focus; }
200
+ }
201
+
202
+ &.outline {
203
+ color: $evo-secondary-text;
204
+ border-color: $evo-secondary-border;
205
+
206
+ &:hover:not(:disabled) { background-color: $evo-secondary-bg; border-color: $color-border-strong; color: $color-text-primary; }
207
+ &:active:not(:disabled) { background-color: $evo-secondary-hover; border-color: $color-border-strong; }
208
+ &:focus-visible { outline-color: $evo-secondary-focus; }
209
+ }
210
+
211
+ &.ghost {
212
+ color: $evo-secondary-text;
213
+
214
+ &:hover:not(:disabled) { background-color: $evo-secondary-bg; color: $color-text-primary; }
215
+ &:active:not(:disabled) { background-color: $evo-secondary-hover; }
216
+ &:focus-visible { outline-color: $evo-secondary-focus; }
217
+ }
218
+
219
+ &.soft {
220
+ color: $color-text-primary;
221
+ background-color: $evo-secondary-bg;
222
+
223
+ &:hover:not(:disabled) { background-color: $evo-secondary-hover; }
224
+ &:active:not(:disabled) { background-color: $evo-secondary-active; }
225
+ &:focus-visible { outline-color: $evo-secondary-focus; }
226
+ }
227
+ }
228
+
229
+ .danger {
230
+ &.solid {
231
+ color: $evo-danger-fg;
232
+ background-color: $evo-danger-color;
233
+ border-color: $evo-danger-color;
234
+
235
+ &:hover:not(:disabled) { background-color: $evo-danger-hover; border-color: $evo-danger-hover; }
236
+ &:active:not(:disabled) { background-color: $evo-danger-active; border-color: $evo-danger-active; }
237
+ &:focus-visible { outline-color: $evo-danger-focus; }
238
+ }
239
+
240
+ &.outline {
241
+ color: $evo-danger-color;
242
+ border-color: $evo-danger-color;
243
+
244
+ &:hover:not(:disabled) { color: $evo-danger-fg; background-color: $evo-danger-color; }
245
+ &:active:not(:disabled) { color: $evo-danger-fg; background-color: $evo-danger-hover; border-color: $evo-danger-hover; }
246
+ &:focus-visible { outline-color: $evo-danger-focus; }
247
+ }
248
+
249
+ &.ghost {
250
+ color: $evo-danger-color;
251
+
252
+ &:hover:not(:disabled) { background-color: $evo-danger-soft; }
253
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-danger-color 22%, transparent); }
254
+ &:focus-visible { outline-color: $evo-danger-focus; }
255
+ }
256
+
257
+ &.soft {
258
+ color: $evo-danger-color;
259
+ background-color: $evo-danger-soft;
260
+
261
+ &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-danger-color 22%, transparent); }
262
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-danger-color 30%, transparent); }
263
+ &:focus-visible { outline-color: $evo-danger-focus; }
264
+ }
265
+ }
266
+
267
+ .warning {
268
+ &.solid {
269
+ color: $evo-warning-text;
270
+ background-color: $evo-warning-color;
271
+ border-color: $evo-warning-color;
272
+
273
+ &:hover:not(:disabled) { background-color: $evo-warning-hover; border-color: $evo-warning-hover; }
274
+ &:active:not(:disabled) { background-color: $evo-warning-active; border-color: $evo-warning-active; }
275
+ &:focus-visible { outline-color: $evo-warning-focus; }
276
+ }
277
+
278
+ &.outline {
279
+ color: $evo-warning-text;
280
+ border-color: $evo-warning-color;
281
+
282
+ &:hover:not(:disabled) { background-color: $evo-warning-color; }
283
+ &:active:not(:disabled) { background-color: $evo-warning-hover; border-color: $evo-warning-hover; }
284
+ &:focus-visible { outline-color: $evo-warning-focus; }
285
+ }
286
+
287
+ &.ghost {
288
+ color: $evo-warning-text;
289
+
290
+ &:hover:not(:disabled) { background-color: $evo-warning-soft; }
291
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-warning-color 22%, transparent); }
292
+ &:focus-visible { outline-color: $evo-warning-focus; }
293
+ }
294
+
295
+ &.soft {
296
+ color: $evo-warning-text;
297
+ background-color: $evo-warning-soft;
298
+
299
+ &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-warning-color 22%, transparent); }
300
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-warning-color 30%, transparent); }
301
+ &:focus-visible { outline-color: $evo-warning-focus; }
302
+ }
303
+ }
304
+
305
+ .success {
306
+ &.solid {
307
+ color: $evo-success-fg;
308
+ background-color: $evo-success-color;
309
+ border-color: $evo-success-color;
310
+
311
+ &:hover:not(:disabled) { background-color: $evo-success-hover; border-color: $evo-success-hover; }
312
+ &:active:not(:disabled) { background-color: $evo-success-active; border-color: $evo-success-active; }
313
+ &:focus-visible { outline-color: $evo-success-focus; }
314
+ }
315
+
316
+ &.outline {
317
+ color: $evo-success-color;
318
+ border-color: $evo-success-color;
319
+
320
+ &:hover:not(:disabled) { color: $evo-success-fg; background-color: $evo-success-color; }
321
+ &:active:not(:disabled) { color: $evo-success-fg; background-color: $evo-success-hover; border-color: $evo-success-hover; }
322
+ &:focus-visible { outline-color: $evo-success-focus; }
323
+ }
324
+
325
+ &.ghost {
326
+ color: $evo-success-color;
327
+
328
+ &:hover:not(:disabled) { background-color: $evo-success-soft; }
329
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-success-color 22%, transparent); }
330
+ &:focus-visible { outline-color: $evo-success-focus; }
331
+ }
332
+
333
+ &.soft {
334
+ color: $evo-success-color;
335
+ background-color: $evo-success-soft;
336
+
337
+ &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-success-color 22%, transparent); }
338
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-success-color 30%, transparent); }
339
+ &:focus-visible { outline-color: $evo-success-focus; }
340
+ }
341
+ }
342
+
343
+ .info {
344
+ &.solid {
345
+ color: $evo-info-fg;
346
+ background-color: $evo-info-color;
347
+ border-color: $evo-info-color;
348
+
349
+ &:hover:not(:disabled) { background-color: $evo-info-hover; border-color: $evo-info-hover; }
350
+ &:active:not(:disabled) { background-color: $evo-info-active; border-color: $evo-info-active; }
351
+ &:focus-visible { outline-color: $evo-info-focus; }
352
+ }
353
+
354
+ &.outline {
355
+ color: $evo-info-color;
356
+ border-color: $evo-info-color;
357
+
358
+ &:hover:not(:disabled) { color: $evo-info-fg; background-color: $evo-info-color; }
359
+ &:active:not(:disabled) { color: $evo-info-fg; background-color: $evo-info-hover; border-color: $evo-info-hover; }
360
+ &:focus-visible { outline-color: $evo-info-focus; }
361
+ }
362
+
363
+ &.ghost {
364
+ color: $evo-info-color;
365
+
366
+ &:hover:not(:disabled) { background-color: $evo-info-soft; }
367
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-info-color 22%, transparent); }
368
+ &:focus-visible { outline-color: $evo-info-focus; }
369
+ }
370
+
371
+ &.soft {
372
+ color: $evo-info-color;
373
+ background-color: $evo-info-soft;
374
+
375
+ &:hover:not(:disabled) { background-color: color-mix(in srgb, $evo-info-color 22%, transparent); }
376
+ &:active:not(:disabled) { background-color: color-mix(in srgb, $evo-info-color 30%, transparent); }
377
+ &:focus-visible { outline-color: $evo-info-focus; }
378
+ }
379
+ }
380
+
381
+ // Respect users who prefer reduced motion
382
+ @media (prefers-reduced-motion: reduce) {
383
+ .button { transition: none; }
384
+ .spinner { animation-duration: 1.6s; }
385
+ }