@vifui/styles 0.4.0-alpha.6

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.
@@ -0,0 +1,564 @@
1
+ /**
2
+ * Button Component
3
+ *
4
+ * Architecture inspired by Vuesax v3 (MIT License)
5
+ * Built with modern Tailwind CSS and CSS variables
6
+ */
7
+
8
+ /* ============================================ */
9
+ /* Base Button */
10
+ /* ============================================ */
11
+
12
+ .vif-button {
13
+ /* Layout */
14
+ @apply relative inline-flex items-center justify-center gap-2;
15
+ @apply whitespace-nowrap select-none;
16
+ @apply overflow-hidden;
17
+
18
+ /* Sizing */
19
+ @apply h-10 px-4;
20
+ @apply text-sm font-medium;
21
+
22
+ /* Borders */
23
+ border-radius: var(--radius);
24
+ border: 0;
25
+
26
+ /* Cursor */
27
+ cursor: var(--cursor-interactive);
28
+
29
+ /* Transitions - smooth like Vuesax */
30
+ transition:
31
+ transform 200ms var(--ease-out),
32
+ background-color 150ms var(--ease-smooth),
33
+ color 150ms var(--ease-smooth),
34
+ box-shadow 250ms var(--ease-smooth);
35
+
36
+ /* Remove default button styles */
37
+ background: transparent;
38
+
39
+ /* Focus state */
40
+ &:focus-visible {
41
+ outline: 2px solid var(--focus);
42
+ outline-offset: var(--ring-offset-width);
43
+ }
44
+
45
+ /* Disabled state */
46
+ &:disabled,
47
+ &[aria-disabled="true"] {
48
+ opacity: var(--disabled-opacity);
49
+ cursor: var(--cursor-disabled);
50
+ pointer-events: none;
51
+ }
52
+
53
+ /* Active/pressed state - scale like Vuesax */
54
+ &:active:not(:disabled) {
55
+ transform: scale(0.97);
56
+ }
57
+
58
+ /* Icon styles */
59
+ & svg {
60
+ @apply size-5 shrink-0;
61
+ flex-shrink: 0;
62
+ }
63
+ }
64
+
65
+ /* ============================================ */
66
+ /* Size Variants */
67
+ /* ============================================ */
68
+
69
+ .vif-button--xs {
70
+ @apply h-6 px-2 text-xs;
71
+
72
+ & svg {
73
+ @apply size-3;
74
+ }
75
+
76
+ &:active:not(:disabled) {
77
+ transform: scale(0.99);
78
+ }
79
+ }
80
+
81
+ .vif-button--sm {
82
+ @apply h-8 px-3 text-xs;
83
+
84
+ & svg {
85
+ @apply size-4;
86
+ }
87
+
88
+ &:active:not(:disabled) {
89
+ transform: scale(0.98);
90
+ }
91
+ }
92
+
93
+ .vif-button--lg {
94
+ @apply h-12 px-6 text-base;
95
+
96
+ & svg {
97
+ @apply size-6;
98
+ }
99
+
100
+ &:active:not(:disabled) {
101
+ transform: scale(0.96);
102
+ }
103
+ }
104
+
105
+ .vif-button--xl {
106
+ @apply h-14 px-8 text-lg;
107
+
108
+ & svg {
109
+ @apply size-7;
110
+ }
111
+
112
+ &:active:not(:disabled) {
113
+ transform: scale(0.95);
114
+ }
115
+ }
116
+
117
+ /* ============================================ */
118
+ /* Primary Variant (Default Filled) */
119
+ /* ============================================ */
120
+
121
+ .vif-button--primary {
122
+ @apply bg-primary text-primary-foreground;
123
+
124
+ &:hover:not(:disabled) {
125
+ @apply bg-primary-hover;
126
+ }
127
+ }
128
+
129
+ /* Primary + Neutral (Gray) */
130
+ .vif-button--primary.vif-button--neutral {
131
+ background-color: var(--color-neutral-200);
132
+ color: var(--color-neutral-900);
133
+
134
+ &:hover:not(:disabled) {
135
+ background-color: var(--color-neutral-300);
136
+ }
137
+ }
138
+
139
+ /* Primary + Colors */
140
+ .vif-button--primary.vif-button--success {
141
+ @apply bg-success text-success-foreground;
142
+
143
+ &:hover:not(:disabled) {
144
+ @apply bg-success-hover;
145
+ }
146
+ }
147
+
148
+ .vif-button--primary.vif-button--warning {
149
+ @apply bg-warning text-warning-foreground;
150
+
151
+ &:hover:not(:disabled) {
152
+ @apply bg-warning-hover;
153
+ }
154
+ }
155
+
156
+ .vif-button--primary.vif-button--danger {
157
+ @apply bg-danger text-danger-foreground;
158
+
159
+ &:hover:not(:disabled) {
160
+ @apply bg-danger-hover;
161
+ }
162
+ }
163
+
164
+ /* ============================================ */
165
+ /* Secondary Variant */
166
+ /* ============================================ */
167
+
168
+ .vif-button--secondary {
169
+ @apply bg-secondary text-secondary-foreground;
170
+
171
+ &:hover:not(:disabled) {
172
+ @apply bg-secondary-hover;
173
+ }
174
+ }
175
+
176
+ /* Secondary + Colors */
177
+ .vif-button--secondary.vif-button--success {
178
+ @apply bg-success/20 text-success;
179
+
180
+ &:hover:not(:disabled) {
181
+ @apply bg-success/30;
182
+ }
183
+ }
184
+
185
+ .vif-button--secondary.vif-button--warning {
186
+ @apply bg-warning/20 text-warning;
187
+
188
+ &:hover:not(:disabled) {
189
+ @apply bg-warning/30;
190
+ }
191
+ }
192
+
193
+ .vif-button--secondary.vif-button--danger {
194
+ @apply bg-danger/20 text-danger;
195
+
196
+ &:hover:not(:disabled) {
197
+ @apply bg-danger/30;
198
+ }
199
+ }
200
+
201
+ /* ============================================ */
202
+ /* Soft Variant */
203
+ /* ============================================ */
204
+
205
+ .vif-button--soft {
206
+ @apply bg-default text-foreground;
207
+
208
+ &:hover:not(:disabled) {
209
+ @apply bg-default-hover;
210
+ }
211
+ }
212
+
213
+ /* Soft + Neutral (Gray) */
214
+ .vif-button--soft.vif-button--neutral {
215
+ background-color: var(--color-neutral-100);
216
+ color: var(--color-neutral-700);
217
+
218
+ &:hover:not(:disabled) {
219
+ background-color: var(--color-neutral-200);
220
+ }
221
+ }
222
+
223
+ /* Soft + Colors */
224
+ .vif-button--soft.vif-button--brand {
225
+ @apply bg-primary/10 text-primary;
226
+
227
+ &:hover:not(:disabled) {
228
+ @apply bg-primary/20;
229
+ }
230
+ }
231
+
232
+ .vif-button--soft.vif-button--success {
233
+ @apply bg-success/10 text-success;
234
+
235
+ &:hover:not(:disabled) {
236
+ @apply bg-success/20;
237
+ }
238
+ }
239
+
240
+ .vif-button--soft.vif-button--warning {
241
+ @apply bg-warning/10 text-warning;
242
+
243
+ &:hover:not(:disabled) {
244
+ @apply bg-warning/20;
245
+ }
246
+ }
247
+
248
+ .vif-button--soft.vif-button--danger {
249
+ @apply bg-danger/10 text-danger;
250
+
251
+ &:hover:not(:disabled) {
252
+ @apply bg-danger/20;
253
+ }
254
+ }
255
+
256
+ /* ============================================ */
257
+ /* Ghost Variant */
258
+ /* ============================================ */
259
+
260
+ .vif-button--ghost {
261
+ @apply bg-transparent text-foreground;
262
+
263
+ &:hover:not(:disabled) {
264
+ @apply bg-default;
265
+ }
266
+ }
267
+
268
+ /* Ghost + Colors */
269
+ .vif-button--ghost.vif-button--brand {
270
+ @apply bg-transparent text-primary;
271
+
272
+ &:hover:not(:disabled) {
273
+ @apply bg-primary/10;
274
+ }
275
+ }
276
+
277
+ .vif-button--ghost.vif-button--success {
278
+ @apply bg-transparent text-success;
279
+
280
+ &:hover:not(:disabled) {
281
+ @apply bg-success/10;
282
+ }
283
+ }
284
+
285
+ .vif-button--ghost.vif-button--warning {
286
+ @apply bg-transparent text-warning;
287
+
288
+ &:hover:not(:disabled) {
289
+ @apply bg-warning/10;
290
+ }
291
+ }
292
+
293
+ .vif-button--ghost.vif-button--danger {
294
+ @apply bg-transparent text-danger;
295
+
296
+ &:hover:not(:disabled) {
297
+ @apply bg-danger/10;
298
+ }
299
+ }
300
+
301
+ /* ============================================ */
302
+ /* Outline Variant */
303
+ /* ============================================ */
304
+
305
+ .vif-button--outline {
306
+ @apply bg-transparent border-2 border-primary text-primary;
307
+
308
+ &:hover:not(:disabled) {
309
+ @apply bg-primary/10;
310
+ }
311
+ }
312
+
313
+ /* Outline + Neutral (Gray) */
314
+ .vif-button--outline.vif-button--neutral {
315
+ @apply bg-transparent;
316
+ border-color: var(--color-neutral-400);
317
+ color: var(--color-neutral-700);
318
+
319
+ &:hover:not(:disabled) {
320
+ background-color: var(--color-neutral-100);
321
+ }
322
+ }
323
+
324
+ /* Outline + Colors */
325
+ .vif-button--outline.vif-button--success {
326
+ @apply bg-transparent border-success text-success;
327
+
328
+ &:hover:not(:disabled) {
329
+ @apply bg-success/10;
330
+ }
331
+ }
332
+
333
+ .vif-button--outline.vif-button--warning {
334
+ @apply bg-transparent border-warning text-warning;
335
+
336
+ &:hover:not(:disabled) {
337
+ @apply bg-warning/10;
338
+ }
339
+ }
340
+
341
+ .vif-button--outline.vif-button--danger {
342
+ @apply bg-transparent border-danger text-danger;
343
+
344
+ &:hover:not(:disabled) {
345
+ @apply bg-danger/10;
346
+ }
347
+ }
348
+
349
+ /* ============================================ */
350
+ /* Shadow Variant - Modern Multi-layer Shadows */
351
+ /* ============================================ */
352
+
353
+ .vif-button--shadow {
354
+ @apply bg-primary text-primary-foreground;
355
+ box-shadow:
356
+ 0 1px 2px 0 color-mix(in srgb, var(--primary) 20%, transparent),
357
+ 0 4px 12px -2px color-mix(in srgb, var(--primary) 35%, transparent),
358
+ 0 8px 24px -4px color-mix(in srgb, var(--primary) 25%, transparent);
359
+
360
+ &:hover:not(:disabled) {
361
+ @apply bg-primary-hover;
362
+ box-shadow:
363
+ 0 2px 4px 0 color-mix(in srgb, var(--primary) 25%, transparent),
364
+ 0 8px 20px -2px color-mix(in srgb, var(--primary) 45%, transparent),
365
+ 0 16px 32px -4px color-mix(in srgb, var(--primary) 30%, transparent);
366
+ transform: translateY(-2px);
367
+ }
368
+
369
+ &:active:not(:disabled) {
370
+ transform: translateY(0) scale(0.97);
371
+ box-shadow:
372
+ 0 1px 2px 0 color-mix(in srgb, var(--primary) 18%, transparent),
373
+ 0 3px 10px -2px color-mix(in srgb, var(--primary) 30%, transparent),
374
+ 0 6px 18px -4px color-mix(in srgb, var(--primary) 20%, transparent);
375
+ }
376
+ }
377
+
378
+ /* Shadow + Neutral (Gray) */
379
+ .vif-button--shadow.vif-button--neutral {
380
+ background-color: var(--color-neutral-200);
381
+ color: var(--color-neutral-900);
382
+ box-shadow:
383
+ 0 1px 2px 0 rgba(0, 0, 0, 0.1),
384
+ 0 4px 12px -2px rgba(0, 0, 0, 0.15),
385
+ 0 8px 24px -4px rgba(0, 0, 0, 0.12);
386
+
387
+ &:hover:not(:disabled) {
388
+ background-color: var(--color-neutral-300);
389
+ box-shadow:
390
+ 0 2px 4px 0 rgba(0, 0, 0, 0.12),
391
+ 0 8px 20px -2px rgba(0, 0, 0, 0.18),
392
+ 0 16px 32px -4px rgba(0, 0, 0, 0.15);
393
+ transform: translateY(-2px);
394
+ }
395
+
396
+ &:active:not(:disabled) {
397
+ transform: translateY(0) scale(0.97);
398
+ box-shadow:
399
+ 0 1px 2px 0 rgba(0, 0, 0, 0.08),
400
+ 0 3px 10px -2px rgba(0, 0, 0, 0.12),
401
+ 0 6px 18px -4px rgba(0, 0, 0, 0.1);
402
+ }
403
+ }
404
+
405
+ /* Shadow + Success */
406
+ .vif-button--shadow.vif-button--success {
407
+ @apply bg-success text-success-foreground;
408
+ box-shadow:
409
+ 0 1px 2px 0 color-mix(in srgb, var(--success) 20%, transparent),
410
+ 0 4px 12px -2px color-mix(in srgb, var(--success) 35%, transparent),
411
+ 0 8px 24px -4px color-mix(in srgb, var(--success) 25%, transparent);
412
+
413
+ &:hover:not(:disabled) {
414
+ @apply bg-success-hover;
415
+ box-shadow:
416
+ 0 2px 4px 0 color-mix(in srgb, var(--success) 25%, transparent),
417
+ 0 8px 20px -2px color-mix(in srgb, var(--success) 45%, transparent),
418
+ 0 16px 32px -4px color-mix(in srgb, var(--success) 30%, transparent);
419
+ transform: translateY(-2px);
420
+ }
421
+
422
+ &:active:not(:disabled) {
423
+ transform: translateY(0) scale(0.97);
424
+ box-shadow:
425
+ 0 1px 2px 0 color-mix(in srgb, var(--success) 18%, transparent),
426
+ 0 3px 10px -2px color-mix(in srgb, var(--success) 30%, transparent),
427
+ 0 6px 18px -4px color-mix(in srgb, var(--success) 20%, transparent);
428
+ }
429
+ }
430
+
431
+ /* Shadow + Warning */
432
+ .vif-button--shadow.vif-button--warning {
433
+ @apply bg-warning text-warning-foreground;
434
+ box-shadow:
435
+ 0 1px 2px 0 color-mix(in srgb, var(--warning) 20%, transparent),
436
+ 0 4px 12px -2px color-mix(in srgb, var(--warning) 35%, transparent),
437
+ 0 8px 24px -4px color-mix(in srgb, var(--warning) 25%, transparent);
438
+
439
+ &:hover:not(:disabled) {
440
+ @apply bg-warning-hover;
441
+ box-shadow:
442
+ 0 2px 4px 0 color-mix(in srgb, var(--warning) 25%, transparent),
443
+ 0 8px 20px -2px color-mix(in srgb, var(--warning) 45%, transparent),
444
+ 0 16px 32px -4px color-mix(in srgb, var(--warning) 30%, transparent);
445
+ transform: translateY(-2px);
446
+ }
447
+
448
+ &:active:not(:disabled) {
449
+ transform: translateY(0) scale(0.97);
450
+ box-shadow:
451
+ 0 1px 2px 0 color-mix(in srgb, var(--warning) 18%, transparent),
452
+ 0 3px 10px -2px color-mix(in srgb, var(--warning) 30%, transparent),
453
+ 0 6px 18px -4px color-mix(in srgb, var(--warning) 20%, transparent);
454
+ }
455
+ }
456
+
457
+ /* Shadow + Danger */
458
+ .vif-button--shadow.vif-button--danger {
459
+ @apply bg-danger text-danger-foreground;
460
+ box-shadow:
461
+ 0 1px 2px 0 color-mix(in srgb, var(--danger) 20%, transparent),
462
+ 0 4px 12px -2px color-mix(in srgb, var(--danger) 35%, transparent),
463
+ 0 8px 24px -4px color-mix(in srgb, var(--danger) 25%, transparent);
464
+
465
+ &:hover:not(:disabled) {
466
+ @apply bg-danger-hover;
467
+ box-shadow:
468
+ 0 2px 4px 0 color-mix(in srgb, var(--danger) 25%, transparent),
469
+ 0 8px 20px -2px color-mix(in srgb, var(--danger) 45%, transparent),
470
+ 0 16px 32px -4px color-mix(in srgb, var(--danger) 30%, transparent);
471
+ transform: translateY(-2px);
472
+ }
473
+
474
+ &:active:not(:disabled) {
475
+ transform: translateY(0) scale(0.97);
476
+ box-shadow:
477
+ 0 1px 2px 0 color-mix(in srgb, var(--danger) 18%, transparent),
478
+ 0 3px 10px -2px color-mix(in srgb, var(--danger) 30%, transparent),
479
+ 0 6px 18px -4px color-mix(in srgb, var(--danger) 20%, transparent);
480
+ }
481
+ }
482
+
483
+ /* ============================================ */
484
+ /* Modifiers */
485
+ /* ============================================ */
486
+
487
+ /* Icon-only button */
488
+ .vif-button--icon-only {
489
+ @apply w-10 p-0;
490
+
491
+ &.vif-button--xs {
492
+ @apply w-6;
493
+ }
494
+
495
+ &.vif-button--sm {
496
+ @apply w-8;
497
+ }
498
+
499
+ &.vif-button--lg {
500
+ @apply w-12;
501
+ }
502
+
503
+ &.vif-button--xl {
504
+ @apply w-14;
505
+ }
506
+ }
507
+
508
+ /* Rounded (fully circular) */
509
+ .vif-button--rounded {
510
+ border-radius: var(--radius-full);
511
+ }
512
+
513
+ /* Loading state */
514
+ .vif-button--loading {
515
+ @apply pointer-events-none relative;
516
+
517
+ /* Content visibility handled in component */
518
+ }
519
+
520
+ /* Button content wrapper */
521
+ .vif-button__content {
522
+ @apply flex items-center justify-center gap-2;
523
+ position: relative;
524
+ z-index: 1;
525
+ }
526
+
527
+ /* Loader positioning */
528
+ .vif-button__loader {
529
+ @apply absolute inset-0 flex items-center justify-center;
530
+ }
531
+
532
+ /* ============================================ */
533
+ /* Ripple Effect - Vuesax Style */
534
+ /* ============================================ */
535
+
536
+ .vif-button__ripple {
537
+ @apply absolute rounded-full pointer-events-none;
538
+ inline-size: 10px;
539
+ block-size: 10px;
540
+ translate: -50% -50%;
541
+ box-shadow: inset 0px 0px 60px 0px rgba(255, 255, 255, 0.5);
542
+ animation: vif-ripple 1s ease-out;
543
+ z-index: 0;
544
+ }
545
+
546
+ /* Ripple animation */
547
+ @keyframes vif-ripple {
548
+ 0% {
549
+ scale: 0;
550
+ opacity: 1;
551
+ }
552
+ 100% {
553
+ scale: 40;
554
+ opacity: 0;
555
+ }
556
+ }
557
+
558
+ .vif-button--danger {
559
+ @apply bg-danger text-danger-foreground;
560
+
561
+ &:hover:not(:disabled) {
562
+ @apply bg-danger-hover;
563
+ }
564
+ }