@keenmate/pure-admin-core 2.3.0 → 2.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.
@@ -1,548 +1,565 @@
1
- /* ========================================
2
- Button Components
3
- Buttons, button groups, sizes, colors, states, and icon buttons
4
- ======================================== */
5
- @use '../variables' as *;
6
-
7
- // Buttons
8
- .pa-btn {
9
- display: inline-block;
10
- height: $btn-height-base;
11
- padding: $btn-padding-v $btn-padding-h;
12
- border: $btn-border-width solid transparent;
13
- border-radius: $border-radius;
14
- font-size: $font-size-sm;
15
- font-weight: $font-weight-medium;
16
- text-align: center;
17
- text-decoration: none;
18
- cursor: pointer;
19
- transition: all $transition-fast $easing-snappy;
20
- background: none;
21
- color: var(--pa-text-color-1);
22
-
23
- &:hover {
24
- transform: translateY($btn-hover-lift);
25
- }
26
-
27
- &--primary {
28
- background-color: var(--pa-accent);
29
- border-color: var(--pa-accent);
30
- color: var(--pa-btn-primary-text);
31
-
32
- &:hover {
33
- background-color: var(--pa-accent);
34
- filter: brightness($btn-hover-brightness);
35
- }
36
- }
37
-
38
- &--secondary {
39
- background-color: transparent;
40
- border-color: var(--pa-border-color);
41
- color: var(--pa-text-color-1);
42
-
43
- &:hover {
44
- background-color: var(--pa-main-bg);
45
- border-color: var(--pa-accent);
46
- }
47
- }
48
-
49
- &--xs {
50
- height: $btn-height-xs;
51
- padding: $btn-padding-xs-v $btn-padding-xs-h;
52
- font-size: $font-size-xs;
53
- }
54
-
55
- &--sm {
56
- height: $btn-height-sm;
57
- padding: $btn-padding-sm-v $btn-padding-sm-h;
58
- font-size: $font-size-sm;
59
- }
60
-
61
- &--lg {
62
- height: $btn-height-lg;
63
- padding: $btn-padding-lg-v $btn-padding-lg-h;
64
- font-size: $font-size-base;
65
- }
66
-
67
- &--xl {
68
- height: $btn-height-xl;
69
- padding: $btn-padding-xl-v $btn-padding-xl-h;
70
- font-size: $font-size-lg;
71
- }
72
-
73
- // Button variants (colors)
74
- &--success {
75
- background-color: var(--pa-btn-success-bg);
76
- border-color: var(--pa-btn-success-bg);
77
- color: var(--pa-btn-success-text);
78
-
79
- &:hover {
80
- background-color: var(--pa-btn-success-bg-hover);
81
- border-color: var(--pa-btn-success-bg-hover);
82
- }
83
- }
84
-
85
- &--warning {
86
- background-color: var(--pa-btn-warning-bg);
87
- border-color: var(--pa-btn-warning-bg);
88
- color: var(--pa-btn-warning-text);
89
-
90
- &:hover {
91
- background-color: var(--pa-btn-warning-bg-hover);
92
- border-color: var(--pa-btn-warning-bg-hover);
93
- }
94
- }
95
-
96
- &--danger {
97
- background-color: var(--pa-btn-danger-bg);
98
- border-color: var(--pa-btn-danger-bg);
99
- color: var(--pa-btn-danger-text);
100
-
101
- &:hover {
102
- background-color: var(--pa-btn-danger-bg-hover);
103
- border-color: var(--pa-btn-danger-bg-hover);
104
- }
105
- }
106
-
107
- &--info {
108
- background-color: var(--pa-btn-info-bg);
109
- border-color: var(--pa-btn-info-bg);
110
- color: var(--pa-btn-info-text);
111
-
112
- &:hover {
113
- background-color: var(--pa-btn-info-bg-hover);
114
- border-color: var(--pa-btn-info-bg-hover);
115
- }
116
- }
117
-
118
- &--light {
119
- background-color: var(--pa-btn-light-bg);
120
- border-color: var(--pa-btn-light-bg);
121
- color: var(--pa-btn-light-text);
122
-
123
- &:hover {
124
- background-color: var(--pa-btn-light-bg-hover);
125
- border-color: var(--pa-btn-light-bg-hover);
126
- }
127
- }
128
-
129
- &--dark {
130
- background-color: var(--pa-btn-dark-bg);
131
- border-color: var(--pa-btn-dark-bg);
132
- color: var(--pa-btn-dark-text);
133
-
134
- &:hover {
135
- background-color: var(--pa-btn-dark-bg-hover);
136
- border-color: var(--pa-btn-dark-bg-hover);
137
- }
138
- }
139
-
140
- // Outline variants
141
- &--outline-primary {
142
- background-color: transparent;
143
- border-color: var(--pa-accent);
144
- color: var(--pa-accent);
145
-
146
- &:hover {
147
- background-color: var(--pa-accent);
148
- color: var(--pa-btn-primary-text);
149
- }
150
- }
151
-
152
- &--outline-secondary {
153
- background-color: transparent;
154
- border-color: var(--pa-btn-secondary-bg);
155
- color: var(--pa-btn-secondary-bg);
156
-
157
- &:hover {
158
- background-color: var(--pa-btn-secondary-bg);
159
- color: var(--pa-btn-secondary-text);
160
- }
161
- }
162
-
163
- &--outline-success {
164
- background-color: transparent;
165
- border-color: var(--pa-btn-success-bg);
166
- color: var(--pa-btn-success-bg);
167
-
168
- &:hover {
169
- background-color: var(--pa-btn-success-bg);
170
- color: var(--pa-btn-success-text);
171
- }
172
- }
173
-
174
- &--outline-warning {
175
- background-color: transparent;
176
- border-color: var(--pa-btn-warning-bg);
177
- color: var(--pa-btn-warning-bg);
178
-
179
- &:hover {
180
- background-color: var(--pa-btn-warning-bg);
181
- color: var(--pa-btn-warning-text);
182
- }
183
- }
184
-
185
- &--outline-danger {
186
- background-color: transparent;
187
- border-color: var(--pa-btn-danger-bg);
188
- color: var(--pa-btn-danger-bg);
189
-
190
- &:hover {
191
- background-color: var(--pa-btn-danger-bg);
192
- color: var(--pa-btn-danger-text);
193
- }
194
- }
195
-
196
- &--outline-info {
197
- background-color: transparent;
198
- border-color: var(--pa-btn-info-bg);
199
- color: var(--pa-btn-info-bg);
200
-
201
- &:hover {
202
- background-color: var(--pa-btn-info-bg);
203
- color: var(--pa-btn-info-text);
204
- }
205
- }
206
-
207
- // Theme color slot variants (color-1 through color-9)
208
- @for $i from 1 through 9 {
209
- &--color-#{$i} {
210
- background-color: var(--pa-color-#{$i});
211
- border-color: var(--pa-color-#{$i});
212
- color: var(--pa-color-#{$i}-text);
213
-
214
- &:hover {
215
- filter: brightness($btn-hover-brightness);
216
- }
217
- }
218
-
219
- &--outline-color-#{$i} {
220
- background-color: transparent;
221
- border-color: var(--pa-color-#{$i});
222
- color: var(--pa-color-#{$i});
223
-
224
- &:hover {
225
- background-color: var(--pa-color-#{$i});
226
- color: var(--pa-color-#{$i}-text);
227
- }
228
- }
229
- }
230
-
231
- // Button states
232
- &:disabled {
233
- opacity: $btn-disabled-opacity;
234
- cursor: not-allowed;
235
- transform: none !important;
236
- }
237
-
238
- &--loading {
239
- position: relative;
240
- pointer-events: none;
241
- -webkit-text-fill-color: transparent; // Hide text but preserve layout and currentColor for spinner
242
- transition: none;
243
-
244
- .pa-btn__spinner {
245
- position: absolute;
246
- top: 0;
247
- left: 0;
248
- right: 0;
249
- bottom: 0;
250
- margin: auto;
251
- width: $spinner-size;
252
- height: $spinner-size;
253
- border: $spinner-border-width solid transparent;
254
- border-top: $spinner-border-width solid currentColor;
255
- border-radius: 50%;
256
- animation: pa-spin $animation-spin-duration linear infinite;
257
- }
258
- }
259
-
260
- // Ripple effect
261
- &--ripple {
262
- position: relative;
263
- overflow: hidden;
264
-
265
- &::before {
266
- content: '';
267
- position: absolute;
268
- top: 50%;
269
- left: 50%;
270
- width: 0;
271
- height: 0;
272
- border-radius: 50%;
273
- background: $ripple-color;
274
- transform: translate(-50%, -50%);
275
- transition: width $ripple-transition-duration ease, height $ripple-transition-duration ease;
276
- pointer-events: none;
277
- }
278
-
279
- &.pa-btn--ripple-active::before {
280
- width: $ripple-size;
281
- height: $ripple-size;
282
- }
283
- }
284
-
285
- // Block button
286
- &--block {
287
- width: 100%;
288
- display: block;
289
- }
290
-
291
- // Icon buttons
292
- &--icon-only {
293
- width: $btn-icon-only-size;
294
- height: $btn-icon-only-size;
295
- padding: 0;
296
- display: flex;
297
- align-items: center;
298
- justify-content: center;
299
- line-height: 1;
300
-
301
- // Size-specific icon-only dimensions
302
- &.pa-btn--xs {
303
- width: $btn-icon-only-size-xs;
304
- height: $btn-icon-only-size-xs;
305
- }
306
-
307
- &.pa-btn--sm {
308
- width: $btn-icon-only-size-sm;
309
- height: $btn-icon-only-size-sm;
310
- }
311
-
312
- &.pa-btn--lg {
313
- width: $btn-icon-only-size-lg;
314
- height: $btn-icon-only-size-lg;
315
- }
316
-
317
- &.pa-btn--xl {
318
- width: $btn-icon-only-size-xl;
319
- height: $btn-icon-only-size-xl;
320
- }
321
- }
322
-
323
- &__icon {
324
- margin-inline-end: $btn-icon-margin; // RTL: flips to margin-left
325
-
326
- &:last-child {
327
- margin-inline-end: 0;
328
- margin-inline-start: $btn-icon-margin; // RTL: flips to margin-right
329
- }
330
- }
331
-
332
- // Buttons with icons align to start like sidebar menu items
333
- &:has(.pa-btn__icon) {
334
- text-align: start; // RTL: flips to right
335
- display: inline-flex;
336
- align-items: center;
337
- gap: $spacing-sm;
338
-
339
- .pa-btn__icon {
340
- width: $sidebar-icon-size;
341
- min-width: $sidebar-icon-size;
342
- // No fixed height - let button padding control height
343
- display: flex;
344
- align-items: center;
345
- justify-content: center;
346
- flex-shrink: 0;
347
- margin: 0;
348
-
349
- &:last-child {
350
- margin: 0;
351
- }
352
- }
353
- }
354
-
355
- // Content alignment modifiers (position content within button)
356
- // Button always keeps its horizontal padding (0.75rem on both sides)
357
- // These classes control content position and remove icon padding on aligned sides
358
-
359
- &--align-start {
360
- justify-content: flex-start;
361
-
362
- .pa-btn__icon {
363
- padding-inline-start: 0; // RTL: flips to padding-right
364
- }
365
- }
366
-
367
- &--align-end {
368
- justify-content: flex-end;
369
-
370
- .pa-btn__icon {
371
- padding-inline-end: 0; // RTL: flips to padding-left
372
- }
373
- }
374
-
375
- &--align-center {
376
- justify-content: center;
377
- }
378
-
379
- &--align-justify {
380
- justify-content: space-between;
381
-
382
- .pa-btn__icon:first-child {
383
- padding-inline-start: 0; // RTL: flips to padding-right
384
- }
385
-
386
- // Remove padding from last element (text or icon)
387
- > *:last-child {
388
- padding-inline-end: 0; // RTL: flips to padding-left
389
- }
390
- }
391
- }
392
-
393
- // Button Groups
394
- .pa-btn-group {
395
- display: inline-flex;
396
- gap: $btn-group-gap;
397
- flex-wrap: wrap;
398
- align-items: center;
399
-
400
- // === Direction Variants ===
401
- &--vertical {
402
- flex-direction: column;
403
- align-items: flex-start;
404
- }
405
-
406
- // === Vertical Alignment Variants ===
407
- &--vertical#{&}--center {
408
- align-items: center;
409
- }
410
-
411
- &--vertical#{&}--end {
412
- align-items: flex-end;
413
- }
414
-
415
- &--vertical#{&}--stretch {
416
- align-items: stretch;
417
-
418
- .pa-btn {
419
- width: 100%;
420
- }
421
- }
422
-
423
- // === Responsive Direction Modifiers ===
424
- @each $bp, $min-width in $grid-breakpoints {
425
- &--#{$bp}-vertical {
426
- @media (min-width: $min-width) {
427
- flex-direction: column;
428
- align-items: flex-start;
429
- }
430
- }
431
-
432
- &--#{$bp}-horizontal {
433
- @media (min-width: $min-width) {
434
- flex-direction: row;
435
- align-items: center;
436
- }
437
- }
438
- }
439
-
440
- // === No Wrap Variant ===
441
- &--nowrap {
442
- flex-wrap: nowrap;
443
- }
444
-
445
- // Ensure tooltips on buttons appear above siblings
446
- .pa-btn.pa-tooltip:hover {
447
- position: relative;
448
- z-index: $z-index-modal;
449
- }
450
-
451
- }
452
-
453
- // === Split Button (primary action + dropdown toggle) ===
454
- .pa-btn-split {
455
- position: relative;
456
- display: inline-flex;
457
-
458
- // RTL: reverse order so toggle is on inline-start side
459
- [dir="rtl"] & {
460
- flex-direction: row-reverse;
461
- }
462
-
463
- // Joined buttons with no gap
464
- .pa-btn {
465
- border-radius: 0;
466
-
467
- &:first-child {
468
- border-start-start-radius: $border-radius;
469
- border-end-start-radius: $border-radius;
470
- border-inline-end: none;
471
- }
472
- }
473
-
474
- // Toggle button (chevron) - fixed square width
475
- &__toggle {
476
- border-start-end-radius: $border-radius;
477
- border-end-end-radius: $border-radius;
478
- border-inline-start: $border-width-base solid rgba(255, 255, 255, 0.25);
479
- border-inline-end: none;
480
- padding-inline: 0;
481
- display: inline-flex;
482
- align-items: center;
483
- justify-content: center;
484
- width: $btn-height-base;
485
- min-width: $btn-height-base;
486
-
487
- &.pa-btn--xs { width: $btn-height-xs; min-width: $btn-height-xs; }
488
- &.pa-btn--sm { width: $btn-height-sm; min-width: $btn-height-sm; }
489
- &.pa-btn--lg { width: $btn-height-lg; min-width: $btn-height-lg; }
490
- &.pa-btn--xl { width: $btn-height-xl; min-width: $btn-height-xl; }
491
- }
492
-
493
- // Chevron icon - opt-in rotation on open
494
- &__chevron {
495
- transition: transform $transition-fast $easing-snappy;
496
- }
497
-
498
- &--open &__chevron {
499
- transform: rotate(180deg);
500
- }
501
-
502
- // Dropdown menu (moved to body and positioned by Floating UI)
503
- &__menu {
504
- display: none;
505
- position: fixed;
506
- top: 0;
507
- left: 0;
508
- width: max-content;
509
- background: var(--pa-card-bg);
510
- border: $border-width-base solid var(--pa-border-color);
511
- border-radius: $border-radius;
512
- box-shadow: $shadow-2xl;
513
- z-index: $z-index-dropdown;
514
- padding: $spacing-xs 0;
515
-
516
- &--open {
517
- display: block;
518
- }
519
- }
520
-
521
- // Menu items
522
- &__item {
523
- display: block;
524
- width: 100%;
525
- padding: $spacing-sm $spacing-base;
526
- border: none;
527
- background: none;
528
- text-align: start;
529
- font-size: $font-size-sm;
530
- color: var(--pa-text-color);
531
- cursor: pointer;
532
- white-space: nowrap;
533
-
534
- &:hover {
535
- background-color: var(--pa-accent-hover);
536
- }
537
-
538
- &--danger {
539
- color: var(--pa-btn-danger-bg);
540
-
541
- &:hover {
542
- background-color: var(--pa-btn-danger-bg);
543
- color: var(--pa-btn-danger-text);
544
- }
545
- }
546
- }
547
- }
548
-
1
+ /* ========================================
2
+ Button Components
3
+ Buttons, button groups, sizes, colors, states, and icon buttons
4
+ ======================================== */
5
+ @use '../variables' as *;
6
+
7
+ // Buttons
8
+ .pa-btn {
9
+ display: inline-block;
10
+ height: $btn-height-base;
11
+ padding: $btn-padding-v $btn-padding-h;
12
+ border: $btn-border-width solid transparent;
13
+ border-radius: $border-radius;
14
+ font-size: $font-size-sm;
15
+ font-weight: $font-weight-medium;
16
+ text-align: center;
17
+ text-decoration: none;
18
+ cursor: pointer;
19
+ transition: all $transition-fast $easing-snappy;
20
+ background: none;
21
+ color: var(--pa-text-color-1);
22
+
23
+ &:hover {
24
+ transform: translateY($btn-hover-lift);
25
+ }
26
+
27
+ &--primary {
28
+ background-color: var(--pa-accent);
29
+ border-color: var(--pa-accent);
30
+ color: var(--pa-btn-primary-text);
31
+
32
+ &:hover {
33
+ background-color: var(--pa-accent);
34
+ filter: brightness($btn-hover-brightness);
35
+ }
36
+ }
37
+
38
+ &--secondary {
39
+ background-color: transparent;
40
+ border-color: var(--pa-border-color);
41
+ color: var(--pa-text-color-1);
42
+
43
+ &:hover {
44
+ background-color: var(--pa-main-bg);
45
+ border-color: var(--pa-accent);
46
+ }
47
+ }
48
+
49
+ &--xs {
50
+ height: $btn-height-xs;
51
+ padding: $btn-padding-xs-v $btn-padding-xs-h;
52
+ font-size: $font-size-xs;
53
+ }
54
+
55
+ &--sm {
56
+ height: $btn-height-sm;
57
+ padding: $btn-padding-sm-v $btn-padding-sm-h;
58
+ font-size: $font-size-sm;
59
+ }
60
+
61
+ &--lg {
62
+ height: $btn-height-lg;
63
+ padding: $btn-padding-lg-v $btn-padding-lg-h;
64
+ font-size: $font-size-base;
65
+ }
66
+
67
+ &--xl {
68
+ height: $btn-height-xl;
69
+ padding: $btn-padding-xl-v $btn-padding-xl-h;
70
+ font-size: $font-size-lg;
71
+ }
72
+
73
+ // Button variants (colors)
74
+ &--success {
75
+ background-color: var(--pa-btn-success-bg);
76
+ border-color: var(--pa-btn-success-bg);
77
+ color: var(--pa-btn-success-text);
78
+
79
+ &:hover {
80
+ background-color: var(--pa-btn-success-bg-hover);
81
+ border-color: var(--pa-btn-success-bg-hover);
82
+ }
83
+ }
84
+
85
+ &--warning {
86
+ background-color: var(--pa-btn-warning-bg);
87
+ border-color: var(--pa-btn-warning-bg);
88
+ color: var(--pa-btn-warning-text);
89
+
90
+ &:hover {
91
+ background-color: var(--pa-btn-warning-bg-hover);
92
+ border-color: var(--pa-btn-warning-bg-hover);
93
+ }
94
+ }
95
+
96
+ &--danger {
97
+ background-color: var(--pa-btn-danger-bg);
98
+ border-color: var(--pa-btn-danger-bg);
99
+ color: var(--pa-btn-danger-text);
100
+
101
+ &:hover {
102
+ background-color: var(--pa-btn-danger-bg-hover);
103
+ border-color: var(--pa-btn-danger-bg-hover);
104
+ }
105
+ }
106
+
107
+ &--info {
108
+ background-color: var(--pa-btn-info-bg);
109
+ border-color: var(--pa-btn-info-bg);
110
+ color: var(--pa-btn-info-text);
111
+
112
+ &:hover {
113
+ background-color: var(--pa-btn-info-bg-hover);
114
+ border-color: var(--pa-btn-info-bg-hover);
115
+ }
116
+ }
117
+
118
+ &--light {
119
+ background-color: var(--pa-btn-light-bg);
120
+ border-color: var(--pa-btn-light-bg);
121
+ color: var(--pa-btn-light-text);
122
+
123
+ &:hover {
124
+ background-color: var(--pa-btn-light-bg-hover);
125
+ border-color: var(--pa-btn-light-bg-hover);
126
+ }
127
+ }
128
+
129
+ &--dark {
130
+ background-color: var(--pa-btn-dark-bg);
131
+ border-color: var(--pa-btn-dark-bg);
132
+ color: var(--pa-btn-dark-text);
133
+
134
+ &:hover {
135
+ background-color: var(--pa-btn-dark-bg-hover);
136
+ border-color: var(--pa-btn-dark-bg-hover);
137
+ }
138
+ }
139
+
140
+ // Outline variants
141
+ &--outline-primary {
142
+ background-color: transparent;
143
+ border-color: var(--pa-accent);
144
+ color: var(--pa-accent);
145
+
146
+ &:hover {
147
+ background-color: var(--pa-accent);
148
+ color: var(--pa-btn-primary-text);
149
+ }
150
+ }
151
+
152
+ &--outline-secondary {
153
+ background-color: transparent;
154
+ border-color: var(--pa-btn-secondary-bg);
155
+ color: var(--pa-btn-secondary-bg);
156
+
157
+ &:hover {
158
+ background-color: var(--pa-btn-secondary-bg);
159
+ color: var(--pa-btn-secondary-text);
160
+ }
161
+ }
162
+
163
+ &--outline-success {
164
+ background-color: transparent;
165
+ border-color: var(--pa-btn-success-bg);
166
+ color: var(--pa-btn-success-bg);
167
+
168
+ &:hover {
169
+ background-color: var(--pa-btn-success-bg);
170
+ color: var(--pa-btn-success-text);
171
+ }
172
+ }
173
+
174
+ &--outline-warning {
175
+ background-color: transparent;
176
+ border-color: var(--pa-btn-warning-bg);
177
+ color: var(--pa-btn-warning-bg);
178
+
179
+ &:hover {
180
+ background-color: var(--pa-btn-warning-bg);
181
+ color: var(--pa-btn-warning-text);
182
+ }
183
+ }
184
+
185
+ &--outline-danger {
186
+ background-color: transparent;
187
+ border-color: var(--pa-btn-danger-bg);
188
+ color: var(--pa-btn-danger-bg);
189
+
190
+ &:hover {
191
+ background-color: var(--pa-btn-danger-bg);
192
+ color: var(--pa-btn-danger-text);
193
+ }
194
+ }
195
+
196
+ &--outline-info {
197
+ background-color: transparent;
198
+ border-color: var(--pa-btn-info-bg);
199
+ color: var(--pa-btn-info-bg);
200
+
201
+ &:hover {
202
+ background-color: var(--pa-btn-info-bg);
203
+ color: var(--pa-btn-info-text);
204
+ }
205
+ }
206
+
207
+ // Theme color slot variants (color-1 through color-9)
208
+ @for $i from 1 through 9 {
209
+ &--color-#{$i} {
210
+ background-color: var(--pa-color-#{$i});
211
+ border-color: var(--pa-color-#{$i});
212
+ color: var(--pa-color-#{$i}-text);
213
+
214
+ &:hover {
215
+ filter: brightness($btn-hover-brightness);
216
+ }
217
+ }
218
+
219
+ &--outline-color-#{$i} {
220
+ background-color: transparent;
221
+ border-color: var(--pa-color-#{$i});
222
+ color: var(--pa-color-#{$i});
223
+
224
+ &:hover {
225
+ background-color: var(--pa-color-#{$i});
226
+ color: var(--pa-color-#{$i}-text);
227
+ }
228
+ }
229
+ }
230
+
231
+ // Button states
232
+ &:disabled {
233
+ opacity: $btn-disabled-opacity;
234
+ cursor: not-allowed;
235
+ transform: none !important;
236
+ }
237
+
238
+ &--loading {
239
+ position: relative;
240
+ pointer-events: none;
241
+ -webkit-text-fill-color: transparent; // Hide text but preserve layout and currentColor for spinner
242
+ transition: none;
243
+
244
+ .pa-btn__spinner {
245
+ position: absolute;
246
+ top: 0;
247
+ left: 0;
248
+ right: 0;
249
+ bottom: 0;
250
+ margin: auto;
251
+ width: $spinner-size;
252
+ height: $spinner-size;
253
+ border: $spinner-border-width solid transparent;
254
+ border-top: $spinner-border-width solid currentColor;
255
+ border-radius: 50%;
256
+ animation: pa-spin $animation-spin-duration linear infinite;
257
+ }
258
+ }
259
+
260
+ // Ripple effect
261
+ &--ripple {
262
+ position: relative;
263
+ overflow: hidden;
264
+
265
+ &::before {
266
+ content: '';
267
+ position: absolute;
268
+ top: 50%;
269
+ left: 50%;
270
+ width: 0;
271
+ height: 0;
272
+ border-radius: 50%;
273
+ background: $ripple-color;
274
+ transform: translate(-50%, -50%);
275
+ transition: width $ripple-transition-duration ease, height $ripple-transition-duration ease;
276
+ pointer-events: none;
277
+ }
278
+
279
+ &.pa-btn--ripple-active::before {
280
+ width: $ripple-size;
281
+ height: $ripple-size;
282
+ }
283
+ }
284
+
285
+ // Block button
286
+ &--block {
287
+ width: 100%;
288
+ display: block;
289
+ }
290
+
291
+ // Icon buttons
292
+ &--icon-only {
293
+ width: $btn-icon-only-size;
294
+ height: $btn-icon-only-size;
295
+ padding: 0;
296
+ display: flex;
297
+ align-items: center;
298
+ justify-content: center;
299
+ line-height: 1;
300
+
301
+ // Size-specific icon-only dimensions
302
+ &.pa-btn--xs {
303
+ width: $btn-icon-only-size-xs;
304
+ height: $btn-icon-only-size-xs;
305
+ }
306
+
307
+ &.pa-btn--sm {
308
+ width: $btn-icon-only-size-sm;
309
+ height: $btn-icon-only-size-sm;
310
+ }
311
+
312
+ &.pa-btn--lg {
313
+ width: $btn-icon-only-size-lg;
314
+ height: $btn-icon-only-size-lg;
315
+ }
316
+
317
+ &.pa-btn--xl {
318
+ width: $btn-icon-only-size-xl;
319
+ height: $btn-icon-only-size-xl;
320
+ }
321
+ }
322
+
323
+ &__icon {
324
+ margin-inline-end: $btn-icon-margin; // RTL: flips to margin-left
325
+
326
+ &:last-child {
327
+ margin-inline-end: 0;
328
+ margin-inline-start: $btn-icon-margin; // RTL: flips to margin-right
329
+ }
330
+ }
331
+
332
+ &__label {
333
+ flex: 0 1 auto;
334
+ }
335
+
336
+ // Buttons with icons align to start like sidebar menu items
337
+ &:has(.pa-btn__icon) {
338
+ text-align: start; // RTL: flips to right
339
+ display: inline-flex;
340
+ align-items: center;
341
+ gap: $spacing-sm;
342
+
343
+ .pa-btn__icon {
344
+ width: $sidebar-icon-size;
345
+ min-width: $sidebar-icon-size;
346
+ // No fixed height - let button padding control height
347
+ display: flex;
348
+ align-items: center;
349
+ justify-content: center;
350
+ flex-shrink: 0;
351
+ margin: 0;
352
+
353
+ &:last-child {
354
+ margin: 0;
355
+ }
356
+ }
357
+ }
358
+
359
+ // Content alignment modifiers (position content within button)
360
+ // Button always keeps its horizontal padding (0.75rem on both sides)
361
+ // These classes control content position and remove icon padding on aligned sides
362
+
363
+ &--align-start {
364
+ justify-content: flex-start;
365
+
366
+ .pa-btn__icon {
367
+ padding-inline-start: 0; // RTL: flips to padding-right
368
+ }
369
+ }
370
+
371
+ &--align-end {
372
+ justify-content: flex-end;
373
+
374
+ .pa-btn__icon {
375
+ padding-inline-end: 0; // RTL: flips to padding-left
376
+ }
377
+ }
378
+
379
+ &--align-center {
380
+ justify-content: center;
381
+
382
+ .pa-btn__label {
383
+ flex: 1;
384
+ text-align: center;
385
+ }
386
+ }
387
+
388
+ &--align-justify {
389
+ justify-content: space-between;
390
+
391
+ .pa-btn__icon:first-child {
392
+ padding-inline-start: 0; // RTL: flips to padding-right
393
+ }
394
+
395
+ // Remove padding from last element (text or icon)
396
+ > *:last-child {
397
+ padding-inline-end: 0; // RTL: flips to padding-left
398
+ }
399
+ }
400
+ }
401
+
402
+ // Button Groups
403
+ .pa-btn-group {
404
+ display: inline-flex;
405
+ gap: $btn-group-gap;
406
+ flex-wrap: wrap;
407
+ align-items: center;
408
+
409
+ // === Direction Variants ===
410
+ &--vertical {
411
+ flex-direction: column;
412
+ align-items: flex-start;
413
+ }
414
+
415
+ // === Vertical Alignment Variants ===
416
+ &--vertical#{&}--center {
417
+ align-items: center;
418
+ }
419
+
420
+ &--vertical#{&}--end {
421
+ align-items: flex-end;
422
+ }
423
+
424
+ &--vertical#{&}--stretch {
425
+ align-items: stretch;
426
+
427
+ .pa-btn {
428
+ width: 100%;
429
+ }
430
+ }
431
+
432
+ // === Responsive Direction Modifiers ===
433
+ @each $bp, $min-width in $grid-breakpoints {
434
+ &--#{$bp}-vertical {
435
+ @media (min-width: $min-width) {
436
+ flex-direction: column;
437
+ align-items: flex-start;
438
+ }
439
+ }
440
+
441
+ &--#{$bp}-horizontal {
442
+ @media (min-width: $min-width) {
443
+ flex-direction: row;
444
+ align-items: center;
445
+ }
446
+ }
447
+ }
448
+
449
+ // === No Wrap Variant ===
450
+ &--nowrap {
451
+ flex-wrap: nowrap;
452
+ }
453
+
454
+ // Ensure tooltips on buttons appear above siblings
455
+ .pa-btn.pa-tooltip:hover {
456
+ position: relative;
457
+ z-index: $z-index-modal;
458
+ }
459
+
460
+ }
461
+
462
+ // === Split Button (primary action + dropdown toggle) ===
463
+ .pa-btn-split {
464
+ position: relative;
465
+ display: inline-flex;
466
+
467
+ // Joined buttons with no gap
468
+ .pa-btn {
469
+ border-radius: 0;
470
+
471
+ &:first-child {
472
+ border-start-start-radius: $border-radius;
473
+ border-end-start-radius: $border-radius;
474
+ border-inline-end: none;
475
+ }
476
+ }
477
+
478
+ // Toggle button (chevron) - fixed square width
479
+ &__toggle {
480
+ border-start-end-radius: $border-radius;
481
+ border-end-end-radius: $border-radius;
482
+ border-inline-start: $border-width-base solid rgba(255, 255, 255, 0.25);
483
+ padding-inline: 0;
484
+ display: inline-flex;
485
+ align-items: center;
486
+ justify-content: center;
487
+ width: $btn-height-base;
488
+ min-width: $btn-height-base;
489
+
490
+ &.pa-btn--xs { width: $btn-height-xs; min-width: $btn-height-xs; }
491
+ &.pa-btn--sm { width: $btn-height-sm; min-width: $btn-height-sm; }
492
+ &.pa-btn--lg { width: $btn-height-lg; min-width: $btn-height-lg; }
493
+ &.pa-btn--xl { width: $btn-height-xl; min-width: $btn-height-xl; }
494
+ }
495
+
496
+ // Chevron icon - opt-in rotation on open
497
+ &__chevron {
498
+ transition: transform $transition-fast $easing-snappy;
499
+ }
500
+
501
+ &--open &__chevron {
502
+ transform: rotate(180deg);
503
+ }
504
+
505
+ // Dropdown menu (moved to body and positioned by Floating UI)
506
+ &__menu {
507
+ display: none;
508
+ flex-direction: column;
509
+ gap: $spacing-xs;
510
+ position: fixed;
511
+ top: 0;
512
+ left: 0;
513
+ width: max-content;
514
+ background: var(--pa-card-bg);
515
+ border: $border-width-base solid var(--pa-border-color);
516
+ border-radius: $border-radius;
517
+ box-shadow: $shadow-2xl;
518
+ z-index: $z-index-dropdown;
519
+ padding: $spacing-xs 0;
520
+
521
+ &--open {
522
+ display: flex;
523
+ }
524
+ }
525
+
526
+ // Menu items
527
+ &__item {
528
+ display: flex;
529
+ align-items: center;
530
+ gap: $spacing-sm;
531
+ width: 100%;
532
+ padding: $spacing-sm $spacing-base;
533
+ border: none;
534
+ background: none;
535
+ text-align: start;
536
+ font-size: $font-size-sm;
537
+ color: var(--pa-text-color);
538
+ cursor: pointer;
539
+ white-space: nowrap;
540
+
541
+ &:hover {
542
+ background-color: var(--pa-accent-hover);
543
+ }
544
+
545
+ &--danger {
546
+ color: var(--pa-btn-danger-bg);
547
+
548
+ &:hover {
549
+ background-color: var(--pa-btn-danger-bg);
550
+ color: var(--pa-btn-danger-text);
551
+ }
552
+ }
553
+ }
554
+
555
+ &__item-icon {
556
+ width: $sidebar-icon-size;
557
+ min-width: $sidebar-icon-size;
558
+ display: flex;
559
+ align-items: center;
560
+ justify-content: center;
561
+ flex-shrink: 0;
562
+ opacity: 0.7;
563
+ }
564
+ }
565
+