@duskmoon-dev/core 1.1.1 → 1.2.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,231 @@
1
+ /**
2
+ * Checkbox Component Styles
3
+ * DuskMoonUI - Material Design 3 inspired checkbox
4
+ *
5
+ * Usage: <input type="checkbox" class="checkbox" />
6
+ * With label: <label class="label cursor-pointer gap-2"><input type="checkbox" class="checkbox" /><span>Label</span></label>
7
+ */
8
+
9
+ @layer components {
10
+ /* Base Checkbox - applied directly to input[type="checkbox"] */
11
+ .checkbox {
12
+ --checkbox-size: 1.25rem;
13
+ --checkbox-color: var(--color-primary);
14
+ --checkbox-border-color: var(--color-on-surface-variant);
15
+
16
+ position: relative;
17
+ display: inline-grid;
18
+ place-content: center;
19
+ width: var(--checkbox-size);
20
+ height: var(--checkbox-size);
21
+ margin: 0;
22
+ cursor: pointer;
23
+ appearance: none;
24
+ background-color: transparent;
25
+ border: 2px solid var(--checkbox-border-color);
26
+ border-radius: 0.125rem;
27
+ transition: background-color 150ms ease-in-out, border-color 150ms ease-in-out;
28
+ }
29
+
30
+ /* Checkmark using ::before pseudo-element */
31
+ .checkbox::before {
32
+ content: "";
33
+ width: 0.65em;
34
+ height: 0.35em;
35
+ transform: scale(0) rotate(-45deg);
36
+ transform-origin: center;
37
+ border-bottom: 2px solid var(--color-on-primary);
38
+ border-left: 2px solid var(--color-on-primary);
39
+ transition: transform 150ms ease-in-out;
40
+ }
41
+
42
+ /* Checked State */
43
+ .checkbox:checked {
44
+ background-color: var(--checkbox-color);
45
+ border-color: var(--checkbox-color);
46
+ }
47
+
48
+ .checkbox:checked::before {
49
+ transform: scale(1) rotate(-45deg);
50
+ }
51
+
52
+ /* Indeterminate State */
53
+ .checkbox:indeterminate {
54
+ background-color: var(--checkbox-color);
55
+ border-color: var(--checkbox-color);
56
+ }
57
+
58
+ .checkbox:indeterminate::before {
59
+ width: 0.5em;
60
+ height: 0;
61
+ border-bottom: 2px solid var(--color-on-primary);
62
+ border-left: 0;
63
+ transform: scale(1) rotate(0deg);
64
+ }
65
+
66
+ /* Hover State */
67
+ .checkbox:hover:not(:disabled):not(:checked) {
68
+ border-color: var(--color-on-surface);
69
+ }
70
+
71
+ .checkbox:checked:hover:not(:disabled) {
72
+ background-color: color-mix(in oklch, var(--checkbox-color), black 10%);
73
+ border-color: color-mix(in oklch, var(--checkbox-color), black 10%);
74
+ }
75
+
76
+ /* Focus State */
77
+ .checkbox:focus-visible {
78
+ outline: 2px solid var(--checkbox-color);
79
+ outline-offset: 2px;
80
+ }
81
+
82
+ /* Disabled State */
83
+ .checkbox:disabled {
84
+ cursor: not-allowed;
85
+ opacity: 0.38;
86
+ }
87
+
88
+ /* ========================================
89
+ * Size Variants
90
+ * ======================================== */
91
+
92
+ .checkbox-xs {
93
+ --checkbox-size: 0.875rem;
94
+ }
95
+
96
+ .checkbox-sm {
97
+ --checkbox-size: 1rem;
98
+ }
99
+
100
+ .checkbox-md {
101
+ --checkbox-size: 1.25rem;
102
+ }
103
+
104
+ .checkbox-lg {
105
+ --checkbox-size: 1.5rem;
106
+ }
107
+
108
+ .checkbox-xl {
109
+ --checkbox-size: 1.75rem;
110
+ }
111
+
112
+ /* ========================================
113
+ * Color Variants
114
+ * ======================================== */
115
+
116
+ .checkbox-primary {
117
+ --checkbox-color: var(--color-primary);
118
+ }
119
+
120
+ .checkbox-primary:checked::before,
121
+ .checkbox-primary:indeterminate::before {
122
+ border-color: var(--color-primary-content);
123
+ }
124
+
125
+ .checkbox-secondary {
126
+ --checkbox-color: var(--color-secondary);
127
+ }
128
+
129
+ .checkbox-secondary:checked::before,
130
+ .checkbox-secondary:indeterminate::before {
131
+ border-color: var(--color-secondary-content);
132
+ }
133
+
134
+ .checkbox-tertiary {
135
+ --checkbox-color: var(--color-tertiary);
136
+ }
137
+
138
+ .checkbox-tertiary:checked::before,
139
+ .checkbox-tertiary:indeterminate::before {
140
+ border-color: var(--color-tertiary-content);
141
+ }
142
+
143
+ .checkbox-success {
144
+ --checkbox-color: var(--color-success);
145
+ }
146
+
147
+ .checkbox-success:checked::before,
148
+ .checkbox-success:indeterminate::before {
149
+ border-color: var(--color-success-content);
150
+ }
151
+
152
+ .checkbox-warning {
153
+ --checkbox-color: var(--color-warning);
154
+ }
155
+
156
+ .checkbox-warning:checked::before,
157
+ .checkbox-warning:indeterminate::before {
158
+ border-color: var(--color-warning-content);
159
+ }
160
+
161
+ .checkbox-error {
162
+ --checkbox-color: var(--color-error);
163
+ }
164
+
165
+ .checkbox-error:checked::before,
166
+ .checkbox-error:indeterminate::before {
167
+ border-color: var(--color-error-content);
168
+ }
169
+
170
+ .checkbox-info {
171
+ --checkbox-color: var(--color-info);
172
+ }
173
+
174
+ .checkbox-info:checked::before,
175
+ .checkbox-info:indeterminate::before {
176
+ border-color: var(--color-info-content);
177
+ }
178
+
179
+ /* ========================================
180
+ * Checkbox with Label (wrapper pattern)
181
+ * ======================================== */
182
+
183
+ .checkbox-label {
184
+ display: inline-flex;
185
+ align-items: center;
186
+ gap: 0.5rem;
187
+ cursor: pointer;
188
+ user-select: none;
189
+ font-size: 0.875rem;
190
+ color: var(--color-on-surface);
191
+ }
192
+
193
+ .checkbox-label:has(.checkbox:disabled) {
194
+ cursor: not-allowed;
195
+ opacity: 0.38;
196
+ }
197
+
198
+ /* ========================================
199
+ * Checkbox Group
200
+ * ======================================== */
201
+
202
+ .checkbox-group {
203
+ display: flex;
204
+ flex-direction: column;
205
+ gap: 0.75rem;
206
+ }
207
+
208
+ .checkbox-group-horizontal {
209
+ flex-direction: row;
210
+ flex-wrap: wrap;
211
+ gap: 1.5rem;
212
+ }
213
+
214
+ .checkbox-group-label {
215
+ font-size: 0.875rem;
216
+ font-weight: 500;
217
+ color: var(--color-on-surface);
218
+ margin-bottom: 0.5rem;
219
+ }
220
+
221
+ /* ========================================
222
+ * Reduce Motion
223
+ * ======================================== */
224
+
225
+ @media (prefers-reduced-motion: reduce) {
226
+ .checkbox,
227
+ .checkbox::before {
228
+ transition: none;
229
+ }
230
+ }
231
+ }
@@ -24,6 +24,18 @@
24
24
  transition: border-color 150ms ease-in-out, box-shadow 150ms ease-in-out;
25
25
  }
26
26
 
27
+ /* Hide native date picker controls when using custom trigger */
28
+ .datepicker-input-container .datepicker-input[type="date"]::-webkit-calendar-picker-indicator {
29
+ display: none;
30
+ -webkit-appearance: none;
31
+ }
32
+
33
+ .datepicker-input-container .datepicker-input[type="date"]::-webkit-inner-spin-button,
34
+ .datepicker-input-container .datepicker-input[type="date"]::-webkit-clear-button {
35
+ display: none;
36
+ -webkit-appearance: none;
37
+ }
38
+
27
39
  .datepicker-input:focus {
28
40
  outline: none;
29
41
  border-color: var(--color-primary);
@@ -52,8 +64,50 @@
52
64
  pointer-events: none;
53
65
  }
54
66
 
55
- /* Datepicker Dropdown */
56
- .datepicker-dropdown {
67
+ /* Datepicker Input Container */
68
+ .datepicker-input-container {
69
+ position: relative;
70
+ display: flex;
71
+ align-items: center;
72
+ width: 100%;
73
+ }
74
+
75
+ .datepicker-input-container .datepicker-input {
76
+ padding-right: 2.5rem;
77
+ }
78
+
79
+ /* Datepicker Trigger (icon button for Popover API) */
80
+ .datepicker-trigger {
81
+ position: absolute;
82
+ right: 0.5rem;
83
+ top: 50%;
84
+ transform: translateY(-50%);
85
+ z-index: 1;
86
+ display: flex;
87
+ align-items: center;
88
+ justify-content: center;
89
+ width: 2rem;
90
+ height: 2rem;
91
+ padding: 0;
92
+ background: transparent;
93
+ border: none;
94
+ border-radius: 50%;
95
+ cursor: pointer;
96
+ color: var(--color-on-surface-variant);
97
+ transition: background-color 150ms ease-in-out;
98
+ }
99
+
100
+ .datepicker-trigger:hover {
101
+ background-color: var(--color-surface-container);
102
+ }
103
+
104
+ .datepicker-trigger .datepicker-icon {
105
+ position: static;
106
+ transform: none;
107
+ }
108
+
109
+ /* Datepicker Dropdown - Non-popover (JS-controlled) */
110
+ .datepicker-dropdown:not([popover]) {
57
111
  position: absolute;
58
112
  top: 100%;
59
113
  left: 0;
@@ -69,13 +123,28 @@
69
123
  transition: opacity 150ms ease-out, visibility 150ms ease-out, transform 150ms ease-out;
70
124
  }
71
125
 
72
- .datepicker.datepicker-open .datepicker-dropdown,
73
- .datepicker-dropdown.show {
126
+ .datepicker.datepicker-open .datepicker-dropdown:not([popover]),
127
+ .datepicker-dropdown:not([popover]).show,
128
+ .datepicker-dropdown-open:not([popover]) {
74
129
  opacity: 1;
75
130
  visibility: visible;
76
131
  transform: translateY(0);
77
132
  }
78
133
 
134
+ /* Popover API Support - Browser handles visibility, JS handles positioning */
135
+ .datepicker-dropdown[popover] {
136
+ /* Reset browser defaults - positioning handled by JavaScript */
137
+ inset: unset;
138
+ margin: 0;
139
+ padding: 0;
140
+ /* Styling */
141
+ min-width: 18rem;
142
+ background-color: var(--color-surface);
143
+ border: 1px solid var(--color-outline);
144
+ border-radius: 0.75rem;
145
+ box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
146
+ }
147
+
79
148
  /* Calendar Header */
80
149
  .datepicker-header {
81
150
  display: flex;
@@ -122,6 +191,9 @@
122
191
 
123
192
  /* Calendar Body */
124
193
  .datepicker-calendar {
194
+ display: grid;
195
+ grid-template-columns: repeat(7, 1fr);
196
+ gap: 0.125rem;
125
197
  padding: 0.5rem;
126
198
  }
127
199
 
@@ -137,7 +209,7 @@
137
209
  display: flex;
138
210
  align-items: center;
139
211
  justify-content: center;
140
- height: 2rem;
212
+ aspect-ratio: 1;
141
213
  font-size: 0.75rem;
142
214
  font-weight: 500;
143
215
  color: var(--color-on-surface-variant);
@@ -154,8 +226,7 @@
154
226
  display: flex;
155
227
  align-items: center;
156
228
  justify-content: center;
157
- width: 2.5rem;
158
- height: 2.5rem;
229
+ aspect-ratio: 1;
159
230
  font-size: 0.875rem;
160
231
  color: var(--color-on-surface);
161
232
  background-color: transparent;
@@ -225,6 +296,7 @@
225
296
  grid-template-columns: repeat(3, 1fr);
226
297
  gap: 0.5rem;
227
298
  padding: 0.5rem;
299
+ min-width: 16rem;
228
300
  }
229
301
 
230
302
  .datepicker-month,
@@ -232,7 +304,7 @@
232
304
  display: flex;
233
305
  align-items: center;
234
306
  justify-content: center;
235
- height: 3rem;
307
+ padding: 0.75rem 1rem;
236
308
  font-size: 0.875rem;
237
309
  color: var(--color-on-surface);
238
310
  background-color: transparent;
@@ -248,11 +320,20 @@
248
320
  }
249
321
 
250
322
  .datepicker-month.selected,
251
- .datepicker-year.selected {
323
+ .datepicker-month-selected,
324
+ .datepicker-year.selected,
325
+ .datepicker-year-selected {
252
326
  background-color: var(--color-primary);
253
327
  color: var(--color-on-primary);
254
328
  }
255
329
 
330
+ .datepicker-day-disabled {
331
+ color: var(--color-on-surface-variant);
332
+ opacity: 0.4;
333
+ cursor: not-allowed;
334
+ pointer-events: none;
335
+ }
336
+
256
337
  /* Footer Actions */
257
338
  .datepicker-footer {
258
339
  display: flex;
@@ -338,9 +419,322 @@
338
419
  font-size: 1rem;
339
420
  }
340
421
 
422
+ /* ========================================
423
+ * Date Range Picker Variants
424
+ * ======================================== */
425
+
426
+ /* Range Input Container */
427
+ .datepicker-range {
428
+ display: flex;
429
+ align-items: center;
430
+ gap: 0.5rem;
431
+ }
432
+
433
+ .datepicker-range-separator {
434
+ color: var(--color-on-surface-variant);
435
+ font-size: 0.875rem;
436
+ }
437
+
438
+ .datepicker-range-input {
439
+ flex: 1;
440
+ }
441
+
442
+ /* Dual Calendar View */
443
+ .datepicker-dual-calendar {
444
+ display: flex;
445
+ gap: 1rem;
446
+ padding: 0.5rem;
447
+ }
448
+
449
+ .datepicker-dual-calendar .datepicker-calendar {
450
+ flex: 1;
451
+ }
452
+
453
+ /* Range Presets */
454
+ .datepicker-presets {
455
+ display: flex;
456
+ flex-direction: column;
457
+ gap: 0.25rem;
458
+ padding: 0.5rem;
459
+ border-right: 1px solid var(--color-outline-variant);
460
+ min-width: 8rem;
461
+ }
462
+
463
+ .datepicker-preset {
464
+ padding: 0.5rem 0.75rem;
465
+ font-size: 0.75rem;
466
+ color: var(--color-on-surface);
467
+ background-color: transparent;
468
+ border: none;
469
+ border-radius: 0.375rem;
470
+ cursor: pointer;
471
+ text-align: left;
472
+ transition: background-color 150ms ease-in-out;
473
+ }
474
+
475
+ .datepicker-preset:hover {
476
+ background-color: var(--color-surface-container);
477
+ }
478
+
479
+ .datepicker-preset-active {
480
+ background-color: var(--color-primary-container);
481
+ color: var(--color-on-primary-container);
482
+ }
483
+
484
+ /* Range Display */
485
+ .datepicker-range-display {
486
+ display: flex;
487
+ align-items: center;
488
+ gap: 0.75rem;
489
+ padding: 0.75rem;
490
+ background-color: var(--color-surface-container-lowest);
491
+ border-bottom: 1px solid var(--color-outline-variant);
492
+ }
493
+
494
+ .datepicker-range-date {
495
+ flex: 1;
496
+ text-align: center;
497
+ }
498
+
499
+ .datepicker-range-date-label {
500
+ font-size: 0.625rem;
501
+ font-weight: 500;
502
+ color: var(--color-on-surface-variant);
503
+ text-transform: uppercase;
504
+ margin-bottom: 0.25rem;
505
+ }
506
+
507
+ .datepicker-range-date-value {
508
+ font-size: 0.875rem;
509
+ font-weight: 500;
510
+ color: var(--color-on-surface);
511
+ }
512
+
513
+ .datepicker-range-arrow {
514
+ color: var(--color-on-surface-variant);
515
+ }
516
+
517
+ /* ========================================
518
+ * DateTime Picker Variants
519
+ * ======================================== */
520
+
521
+ /* DateTime Container */
522
+ .datetime-picker {
523
+ position: relative;
524
+ display: inline-block;
525
+ width: 100%;
526
+ }
527
+
528
+ .datetime-picker-input {
529
+ width: 100%;
530
+ padding: 0.75rem 2.5rem 0.75rem 1rem;
531
+ font-size: 0.875rem;
532
+ line-height: 1.5;
533
+ color: var(--color-on-surface);
534
+ background-color: var(--color-surface);
535
+ border: 1px solid var(--color-outline);
536
+ border-radius: 0.5rem;
537
+ transition: border-color 150ms ease-in-out, box-shadow 150ms ease-in-out;
538
+ }
539
+
540
+ .datetime-picker-input:focus {
541
+ outline: none;
542
+ border-color: var(--color-primary);
543
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
544
+ }
545
+
546
+ /* DateTime Dropdown Layout */
547
+ .datetime-picker-dropdown {
548
+ display: flex;
549
+ flex-direction: column;
550
+ }
551
+
552
+ .datetime-picker-body {
553
+ display: flex;
554
+ }
555
+
556
+ .datetime-picker-calendar {
557
+ flex: 1;
558
+ }
559
+
560
+ .datetime-picker-time-panel {
561
+ display: flex;
562
+ flex-direction: column;
563
+ min-width: 5rem;
564
+ border-left: 1px solid var(--color-outline-variant);
565
+ }
566
+
567
+ .datetime-picker-time-header {
568
+ padding: 0.5rem;
569
+ font-size: 0.75rem;
570
+ font-weight: 500;
571
+ color: var(--color-on-surface-variant);
572
+ text-align: center;
573
+ border-bottom: 1px solid var(--color-outline-variant);
574
+ }
575
+
576
+ .datetime-picker-time-columns {
577
+ display: flex;
578
+ flex: 1;
579
+ max-height: 16rem;
580
+ }
581
+
582
+ .datetime-picker-time-column {
583
+ flex: 1;
584
+ display: flex;
585
+ flex-direction: column;
586
+ overflow-y: auto;
587
+ border-right: 1px solid var(--color-outline-variant);
588
+ }
589
+
590
+ .datetime-picker-time-column:last-child {
591
+ border-right: none;
592
+ }
593
+
594
+ .datetime-picker-time-option {
595
+ padding: 0.375rem 0.5rem;
596
+ font-size: 0.75rem;
597
+ text-align: center;
598
+ color: var(--color-on-surface);
599
+ background-color: transparent;
600
+ border: none;
601
+ cursor: pointer;
602
+ transition: background-color 150ms ease-in-out;
603
+ }
604
+
605
+ .datetime-picker-time-option:hover {
606
+ background-color: var(--color-surface-container);
607
+ }
608
+
609
+ .datetime-picker-time-option-selected {
610
+ background-color: var(--color-primary);
611
+ color: var(--color-primary-content);
612
+ }
613
+
614
+ .datetime-picker-time-option:disabled {
615
+ opacity: 0.4;
616
+ cursor: not-allowed;
617
+ }
618
+
619
+ /* ========================================
620
+ * DateTime Range Picker
621
+ * ======================================== */
622
+
623
+ .datetime-range-picker {
624
+ position: relative;
625
+ display: inline-block;
626
+ width: 100%;
627
+ }
628
+
629
+ .datetime-range-picker-inputs {
630
+ display: flex;
631
+ align-items: center;
632
+ gap: 0.5rem;
633
+ }
634
+
635
+ .datetime-range-picker-input {
636
+ flex: 1;
637
+ padding: 0.75rem 1rem;
638
+ font-size: 0.875rem;
639
+ color: var(--color-on-surface);
640
+ background-color: var(--color-surface);
641
+ border: 1px solid var(--color-outline);
642
+ border-radius: 0.5rem;
643
+ transition: border-color 150ms ease-in-out;
644
+ }
645
+
646
+ .datetime-range-picker-input:focus {
647
+ outline: none;
648
+ border-color: var(--color-primary);
649
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 10%, transparent);
650
+ }
651
+
652
+ .datetime-range-picker-dropdown {
653
+ min-width: 40rem;
654
+ }
655
+
656
+ .datetime-range-picker-body {
657
+ display: flex;
658
+ }
659
+
660
+ .datetime-range-picker-panel {
661
+ flex: 1;
662
+ border-right: 1px solid var(--color-outline-variant);
663
+ }
664
+
665
+ .datetime-range-picker-panel:last-child {
666
+ border-right: none;
667
+ }
668
+
669
+ .datetime-range-picker-panel-header {
670
+ padding: 0.5rem 0.75rem;
671
+ font-size: 0.75rem;
672
+ font-weight: 500;
673
+ color: var(--color-on-surface-variant);
674
+ text-align: center;
675
+ background-color: var(--color-surface-container-lowest);
676
+ border-bottom: 1px solid var(--color-outline-variant);
677
+ }
678
+
679
+ /* Inline Datepicker (always visible) */
680
+ .datepicker-inline {
681
+ position: static;
682
+ }
683
+
684
+ .datepicker-inline .datepicker-dropdown,
685
+ .datepicker-dropdown.datepicker-inline {
686
+ position: static;
687
+ display: block;
688
+ opacity: 1;
689
+ visibility: visible;
690
+ transform: none;
691
+ margin-top: 0;
692
+ box-shadow: none;
693
+ }
694
+
695
+ /* Color Variants */
696
+ .datepicker-primary .datepicker-day-selected,
697
+ .datepicker-primary .datepicker-day-range-start,
698
+ .datepicker-primary .datepicker-day-range-end {
699
+ background-color: var(--color-primary);
700
+ color: var(--color-primary-content);
701
+ }
702
+
703
+ .datepicker-secondary .datepicker-day-selected,
704
+ .datepicker-secondary .datepicker-day-range-start,
705
+ .datepicker-secondary .datepicker-day-range-end {
706
+ background-color: var(--color-secondary);
707
+ color: var(--color-secondary-content);
708
+ }
709
+
710
+ .datepicker-tertiary .datepicker-day-selected,
711
+ .datepicker-tertiary .datepicker-day-range-start,
712
+ .datepicker-tertiary .datepicker-day-range-end {
713
+ background-color: var(--color-tertiary);
714
+ color: var(--color-tertiary-content);
715
+ }
716
+
717
+ /* Error State */
718
+ .datepicker-error .datepicker-input,
719
+ .datetime-picker-error .datetime-picker-input {
720
+ border-color: var(--color-error);
721
+ }
722
+
723
+ .datepicker-error .datepicker-input:focus,
724
+ .datetime-picker-error .datetime-picker-input:focus {
725
+ border-color: var(--color-error);
726
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-error) 10%, transparent);
727
+ }
728
+
341
729
  /* Reduce Motion */
342
730
  @media (prefers-reduced-motion: reduce) {
343
- .datepicker-dropdown {
731
+ .datepicker-dropdown,
732
+ .datepicker-nav-btn,
733
+ .datepicker-day,
734
+ .datepicker-month,
735
+ .datepicker-year,
736
+ .datepicker-preset,
737
+ .datetime-picker-time-option {
344
738
  transition: none;
345
739
  }
346
740
  }