@noatgnu/cupcake-core 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.
@@ -0,0 +1,494 @@
1
+ // =============================================================================
2
+ // CUPCAKE CORE - Component Styles
3
+ // =============================================================================
4
+ // Pre-built component styles that can be used across cupcake applications
5
+
6
+ @import './variables';
7
+ @import './mixins';
8
+
9
+ // =============================================================================
10
+ // GLOBAL CUPCAKE STYLES
11
+ // =============================================================================
12
+
13
+ body {
14
+ font-family: $cupcake-font-family-base;
15
+ line-height: 1.6;
16
+ color: var(--cupcake-text);
17
+ background-color: var(--cupcake-bg-secondary);
18
+ transition: var(--cupcake-transition);
19
+ }
20
+
21
+ // =============================================================================
22
+ // NAVIGATION COMPONENTS
23
+ // =============================================================================
24
+
25
+ .cupcake-navbar {
26
+ background-color: var(--cupcake-card-bg);
27
+ border-bottom: 1px solid var(--cupcake-border);
28
+ box-shadow: 0 1px 3px var(--cupcake-shadow);
29
+
30
+ .navbar-brand {
31
+ font-weight: map-get($cupcake-font-weights, semibold);
32
+ font-size: map-get($cupcake-font-sizes, lg);
33
+ color: var(--cupcake-primary);
34
+ }
35
+
36
+ .nav-link {
37
+ color: var(--cupcake-text);
38
+ transition: var(--cupcake-transition-fast);
39
+
40
+ &:hover,
41
+ &:focus {
42
+ color: var(--cupcake-primary);
43
+ }
44
+
45
+ &.active {
46
+ color: var(--cupcake-primary);
47
+ font-weight: map-get($cupcake-font-weights, medium);
48
+ }
49
+ }
50
+ }
51
+
52
+ .cupcake-breadcrumb {
53
+ background-color: var(--cupcake-bg-secondary);
54
+ border-radius: var(--cupcake-border-radius);
55
+ padding: var(--cupcake-spacing-sm) var(--cupcake-spacing-md);
56
+
57
+ .breadcrumb-item {
58
+ + .breadcrumb-item::before {
59
+ color: var(--cupcake-text-muted);
60
+ }
61
+
62
+ &.active {
63
+ color: var(--cupcake-text);
64
+ font-weight: map-get($cupcake-font-weights, medium);
65
+ }
66
+
67
+ a {
68
+ color: var(--cupcake-primary);
69
+ text-decoration: none;
70
+
71
+ &:hover {
72
+ text-decoration: underline;
73
+ }
74
+ }
75
+ }
76
+ }
77
+
78
+ // =============================================================================
79
+ // CARD COMPONENTS
80
+ // =============================================================================
81
+
82
+ .cupcake-card {
83
+ @include cupcake-card();
84
+
85
+ .cupcake-card-header {
86
+ background-color: var(--cupcake-card-header-bg);
87
+ border-bottom: 1px solid var(--cupcake-card-border);
88
+ padding: var(--cupcake-spacing-md);
89
+ font-weight: map-get($cupcake-font-weights, semibold);
90
+
91
+ h1, h2, h3, h4, h5, h6 {
92
+ margin-bottom: 0;
93
+ }
94
+ }
95
+
96
+ .cupcake-card-body {
97
+ padding: var(--cupcake-spacing-md);
98
+ }
99
+
100
+ .cupcake-card-footer {
101
+ background-color: var(--cupcake-card-header-bg);
102
+ border-top: 1px solid var(--cupcake-card-border);
103
+ padding: var(--cupcake-spacing-sm) var(--cupcake-spacing-md);
104
+ color: var(--cupcake-text-muted);
105
+ font-size: map-get($cupcake-font-sizes, sm);
106
+ }
107
+
108
+ &.cupcake-card-hoverable {
109
+ @include cupcake-hover-lift();
110
+ cursor: pointer;
111
+ }
112
+ }
113
+
114
+ // =============================================================================
115
+ // BUTTON COMPONENTS
116
+ // =============================================================================
117
+
118
+ .cupcake-btn {
119
+ display: inline-flex;
120
+ align-items: center;
121
+ justify-content: center;
122
+ gap: var(--cupcake-spacing-xs);
123
+ padding: var(--cupcake-spacing-sm) var(--cupcake-spacing-md);
124
+ font-size: map-get($cupcake-font-sizes, base);
125
+ font-weight: map-get($cupcake-font-weights, medium);
126
+ line-height: 1.5;
127
+ border-radius: var(--cupcake-border-radius);
128
+ border: 1px solid transparent;
129
+ transition: var(--cupcake-transition-fast);
130
+ cursor: pointer;
131
+ text-decoration: none;
132
+ @include cupcake-focus-ring();
133
+
134
+ &:disabled,
135
+ &.disabled {
136
+ opacity: 0.6;
137
+ cursor: not-allowed;
138
+ pointer-events: none;
139
+ }
140
+
141
+ // Size variants
142
+ &.cupcake-btn-sm {
143
+ padding: var(--cupcake-spacing-xs) var(--cupcake-spacing-sm);
144
+ font-size: map-get($cupcake-font-sizes, sm);
145
+ }
146
+
147
+ &.cupcake-btn-lg {
148
+ padding: var(--cupcake-spacing-sm) var(--cupcake-spacing-lg);
149
+ font-size: map-get($cupcake-font-sizes, lg);
150
+ }
151
+
152
+ // Loading state
153
+ &.cupcake-btn-loading {
154
+ position: relative;
155
+ color: transparent;
156
+
157
+ &::after {
158
+ content: '';
159
+ position: absolute;
160
+ @include cupcake-spinner();
161
+ color: currentColor;
162
+ }
163
+ }
164
+ }
165
+
166
+ .cupcake-btn-primary {
167
+ background-color: var(--cupcake-primary);
168
+ border-color: var(--cupcake-primary);
169
+ color: white;
170
+
171
+ &:hover:not(:disabled) {
172
+ background-color: var(--cupcake-primary-dark);
173
+ border-color: var(--cupcake-primary-dark);
174
+ transform: translateY(-1px);
175
+ }
176
+ }
177
+
178
+ .cupcake-btn-outline-primary {
179
+ background-color: transparent;
180
+ border-color: var(--cupcake-primary);
181
+ color: var(--cupcake-primary);
182
+
183
+ &:hover:not(:disabled) {
184
+ background-color: var(--cupcake-primary);
185
+ color: white;
186
+ }
187
+ }
188
+
189
+ .cupcake-btn-ghost {
190
+ background-color: transparent;
191
+ border-color: transparent;
192
+ color: var(--cupcake-text);
193
+
194
+ &:hover:not(:disabled) {
195
+ background-color: var(--cupcake-bg-secondary);
196
+ }
197
+ }
198
+
199
+ // =============================================================================
200
+ // FORM COMPONENTS
201
+ // =============================================================================
202
+
203
+ .cupcake-form-group {
204
+ margin-bottom: var(--cupcake-spacing-md);
205
+ }
206
+
207
+ .cupcake-form-label {
208
+ display: block;
209
+ font-weight: map-get($cupcake-font-weights, medium);
210
+ color: var(--cupcake-text);
211
+ margin-bottom: var(--cupcake-spacing-xs);
212
+ }
213
+
214
+ .cupcake-form-control {
215
+ display: block;
216
+ width: 100%;
217
+ padding: var(--cupcake-spacing-sm);
218
+ font-size: map-get($cupcake-font-sizes, base);
219
+ line-height: 1.5;
220
+ color: var(--cupcake-text);
221
+ background-color: var(--cupcake-input-bg);
222
+ border: 1px solid var(--cupcake-input-border);
223
+ border-radius: var(--cupcake-border-radius);
224
+ transition: var(--cupcake-transition-fast);
225
+
226
+ &:focus {
227
+ @include cupcake-input-focus();
228
+ }
229
+
230
+ &:disabled,
231
+ &[readonly] {
232
+ background-color: var(--cupcake-bg-secondary);
233
+ opacity: 0.6;
234
+ cursor: not-allowed;
235
+ }
236
+
237
+ &.is-invalid {
238
+ border-color: var(--cupcake-danger);
239
+
240
+ &:focus {
241
+ border-color: var(--cupcake-danger);
242
+ box-shadow: 0 0 0 0.25rem rgba(var(--cupcake-danger-rgb), 0.25);
243
+ }
244
+ }
245
+
246
+ &.is-valid {
247
+ border-color: var(--cupcake-success);
248
+
249
+ &:focus {
250
+ border-color: var(--cupcake-success);
251
+ box-shadow: 0 0 0 0.25rem rgba(var(--cupcake-success-rgb), 0.25);
252
+ }
253
+ }
254
+ }
255
+
256
+ .cupcake-form-text {
257
+ font-size: map-get($cupcake-font-sizes, sm);
258
+ color: var(--cupcake-text-muted);
259
+ margin-top: var(--cupcake-spacing-xs);
260
+ }
261
+
262
+ .cupcake-invalid-feedback {
263
+ display: block;
264
+ font-size: map-get($cupcake-font-sizes, sm);
265
+ color: var(--cupcake-danger);
266
+ margin-top: var(--cupcake-spacing-xs);
267
+ }
268
+
269
+ .cupcake-valid-feedback {
270
+ display: block;
271
+ font-size: map-get($cupcake-font-sizes, sm);
272
+ color: var(--cupcake-success);
273
+ margin-top: var(--cupcake-spacing-xs);
274
+ }
275
+
276
+ // =============================================================================
277
+ // TABLE COMPONENTS
278
+ // =============================================================================
279
+
280
+ .cupcake-table {
281
+ width: 100%;
282
+ border-collapse: collapse;
283
+ background-color: var(--cupcake-card-bg);
284
+ border: 1px solid var(--cupcake-table-border);
285
+ border-radius: var(--cupcake-border-radius);
286
+ overflow: hidden;
287
+
288
+ th,
289
+ td {
290
+ padding: var(--cupcake-spacing-sm) var(--cupcake-spacing-md);
291
+ text-align: left;
292
+ border-bottom: 1px solid var(--cupcake-table-border);
293
+ }
294
+
295
+ th {
296
+ background-color: var(--cupcake-card-header-bg);
297
+ font-weight: map-get($cupcake-font-weights, semibold);
298
+ color: var(--cupcake-text);
299
+ }
300
+
301
+ tbody tr {
302
+ transition: var(--cupcake-transition-fast);
303
+
304
+ &:hover {
305
+ background-color: var(--cupcake-table-hover);
306
+ }
307
+
308
+ &:nth-child(even) {
309
+ background-color: var(--cupcake-table-striped);
310
+ }
311
+ }
312
+
313
+ &.cupcake-table-sm {
314
+ th,
315
+ td {
316
+ padding: var(--cupcake-spacing-xs) var(--cupcake-spacing-sm);
317
+ font-size: map-get($cupcake-font-sizes, sm);
318
+ }
319
+ }
320
+ }
321
+
322
+ // =============================================================================
323
+ // BADGE COMPONENTS
324
+ // =============================================================================
325
+
326
+ .cupcake-badge {
327
+ display: inline-flex;
328
+ align-items: center;
329
+ padding: 0.25em 0.5em;
330
+ font-size: map-get($cupcake-font-sizes, xs);
331
+ font-weight: map-get($cupcake-font-weights, medium);
332
+ line-height: 1;
333
+ border-radius: var(--cupcake-border-radius-sm);
334
+
335
+ &.cupcake-badge-primary {
336
+ @include cupcake-status-badge(--cupcake-primary);
337
+ }
338
+
339
+ &.cupcake-badge-success {
340
+ @include cupcake-status-badge(--cupcake-success);
341
+ }
342
+
343
+ &.cupcake-badge-warning {
344
+ @include cupcake-status-badge(--cupcake-warning);
345
+ color: var(--cupcake-text);
346
+ }
347
+
348
+ &.cupcake-badge-danger {
349
+ @include cupcake-status-badge(--cupcake-danger);
350
+ }
351
+
352
+ &.cupcake-badge-info {
353
+ @include cupcake-status-badge(--cupcake-info);
354
+ }
355
+
356
+ &.cupcake-badge-secondary {
357
+ @include cupcake-status-badge(--cupcake-secondary);
358
+ }
359
+ }
360
+
361
+ // =============================================================================
362
+ // ALERT COMPONENTS
363
+ // =============================================================================
364
+
365
+ .cupcake-alert {
366
+ padding: var(--cupcake-spacing-md);
367
+ border-radius: var(--cupcake-border-radius);
368
+ border: 1px solid transparent;
369
+ margin-bottom: var(--cupcake-spacing-md);
370
+
371
+ &.cupcake-alert-primary {
372
+ background-color: rgba(var(--cupcake-primary-rgb), 0.1);
373
+ border-color: rgba(var(--cupcake-primary-rgb), 0.2);
374
+ color: var(--cupcake-primary-dark);
375
+ }
376
+
377
+ &.cupcake-alert-success {
378
+ background-color: rgba(var(--cupcake-success-rgb), 0.1);
379
+ border-color: rgba(var(--cupcake-success-rgb), 0.2);
380
+ color: var(--cupcake-success);
381
+ }
382
+
383
+ &.cupcake-alert-warning {
384
+ background-color: rgba(var(--cupcake-warning-rgb), 0.1);
385
+ border-color: rgba(var(--cupcake-warning-rgb), 0.2);
386
+ color: #856404;
387
+ }
388
+
389
+ &.cupcake-alert-danger {
390
+ background-color: rgba(var(--cupcake-danger-rgb), 0.1);
391
+ border-color: rgba(var(--cupcake-danger-rgb), 0.2);
392
+ color: var(--cupcake-danger);
393
+ }
394
+
395
+ &.cupcake-alert-info {
396
+ background-color: rgba(var(--cupcake-info-rgb), 0.1);
397
+ border-color: rgba(var(--cupcake-info-rgb), 0.2);
398
+ color: #055160;
399
+ }
400
+ }
401
+
402
+ // =============================================================================
403
+ // UTILITY CLASSES
404
+ // =============================================================================
405
+
406
+ .cupcake-text-truncate {
407
+ @include cupcake-text-truncate();
408
+ }
409
+
410
+ .cupcake-sr-only {
411
+ @include cupcake-sr-only();
412
+ }
413
+
414
+ .cupcake-clearfix {
415
+ @include cupcake-clearfix();
416
+ }
417
+
418
+ .cupcake-flex-center {
419
+ @include cupcake-flex-center();
420
+ }
421
+
422
+ .cupcake-loading-overlay {
423
+ @include cupcake-loading-overlay();
424
+ }
425
+
426
+ .cupcake-spinner {
427
+ @include cupcake-spinner();
428
+ }
429
+
430
+ .cupcake-fade-in {
431
+ @include cupcake-fade-in();
432
+ }
433
+
434
+ .cupcake-slide-in-up {
435
+ @include cupcake-slide-in('up');
436
+ }
437
+
438
+ .cupcake-slide-in-down {
439
+ @include cupcake-slide-in('down');
440
+ }
441
+
442
+ .cupcake-slide-in-left {
443
+ @include cupcake-slide-in('left');
444
+ }
445
+
446
+ .cupcake-slide-in-right {
447
+ @include cupcake-slide-in('right');
448
+ }
449
+
450
+ .cupcake-hover-lift {
451
+ @include cupcake-hover-lift();
452
+ }
453
+
454
+ // Spacing utilities
455
+ @each $prop, $abbrev in (margin: m, padding: p) {
456
+ @each $size, $value in (
457
+ 0: 0,
458
+ 1: var(--cupcake-spacing-xs),
459
+ 2: var(--cupcake-spacing-sm),
460
+ 3: var(--cupcake-spacing-md),
461
+ 4: var(--cupcake-spacing-lg),
462
+ 5: var(--cupcake-spacing-xl)
463
+ ) {
464
+ .cupcake-#{$abbrev}-#{$size} {
465
+ #{$prop}: #{$value} !important;
466
+ }
467
+
468
+ .cupcake-#{$abbrev}t-#{$size} {
469
+ #{$prop}-top: #{$value} !important;
470
+ }
471
+
472
+ .cupcake-#{$abbrev}r-#{$size} {
473
+ #{$prop}-right: #{$value} !important;
474
+ }
475
+
476
+ .cupcake-#{$abbrev}b-#{$size} {
477
+ #{$prop}-bottom: #{$value} !important;
478
+ }
479
+
480
+ .cupcake-#{$abbrev}l-#{$size} {
481
+ #{$prop}-left: #{$value} !important;
482
+ }
483
+
484
+ .cupcake-#{$abbrev}x-#{$size} {
485
+ #{$prop}-right: #{$value} !important;
486
+ #{$prop}-left: #{$value} !important;
487
+ }
488
+
489
+ .cupcake-#{$abbrev}y-#{$size} {
490
+ #{$prop}-top: #{$value} !important;
491
+ #{$prop}-bottom: #{$value} !important;
492
+ }
493
+ }
494
+ }
@@ -0,0 +1,231 @@
1
+ // =============================================================================
2
+ // CUPCAKE CORE - Mixins
3
+ // =============================================================================
4
+ // Reusable SCSS mixins for common UI patterns in cupcake applications
5
+
6
+ @import './variables';
7
+
8
+ // Responsive breakpoint mixin
9
+ @mixin cupcake-media-breakpoint-up($name) {
10
+ $min: map-get($cupcake-breakpoints, $name);
11
+ @if $min != 0 {
12
+ @media (min-width: $min) {
13
+ @content;
14
+ }
15
+ } @else {
16
+ @content;
17
+ }
18
+ }
19
+
20
+ @mixin cupcake-media-breakpoint-down($name) {
21
+ $max: map-get($cupcake-breakpoints, $name);
22
+ @if $max != 0 {
23
+ @media (max-width: $max - 1px) {
24
+ @content;
25
+ }
26
+ }
27
+ }
28
+
29
+ // Card styling mixin
30
+ @mixin cupcake-card() {
31
+ background-color: var(--cupcake-card-bg);
32
+ border: 1px solid var(--cupcake-card-border);
33
+ border-radius: var(--cupcake-border-radius);
34
+ box-shadow: 0 0.125rem 0.25rem var(--cupcake-shadow);
35
+ transition: var(--cupcake-transition);
36
+
37
+ &:hover {
38
+ box-shadow: 0 0.25rem 0.5rem var(--cupcake-shadow-lg);
39
+ }
40
+ }
41
+
42
+ // Button reset mixin
43
+ @mixin cupcake-button-reset() {
44
+ appearance: none;
45
+ background: none;
46
+ border: none;
47
+ padding: 0;
48
+ margin: 0;
49
+ font: inherit;
50
+ color: inherit;
51
+ cursor: pointer;
52
+ outline: none;
53
+
54
+ &:focus-visible {
55
+ outline: 2px solid var(--cupcake-primary);
56
+ outline-offset: 2px;
57
+ }
58
+ }
59
+
60
+ // Input focus mixin
61
+ @mixin cupcake-input-focus() {
62
+ border-color: var(--cupcake-input-focus);
63
+ box-shadow: 0 0 0 0.25rem rgba(var(--cupcake-primary-rgb), 0.25);
64
+ outline: none;
65
+ }
66
+
67
+ // Loading state mixin
68
+ @mixin cupcake-loading-overlay() {
69
+ position: absolute;
70
+ top: 0;
71
+ left: 0;
72
+ right: 0;
73
+ bottom: 0;
74
+ background: var(--cupcake-loading-overlay);
75
+ display: flex;
76
+ align-items: center;
77
+ justify-content: center;
78
+ z-index: map-get($cupcake-z-indices, modal);
79
+ }
80
+
81
+ // Truncate text mixin
82
+ @mixin cupcake-text-truncate() {
83
+ overflow: hidden;
84
+ text-overflow: ellipsis;
85
+ white-space: nowrap;
86
+ }
87
+
88
+ // Visually hidden mixin (for accessibility)
89
+ @mixin cupcake-sr-only() {
90
+ position: absolute !important;
91
+ width: 1px !important;
92
+ height: 1px !important;
93
+ padding: 0 !important;
94
+ margin: -1px !important;
95
+ overflow: hidden !important;
96
+ clip: rect(0, 0, 0, 0) !important;
97
+ white-space: nowrap !important;
98
+ border: 0 !important;
99
+ }
100
+
101
+ // Clearfix mixin
102
+ @mixin cupcake-clearfix() {
103
+ &::after {
104
+ display: block;
105
+ clear: both;
106
+ content: "";
107
+ }
108
+ }
109
+
110
+ // Flex center mixin
111
+ @mixin cupcake-flex-center() {
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ }
116
+
117
+ // Status badge mixin
118
+ @mixin cupcake-status-badge($color-var) {
119
+ display: inline-flex;
120
+ align-items: center;
121
+ padding: 0.25em 0.6em;
122
+ font-size: 0.75em;
123
+ font-weight: map-get($cupcake-font-weights, medium);
124
+ line-height: 1;
125
+ color: white;
126
+ background-color: var(#{$color-var});
127
+ border-radius: var(--cupcake-border-radius-sm);
128
+ text-transform: uppercase;
129
+ letter-spacing: 0.025em;
130
+ }
131
+
132
+ // Hover lift effect
133
+ @mixin cupcake-hover-lift() {
134
+ transition: var(--cupcake-transition);
135
+
136
+ &:hover {
137
+ transform: translateY(-2px);
138
+ box-shadow: 0 4px 12px var(--cupcake-shadow-lg);
139
+ }
140
+ }
141
+
142
+ // Focus ring mixin
143
+ @mixin cupcake-focus-ring($color: var(--cupcake-primary)) {
144
+ &:focus-visible {
145
+ outline: 2px solid $color;
146
+ outline-offset: 2px;
147
+ border-radius: var(--cupcake-border-radius-sm);
148
+ }
149
+ }
150
+
151
+ // Spinner animation mixin
152
+ @mixin cupcake-spinner() {
153
+ display: inline-block;
154
+ width: 1rem;
155
+ height: 1rem;
156
+ border: 0.125em solid currentColor;
157
+ border-right-color: transparent;
158
+ border-radius: 50%;
159
+ animation: cupcake-spin 0.75s linear infinite;
160
+ }
161
+
162
+ @keyframes cupcake-spin {
163
+ to {
164
+ transform: rotate(360deg);
165
+ }
166
+ }
167
+
168
+ // Fade in animation mixin
169
+ @mixin cupcake-fade-in($duration: 0.3s) {
170
+ opacity: 0;
171
+ animation: cupcake-fade-in $duration ease-out forwards;
172
+ }
173
+
174
+ @keyframes cupcake-fade-in {
175
+ to {
176
+ opacity: 1;
177
+ }
178
+ }
179
+
180
+ // Slide in animation mixin
181
+ @mixin cupcake-slide-in($direction: 'up', $distance: 20px, $duration: 0.3s) {
182
+ opacity: 0;
183
+
184
+ @if $direction == 'up' {
185
+ transform: translateY($distance);
186
+ } @else if $direction == 'down' {
187
+ transform: translateY(-$distance);
188
+ } @else if $direction == 'left' {
189
+ transform: translateX($distance);
190
+ } @else if $direction == 'right' {
191
+ transform: translateX(-$distance);
192
+ }
193
+
194
+ animation: cupcake-slide-in-#{$direction} $duration ease-out forwards;
195
+ }
196
+
197
+ @keyframes cupcake-slide-in-up {
198
+ to {
199
+ opacity: 1;
200
+ transform: translateY(0);
201
+ }
202
+ }
203
+
204
+ @keyframes cupcake-slide-in-down {
205
+ to {
206
+ opacity: 1;
207
+ transform: translateY(0);
208
+ }
209
+ }
210
+
211
+ @keyframes cupcake-slide-in-left {
212
+ to {
213
+ opacity: 1;
214
+ transform: translateX(0);
215
+ }
216
+ }
217
+
218
+ @keyframes cupcake-slide-in-right {
219
+ to {
220
+ opacity: 1;
221
+ transform: translateX(0);
222
+ }
223
+ }
224
+
225
+ // Dark mode mixin
226
+ @mixin cupcake-dark-mode() {
227
+ :root[data-bs-theme="dark"] &,
228
+ .dark-mode & {
229
+ @content;
230
+ }
231
+ }