@duskmoon-dev/core 1.19.2 → 1.19.4

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 (122) hide show
  1. package/README.md +1 -1
  2. package/dist/base.css +484 -0
  3. package/dist/components/accordion.css +33 -9
  4. package/dist/components/autocomplete.css +67 -13
  5. package/dist/components/avatar.css +39 -15
  6. package/dist/components/badge.css +15 -3
  7. package/dist/components/card.css +12 -0
  8. package/dist/components/carousel.css +28 -0
  9. package/dist/components/chat.css +15 -11
  10. package/dist/components/checkbox.css +83 -13
  11. package/dist/components/collapse.css +67 -16
  12. package/dist/components/countdown.css +22 -0
  13. package/dist/components/datepicker.css +76 -0
  14. package/dist/components/diff.css +33 -0
  15. package/dist/components/file-input.css +107 -0
  16. package/dist/components/filter-group.css +452 -0
  17. package/dist/components/footer.css +48 -0
  18. package/dist/components/form-group.css +95 -204
  19. package/dist/components/form.css +1551 -421
  20. package/dist/components/hero.css +57 -0
  21. package/dist/components/index.css +7657 -7321
  22. package/dist/components/indicator.css +63 -0
  23. package/dist/components/input.css +114 -31
  24. package/dist/components/join.css +70 -0
  25. package/dist/components/kbd.css +28 -0
  26. package/dist/components/list.css +22 -3
  27. package/dist/components/mask.css +38 -0
  28. package/dist/components/otp-input.css +124 -6
  29. package/dist/components/radio.css +70 -0
  30. package/dist/components/range.css +41 -0
  31. package/dist/components/rating.css +39 -12
  32. package/dist/components/select.css +74 -0
  33. package/dist/components/sidebar-layout.css +66 -0
  34. package/dist/components/stack.css +56 -0
  35. package/dist/components/stat.css +40 -0
  36. package/dist/components/switch.css +70 -0
  37. package/dist/components/table.css +8 -0
  38. package/dist/components/textarea.css +74 -0
  39. package/dist/components/timeline.css +40 -25
  40. package/dist/components/toggle-switch.css +165 -0
  41. package/dist/components/toggle.css +198 -32
  42. package/dist/components/validator.css +66 -0
  43. package/dist/effects/aura.css +22 -0
  44. package/dist/effects/hover-3d.css +8 -0
  45. package/dist/effects/hover-gallery.css +14 -0
  46. package/dist/effects/index.css +65 -0
  47. package/dist/effects/text-rotate.css +16 -0
  48. package/dist/esm/components/accordion.js +33 -9
  49. package/dist/esm/components/autocomplete.js +67 -13
  50. package/dist/esm/components/avatar.js +39 -15
  51. package/dist/esm/components/badge.js +15 -3
  52. package/dist/esm/components/card.js +12 -0
  53. package/dist/esm/components/carousel.d.ts +5 -0
  54. package/dist/esm/components/carousel.js +37 -0
  55. package/dist/esm/components/chat.js +15 -11
  56. package/dist/esm/components/checkbox.js +84 -14
  57. package/dist/esm/components/collapse.js +67 -16
  58. package/dist/esm/components/countdown.d.ts +5 -0
  59. package/dist/esm/components/countdown.js +31 -0
  60. package/dist/esm/components/datepicker.js +77 -1
  61. package/dist/esm/components/diff.d.ts +5 -0
  62. package/dist/esm/components/diff.js +42 -0
  63. package/dist/esm/components/file-input.d.ts +5 -0
  64. package/dist/esm/components/file-input.js +116 -0
  65. package/dist/esm/components/filter-group.d.ts +5 -0
  66. package/dist/esm/components/filter-group.js +461 -0
  67. package/dist/esm/components/footer.d.ts +5 -0
  68. package/dist/esm/components/footer.js +57 -0
  69. package/dist/esm/components/form-group.js +96 -205
  70. package/dist/esm/components/form.js +1539 -409
  71. package/dist/esm/components/hero.d.ts +5 -0
  72. package/dist/esm/components/hero.js +66 -0
  73. package/dist/esm/components/indicator.d.ts +5 -0
  74. package/dist/esm/components/indicator.js +72 -0
  75. package/dist/esm/components/input.js +115 -32
  76. package/dist/esm/components/join.d.ts +5 -0
  77. package/dist/esm/components/join.js +79 -0
  78. package/dist/esm/components/kbd.d.ts +5 -0
  79. package/dist/esm/components/kbd.js +37 -0
  80. package/dist/esm/components/list.js +22 -3
  81. package/dist/esm/components/mask.d.ts +5 -0
  82. package/dist/esm/components/mask.js +47 -0
  83. package/dist/esm/components/otp-input.js +125 -7
  84. package/dist/esm/components/radio.js +71 -1
  85. package/dist/esm/components/range.d.ts +5 -0
  86. package/dist/esm/components/range.js +50 -0
  87. package/dist/esm/components/rating.js +39 -12
  88. package/dist/esm/components/select.js +75 -1
  89. package/dist/esm/components/sidebar-layout.d.ts +5 -0
  90. package/dist/esm/components/sidebar-layout.js +75 -0
  91. package/dist/esm/components/stack.d.ts +5 -0
  92. package/dist/esm/components/stack.js +65 -0
  93. package/dist/esm/components/stat.d.ts +5 -0
  94. package/dist/esm/components/stat.js +49 -0
  95. package/dist/esm/components/switch.js +71 -1
  96. package/dist/esm/components/table.js +8 -0
  97. package/dist/esm/components/textarea.js +75 -1
  98. package/dist/esm/components/timeline.js +40 -25
  99. package/dist/esm/components/toggle-switch.d.ts +5 -0
  100. package/dist/esm/components/toggle-switch.js +174 -0
  101. package/dist/esm/components/toggle.js +198 -32
  102. package/dist/esm/components/validator.d.ts +5 -0
  103. package/dist/esm/components/validator.js +75 -0
  104. package/dist/esm/effects/aura.d.ts +5 -0
  105. package/dist/esm/effects/aura.js +31 -0
  106. package/dist/esm/effects/hover-3d.d.ts +5 -0
  107. package/dist/esm/effects/hover-3d.js +17 -0
  108. package/dist/esm/effects/hover-gallery.d.ts +5 -0
  109. package/dist/esm/effects/hover-gallery.js +23 -0
  110. package/dist/esm/effects/index.d.ts +5 -0
  111. package/dist/esm/effects/index.js +74 -0
  112. package/dist/esm/effects/text-rotate.d.ts +5 -0
  113. package/dist/esm/effects/text-rotate.js +25 -0
  114. package/dist/index.css +8324 -7989
  115. package/dist/index.min.css +1 -1
  116. package/dist/standalone/duskmoonui-themes.css +1 -1
  117. package/dist/standalone/duskmoonui.css +9103 -8759
  118. package/dist/standalone/duskmoonui.js +12 -13
  119. package/dist/standalone/duskmoonui.mjs +12 -13
  120. package/dist/types/types/plugin.d.ts +1 -1
  121. package/dist/types/types/plugin.d.ts.map +1 -1
  122. package/package.json +140 -1
@@ -4,6 +4,8 @@
4
4
  */
5
5
 
6
6
  @layer components {
7
+ :where(.autocomplete, .autocomplete *) { box-sizing: border-box; }
8
+
7
9
  /* Autocomplete Container */
8
10
  .autocomplete {
9
11
  position: relative;
@@ -14,6 +16,7 @@
14
16
  /* Autocomplete Input */
15
17
  .autocomplete-input {
16
18
  width: 100%;
19
+ min-inline-size: 0;
17
20
  padding: 0.75rem 1rem;
18
21
  font-size: 0.875rem;
19
22
  line-height: 1.5;
@@ -24,6 +27,37 @@
24
27
  transition: border-color 150ms ease-in-out, box-shadow 150ms ease-in-out;
25
28
  }
26
29
 
30
+ .autocomplete-input-wrapper {
31
+ position: relative;
32
+ display: flex;
33
+ align-items: center;
34
+ }
35
+
36
+ .autocomplete-toggle {
37
+ position: absolute;
38
+ inset-inline-end: 0.125rem;
39
+ inset-block-start: 50%;
40
+ transform: translateY(-50%);
41
+ display: grid;
42
+ place-items: center;
43
+ inline-size: 2.75rem;
44
+ block-size: 2.75rem;
45
+ padding: 0;
46
+ font: inherit;
47
+ color: var(--color-on-surface);
48
+ background: transparent;
49
+ border: none;
50
+ border-radius: var(--radius-sm);
51
+ cursor: pointer;
52
+ }
53
+
54
+ .autocomplete-toggle:hover:not(:disabled) { background-color: var(--color-surface-container); }
55
+ .autocomplete-toggle:focus-visible { outline: 2px solid currentColor; outline-offset: -3px; }
56
+ .autocomplete-toggle:disabled { opacity: 0.38; cursor: not-allowed; }
57
+ .autocomplete-sm .autocomplete-toggle { inline-size: 1.75rem; block-size: 1.75rem; }
58
+ .autocomplete-outlined .autocomplete-input { background-color: transparent; }
59
+ .autocomplete-options { list-style: none; margin: 0; padding: 0.25rem; }
60
+
27
61
  .autocomplete-input:focus {
28
62
  outline: none;
29
63
  box-shadow: 0 0 0 3px color-mix(in oklch, currentColor 20%, transparent);
@@ -40,8 +74,7 @@
40
74
  .autocomplete-dropdown {
41
75
  position: absolute;
42
76
  top: 100%;
43
- left: 0;
44
- right: 0;
77
+ inset-inline: 0;
45
78
  z-index: 1000;
46
79
  max-height: 15rem;
47
80
  margin-top: 0.25rem;
@@ -57,12 +90,18 @@
57
90
  }
58
91
 
59
92
  .autocomplete.autocomplete-open .autocomplete-dropdown,
93
+ .autocomplete-dropdown.autocomplete-dropdown-open,
60
94
  .autocomplete-dropdown.show {
61
95
  opacity: 1;
62
96
  visibility: visible;
63
97
  transform: translateY(0);
64
98
  }
65
99
 
100
+ .autocomplete-dropdown[hidden],
101
+ .autocomplete-option[hidden],
102
+ .autocomplete-no-results[hidden],
103
+ .autocomplete-no-options[hidden] { display: none; }
104
+
66
105
  /* Autocomplete Options */
67
106
  .autocomplete-option {
68
107
  display: flex;
@@ -77,16 +116,20 @@
77
116
 
78
117
  .autocomplete-option:hover,
79
118
  .autocomplete-option:focus,
119
+ .autocomplete-option.autocomplete-option-focused,
80
120
  .autocomplete-option.highlighted {
81
121
  background-color: var(--color-surface-container);
82
122
  }
83
123
 
84
- .autocomplete-option.selected {
124
+ .autocomplete-option.selected,
125
+ .autocomplete-option.autocomplete-option-selected,
126
+ .autocomplete-option[aria-selected="true"] {
85
127
  background-color: var(--color-primary-container);
86
128
  color: var(--color-on-primary-container);
87
129
  }
88
130
 
89
131
  .autocomplete-option:disabled,
132
+ .autocomplete-option[aria-disabled="true"],
90
133
  .autocomplete-option.disabled {
91
134
  color: var(--color-on-surface-variant);
92
135
  cursor: not-allowed;
@@ -133,7 +176,8 @@
133
176
  }
134
177
 
135
178
  /* Group Header */
136
- .autocomplete-group-header {
179
+ .autocomplete-group-header,
180
+ .autocomplete-group-label {
137
181
  padding: 0.5rem 1rem;
138
182
  font-size: 0.75rem;
139
183
  font-weight: 600;
@@ -144,7 +188,8 @@
144
188
  }
145
189
 
146
190
  /* No Results */
147
- .autocomplete-no-results {
191
+ .autocomplete-no-results,
192
+ .autocomplete-no-options {
148
193
  padding: 1rem;
149
194
  text-align: center;
150
195
  font-size: 0.875rem;
@@ -164,7 +209,7 @@
164
209
  /* Clear Button */
165
210
  .autocomplete-clear {
166
211
  position: absolute;
167
- right: 0.75rem;
212
+ inset-inline-end: 0.75rem;
168
213
  top: 50%;
169
214
  transform: translateY(-50%);
170
215
  display: flex;
@@ -187,28 +232,31 @@
187
232
 
188
233
  /* With Clear Button */
189
234
  .autocomplete-clearable .autocomplete-input {
190
- padding-right: 2.5rem;
235
+ padding-inline-end: 2.5rem;
191
236
  }
192
237
 
193
238
  /* Multi-select Tags */
194
- .autocomplete-tags {
239
+ .autocomplete-tags,
240
+ .autocomplete-chips {
195
241
  display: flex;
196
242
  flex-wrap: wrap;
197
243
  gap: 0.25rem;
198
244
  padding: 0.375rem;
199
- padding-right: 2.5rem;
245
+ padding-inline-end: 2.5rem;
200
246
  min-height: 2.75rem;
201
247
  background-color: var(--color-surface);
202
248
  border: 1px solid var(--color-outline);
203
249
  border-radius: var(--radius-sm);
204
250
  }
205
251
 
206
- .autocomplete-tags:focus-within {
252
+ .autocomplete-tags:focus-within,
253
+ .autocomplete-chips:focus-within {
207
254
  border-color: var(--color-primary);
208
255
  box-shadow: 0 0 0 3px var(--color-primary-container);
209
256
  }
210
257
 
211
- .autocomplete-tag {
258
+ .autocomplete-tag,
259
+ .autocomplete-chip {
212
260
  display: inline-flex;
213
261
  align-items: center;
214
262
  gap: 0.25rem;
@@ -219,7 +267,8 @@
219
267
  border-radius: var(--radius-xs);
220
268
  }
221
269
 
222
- .autocomplete-tag-remove {
270
+ .autocomplete-tag-remove,
271
+ .autocomplete-chip-remove {
223
272
  display: flex;
224
273
  align-items: center;
225
274
  justify-content: center;
@@ -233,7 +282,8 @@
233
282
  transition: background-color 150ms ease-in-out;
234
283
  }
235
284
 
236
- .autocomplete-tag-remove:hover {
285
+ .autocomplete-tag-remove:hover,
286
+ .autocomplete-chip-remove:hover {
237
287
  background-color: var(--color-on-primary-container);
238
288
  color: var(--color-primary-container);
239
289
  }
@@ -341,6 +391,10 @@
341
391
  font-size: 1rem;
342
392
  }
343
393
 
394
+ /* Reserve the toggle's space after size shorthands set input padding. */
395
+ .autocomplete-input-wrapper .autocomplete-input { padding-inline-end: 3.25rem; }
396
+ .autocomplete-sm .autocomplete-input-wrapper .autocomplete-input { padding-inline-end: 2.25rem; }
397
+
344
398
  /* Reduce Motion */
345
399
  @media (prefers-reduced-motion: reduce) {
346
400
  .autocomplete-dropdown {
@@ -13,7 +13,7 @@
13
13
  width: 3rem;
14
14
  height: 3rem;
15
15
  border-radius: var(--radius-full);
16
- overflow: hidden;
16
+ overflow: visible;
17
17
  background-color: var(--color-surface-container);
18
18
  color: var(--color-on-surface);
19
19
  font-weight: 500;
@@ -24,6 +24,7 @@
24
24
  width: 100%;
25
25
  height: 100%;
26
26
  object-fit: cover;
27
+ border-radius: inherit;
27
28
  }
28
29
 
29
30
  /* Avatar Placeholder */
@@ -33,7 +34,9 @@
33
34
  justify-content: center;
34
35
  width: 100%;
35
36
  height: 100%;
36
- font-size: 1.25rem;
37
+ font-size: inherit;
38
+ border-radius: inherit;
39
+ overflow: hidden;
37
40
  text-transform: uppercase;
38
41
  }
39
42
 
@@ -135,24 +138,28 @@
135
138
  }
136
139
 
137
140
  .avatar-ring-primary {
138
- outline-color: var(--color-primary);
141
+ box-shadow: 0 0 0 3px var(--color-primary);
139
142
  }
140
143
 
141
144
  .avatar-ring-secondary {
142
- outline-color: var(--color-secondary);
145
+ box-shadow: 0 0 0 3px var(--color-secondary);
143
146
  }
144
147
 
145
148
  .avatar-ring-tertiary {
146
- outline-color: var(--color-tertiary);
149
+ box-shadow: 0 0 0 3px var(--color-tertiary);
147
150
  }
148
151
 
149
152
  /* Online/Offline Indicator */
150
153
  .avatar-online::after,
151
- .avatar-offline::after {
154
+ .avatar-offline::after,
155
+ .avatar-status-online::after,
156
+ .avatar-status-offline::after,
157
+ .avatar-status-busy::after,
158
+ .avatar-status-away::after {
152
159
  content: '';
153
160
  position: absolute;
154
- bottom: 0;
155
- right: 0;
161
+ inset-block-end: 0;
162
+ inset-inline-end: 0;
156
163
  width: 25%;
157
164
  height: 25%;
158
165
  min-width: 0.5rem;
@@ -161,14 +168,19 @@
161
168
  border: 2px solid var(--color-surface);
162
169
  }
163
170
 
164
- .avatar-online::after {
171
+ .avatar-online::after,
172
+ .avatar-status-online::after {
165
173
  background-color: var(--color-success);
166
174
  }
167
175
 
168
- .avatar-offline::after {
176
+ .avatar-offline::after,
177
+ .avatar-status-offline::after {
169
178
  background-color: var(--color-outline);
170
179
  }
171
180
 
181
+ .avatar-status-busy::after { background-color: var(--color-error); }
182
+ .avatar-status-away::after { background-color: var(--color-warning); }
183
+
172
184
  /* Avatar Group */
173
185
  .avatar-group {
174
186
  display: flex;
@@ -178,21 +190,33 @@
178
190
 
179
191
  .avatar-group .avatar {
180
192
  border: 2px solid var(--color-surface);
181
- margin-left: -0.75rem;
193
+ margin-inline-start: -0.75rem;
182
194
  }
183
195
 
184
196
  .avatar-group .avatar:last-child {
185
- margin-left: 0;
197
+ margin-inline-start: 0;
186
198
  }
187
199
 
188
200
  /* Avatar Group Sizes */
189
201
  .avatar-group-sm .avatar {
190
- margin-left: -0.5rem;
202
+ margin-inline-start: -0.5rem;
191
203
  }
192
204
 
193
205
  .avatar-group-lg .avatar {
194
- margin-left: -1rem;
195
- }
206
+ margin-inline-start: -1rem;
207
+ }
208
+
209
+ /* Historical documented composition classes. */
210
+ .avatar-image { inline-size: 100%; block-size: 100%; border-radius: inherit; overflow: hidden; }
211
+ .avatar-icon { display: inline-flex; align-items: center; justify-content: center; inline-size: 100%; block-size: 100%; }
212
+ .avatar-circle { border-radius: var(--radius-full); }
213
+ .avatar-bordered { border: 2px solid currentColor; }
214
+ .avatar-clickable { cursor: pointer; }
215
+ .avatar-overflow { font-size: 0.875rem; }
216
+ .avatar-group-dense > .avatar { margin-inline-start: -1rem; }
217
+ .avatar-group-xs > .avatar { inline-size: 1.5rem; block-size: 1.5rem; font-size: 0.625rem; }
218
+ .avatar-group-xl > .avatar { inline-size: 6rem; block-size: 6rem; font-size: 2rem; }
219
+ .avatar-group-dense > .avatar:last-child { margin-inline-start: 0; }
196
220
 
197
221
  /* Focus State for Interactive Avatars */
198
222
  .avatar:focus-visible {
@@ -6,6 +6,7 @@
6
6
  @layer components {
7
7
  /* Base Badge */
8
8
  .badge {
9
+ box-sizing: border-box;
9
10
  display: inline-flex;
10
11
  align-items: center;
11
12
  justify-content: center;
@@ -13,7 +14,10 @@
13
14
  font-size: 0.75rem;
14
15
  font-weight: 500;
15
16
  line-height: 1rem;
16
- white-space: nowrap;
17
+ white-space: normal;
18
+ max-inline-size: 100%;
19
+ overflow-wrap: anywhere;
20
+ min-inline-size: 0;
17
21
  border-radius: var(--radius-full);
18
22
  background-color: var(--color-surface-container);
19
23
  color: var(--color-on-surface);
@@ -227,13 +231,13 @@
227
231
  /* Badge with Indicator Dot */
228
232
  .badge-indicator {
229
233
  position: relative;
230
- padding-left: 1rem;
234
+ padding-inline-start: 1rem;
231
235
  }
232
236
 
233
237
  .badge-indicator::before {
234
238
  content: '';
235
239
  position: absolute;
236
- left: 0.375rem;
240
+ inset-inline-start: 0.375rem;
237
241
  top: 50%;
238
242
  transform: translateY(-50%);
239
243
  width: 0.375rem;
@@ -242,6 +246,14 @@
242
246
  background-color: currentColor;
243
247
  }
244
248
 
249
+ .badge-filled { font-weight: 500; }
250
+ .badge-md { padding: 0.125rem 0.5rem; font-size: 0.75rem; line-height: 1rem; }
251
+ .badge-notification { position: absolute; inset-block-start: 0; inset-inline-end: 0; transform: translate(50%, -50%); }
252
+ .badge-notification:dir(rtl) { transform: translate(-50%, -50%); }
253
+ .badge-removable { gap: 0.25rem; }
254
+ .badge-removable > button { display: inline-flex; padding: 0; border: 0; color: inherit; background: transparent; cursor: pointer; }
255
+ .badge-removable > button:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
256
+
245
257
  /* Empty Badge (just a dot) */
246
258
  .badge-dot {
247
259
  width: 0.5rem;
@@ -36,6 +36,8 @@
36
36
 
37
37
  /* Card Body */
38
38
  .card-body {
39
+ min-inline-size: 0;
40
+ overflow-wrap: anywhere;
39
41
  --card-p: 1.5rem;
40
42
  display: flex;
41
43
  flex-direction: column;
@@ -100,6 +102,16 @@
100
102
  border: 1px solid var(--color-outline);
101
103
  box-shadow: none;
102
104
  }
105
+ .card-outlined { border: 1px solid var(--color-outline); box-shadow: none; }
106
+ .card-outlined:hover { box-shadow: none; }
107
+ .card-filled { background: var(--color-surface-container-highest); box-shadow: none; }
108
+ .card-lowest { background: var(--color-surface-container-lowest); box-shadow: none; }
109
+ .card-low { background: var(--color-surface-container-low); box-shadow: var(--shadow-sm); }
110
+ .card-default { background: var(--color-surface-container); box-shadow: var(--shadow-md); }
111
+ .card-high { background: var(--color-surface-container-high); box-shadow: var(--shadow-lg); }
112
+ .card-highest { background: var(--color-surface-container-highest); box-shadow: var(--shadow-xl); }
113
+ .card-subtitle { color: var(--color-on-surface-variant); font-size: 0.875rem; }
114
+ .card-comfortable .card-body { --card-p: 2rem; }
103
115
 
104
116
  .card-bordered:hover {
105
117
  box-shadow: none;
@@ -0,0 +1,28 @@
1
+ @layer components {
2
+ .carousel {
3
+ display: flex;
4
+ gap: 1rem;
5
+ max-inline-size: 100%;
6
+ min-inline-size: 0;
7
+ overflow: auto;
8
+ scroll-snap-type: inline mandatory;
9
+ scroll-behavior: smooth;
10
+ color: var(--color-on-surface);
11
+ }
12
+ .carousel-item { flex: none; min-inline-size: 0; max-inline-size: 100%; scroll-snap-align: start; overflow-wrap: anywhere; }
13
+ .carousel-horizontal { flex-direction: row; scroll-snap-type: inline mandatory; }
14
+ .carousel-center > .carousel-item { scroll-snap-align: center; }
15
+ .carousel-end > .carousel-item { scroll-snap-align: end; }
16
+ .carousel-start > .carousel-item { scroll-snap-align: start; }
17
+ .carousel-vertical { flex-direction: column; max-block-size: var(--carousel-height, 24rem); scroll-snap-type: block mandatory; }
18
+ .carousel:focus-visible, .carousel-item:focus-visible { outline: 2px solid var(--color-primary); outline-offset: -2px; }
19
+ @media (prefers-reduced-motion: reduce) { .carousel { scroll-behavior: auto; } }
20
+ @media print { .carousel { flex-wrap: wrap; overflow: visible; max-block-size: none; } }
21
+ .carousel-primary { color: var(--color-primary); }
22
+ .carousel-secondary { color: var(--color-secondary); }
23
+ .carousel-tertiary { color: var(--color-tertiary); }
24
+ .carousel-info { color: var(--color-info); }
25
+ .carousel-success { color: var(--color-success); }
26
+ .carousel-warning { color: var(--color-warning); }
27
+ .carousel-error { color: var(--color-error); }
28
+ }
@@ -431,6 +431,8 @@
431
431
  align-items: stretch;
432
432
  gap: 0.5rem;
433
433
  max-width: min(80ch, 100%);
434
+ min-inline-size: 0;
435
+ box-sizing: border-box;
434
436
  padding: 0.625rem 0.875rem;
435
437
  border-radius: 1rem;
436
438
  background-color: var(--chat-bubble-bg);
@@ -445,39 +447,41 @@
445
447
  .chat-bubble-content {
446
448
  min-width: 0;
447
449
  }
450
+ .chat-bubble pre { max-inline-size: 100%; min-inline-size: 0; overflow: auto; white-space: pre; }
451
+ .chat-bubble a { overflow-wrap: anywhere; text-decoration: underline; }
448
452
 
449
453
  .chat-start .chat-bubble::before,
450
454
  .chat-end .chat-bubble::before {
451
455
  content: "";
452
456
  position: absolute;
453
- top: 0;
454
- width: calc(1rem - 2px);
455
- height: calc(1rem - 2px);
457
+ inset-block-start: 0;
458
+ inline-size: 0.75rem;
459
+ block-size: 1rem;
456
460
  background-color: var(--chat-bubble-bg);
457
- clip-path: polygon(0 0, 100% 0, 100% 100%);
458
- filter:
459
- drop-shadow(-1px 0 0 var(--color-outline-variant))
460
- drop-shadow(0 -1px 0 var(--color-outline-variant));
461
+ mask-image: radial-gradient(ellipse at 0 100%, transparent 68%, black 72%);
461
462
  pointer-events: none;
462
463
  }
463
464
 
464
465
  .chat-start .chat-bubble::before {
465
- left: -0.5rem;
466
+ inset-inline-start: -0.5rem;
466
467
  }
467
468
 
468
469
  .chat-start .chat-bubble {
469
- border-top-left-radius: 0;
470
+ border-start-start-radius: 0;
470
471
  }
471
472
 
472
473
  .chat-end .chat-bubble::before {
473
- right: -0.5rem;
474
+ inset-inline-end: -0.5rem;
474
475
  transform: scaleX(-1);
475
476
  }
476
477
 
477
478
  .chat-end .chat-bubble {
478
- border-top-right-radius: 0;
479
+ border-start-end-radius: 0;
479
480
  }
480
481
 
482
+ .chat-start:dir(rtl) .chat-bubble::before { transform: scaleX(-1); }
483
+ .chat-end:dir(rtl) .chat-bubble::before { transform: none; }
484
+
481
485
  .chat-bubble-primary {
482
486
  --chat-bubble-bg: var(--color-primary-container);
483
487
  --chat-bubble-fg: var(--color-on-primary-container);
@@ -1,3 +1,71 @@
1
+ /** Opt-in native presentation. Applications own errors, messages and announcements. */
2
+ @layer components {
3
+ /* Compatibility wrapper states are intentionally immediate. */
4
+ :is(.form-group-info, .form-control.info) { --dm-validation-color: var(--color-info); }
5
+ :is(.form-group-warning, .form-control.warning) { --dm-validation-color: var(--color-warning); }
6
+ :is(.form-group-success, .form-control.success) { --dm-validation-color: var(--color-success); }
7
+
8
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :valid, .validate:valid, .validator.validator-success:user-valid):not([aria-invalid="true"]):not(:where(.form-group-error *, .form-control.error *)):not(:disabled) {
9
+ --dm-validation-color: var(--color-success);
10
+ --dm-validation-content: var(--color-success-content);
11
+ }
12
+
13
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is(.validate :invalid, .validate:invalid, .validator:user-invalid):not(:disabled) {
14
+ --dm-validation-color: var(--color-error);
15
+ --dm-validation-content: var(--color-error-content);
16
+ }
17
+
18
+ :is(.form-group-error, .form-control.error) {
19
+ --dm-validation-color: var(--color-error);
20
+ --dm-validation-content: var(--color-error-content);
21
+ }
22
+
23
+ /* Higher specificity than native states, including server-invalid + user-valid. */
24
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .form-group-error *, .form-control.error *):not(:disabled):is(:focus, :not(:focus)) {
25
+ --dm-validation-color: var(--color-error);
26
+ --dm-validation-content: var(--color-error-content);
27
+ }
28
+
29
+ /* This shared selector wins over filled/ghost focus and semantic modifiers. */
30
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled) {
31
+ color: var(--dm-validation-color);
32
+ border-color: var(--dm-validation-color);
33
+ --checkbox-color: var(--dm-validation-color);
34
+ --radio-color: var(--dm-validation-color);
35
+ --switch-color: var(--dm-validation-color);
36
+ --switch-content-color: var(--dm-validation-content, var(--color-primary-content));
37
+ --toggle-color: var(--dm-validation-color);
38
+ }
39
+
40
+ :is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):is([aria-invalid="true"], .validator:user-invalid, .validator.validator-success:user-valid, .validate :invalid, .validate :valid, .validate:invalid, .validate:valid, .form-group-error *, .form-group-success *, .form-group-warning *, .form-group-info *, .form-control.error *, .form-control.success *, .form-control.warning *, .form-control.info *):not(:disabled):focus {
41
+ border-color: var(--dm-validation-color);
42
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--dm-validation-color) 20%, transparent);
43
+ }
44
+
45
+ :is(.form-group-error, .form-control.error) :is(.form-label, .label-text) { color: var(--color-error); }
46
+ :is(.form-group-success, .form-control.success) :is(.form-label, .label-text) { color: var(--color-success); }
47
+ :is(.form-group-warning, .form-control.warning) :is(.form-label, .label-text) { color: var(--color-warning); }
48
+ :is(.form-group-info, .form-control.info) :is(.form-label, .label-text) { color: var(--color-info); }
49
+
50
+ .validator-hint { font-size: 0.75rem; color: var(--color-on-surface-variant); }
51
+ .validator-error { display: none; font-size: 0.75rem; color: var(--color-error); }
52
+ /* Keep OTP actions stationary when blur reveals an error during a click. */
53
+ .otp-code ~ .validator-error { display: block; visibility: hidden; }
54
+ :is(.form-group, .form-control):has(:is([aria-invalid="true"], .validator:user-invalid, .validate :invalid, .validate:invalid):not(:disabled)) > .validator-error,
55
+ :is(.form-group-error, .form-control.error) > .validator-error { display: block; visibility: visible; }
56
+
57
+ @media (forced-colors: active) {
58
+ :is(input, select, textarea):is(.input, .select, .textarea, .checkbox, .radio, .switch, .toggle, .file-input, .otp-input-field, .otp-code, .datepicker-input):focus-visible {
59
+ outline: 2px solid Highlight;
60
+ outline-offset: 2px;
61
+ }
62
+ input:is(.checkbox, .radio, .switch, .toggle) { appearance: auto; }
63
+ input:is(.checkbox, .radio, .switch, .toggle)::before,
64
+ input:is(.checkbox, .radio, .switch, .toggle)::after { content: none; }
65
+ }
66
+ }
67
+
68
+
1
69
  /**
2
70
  * Checkbox Component Styles
3
71
  * DuskMoonUI - Material Design 3 inspired checkbox
@@ -7,6 +75,8 @@
7
75
  */
8
76
 
9
77
  @layer components {
78
+ :where(.checkbox) { box-sizing: border-box; }
79
+
10
80
  /* Base Checkbox - applied directly to input[type="checkbox"] */
11
81
  .checkbox {
12
82
  --checkbox-size: 1.25rem;
@@ -35,8 +105,8 @@
35
105
  height: 0.35em;
36
106
  transform: scale(0) rotate(-45deg);
37
107
  transform-origin: center;
38
- border-bottom: 2px solid var(--color-primary-content);
39
- border-left: 2px solid var(--color-primary-content);
108
+ border-bottom: 2px solid var(--dm-validation-content, var(--color-primary-content));
109
+ border-left: 2px solid var(--dm-validation-content, var(--color-primary-content));
40
110
  transition: transform 150ms ease-in-out;
41
111
  }
42
112
 
@@ -59,7 +129,7 @@
59
129
  .checkbox:indeterminate::before {
60
130
  width: 0.5em;
61
131
  height: 0;
62
- border-bottom: 2px solid var(--color-primary-content);
132
+ border-bottom: 2px solid var(--dm-validation-content, var(--color-primary-content));
63
133
  border-left: 0;
64
134
  transform: scale(1) rotate(0deg);
65
135
  }
@@ -121,7 +191,7 @@
121
191
 
122
192
  .checkbox-primary:checked::before,
123
193
  .checkbox-primary:indeterminate::before {
124
- border-color: var(--color-primary-content);
194
+ border-color: var(--dm-validation-content, var(--color-primary-content));
125
195
  }
126
196
 
127
197
  .checkbox-secondary {
@@ -130,7 +200,7 @@
130
200
 
131
201
  .checkbox-secondary:checked::before,
132
202
  .checkbox-secondary:indeterminate::before {
133
- border-color: var(--color-secondary-content);
203
+ border-color: var(--dm-validation-content, var(--color-secondary-content));
134
204
  }
135
205
 
136
206
  .checkbox-tertiary {
@@ -139,7 +209,7 @@
139
209
 
140
210
  .checkbox-tertiary:checked::before,
141
211
  .checkbox-tertiary:indeterminate::before {
142
- border-color: var(--color-tertiary-content);
212
+ border-color: var(--dm-validation-content, var(--color-tertiary-content));
143
213
  }
144
214
 
145
215
  .checkbox-success {
@@ -148,7 +218,7 @@
148
218
 
149
219
  .checkbox-success:checked::before,
150
220
  .checkbox-success:indeterminate::before {
151
- border-color: var(--color-success-content);
221
+ border-color: var(--dm-validation-content, var(--color-success-content));
152
222
  }
153
223
 
154
224
  .checkbox-warning {
@@ -157,7 +227,7 @@
157
227
 
158
228
  .checkbox-warning:checked::before,
159
229
  .checkbox-warning:indeterminate::before {
160
- border-color: var(--color-warning-content);
230
+ border-color: var(--dm-validation-content, var(--color-warning-content));
161
231
  }
162
232
 
163
233
  .checkbox-error {
@@ -166,7 +236,7 @@
166
236
 
167
237
  .checkbox-error:checked::before,
168
238
  .checkbox-error:indeterminate::before {
169
- border-color: var(--color-error-content);
239
+ border-color: var(--dm-validation-content, var(--color-error-content));
170
240
  }
171
241
 
172
242
  .checkbox-info {
@@ -175,7 +245,7 @@
175
245
 
176
246
  .checkbox-info:checked::before,
177
247
  .checkbox-info:indeterminate::before {
178
- border-color: var(--color-info-content);
248
+ border-color: var(--dm-validation-content, var(--color-info-content));
179
249
  }
180
250
 
181
251
  .checkbox-accent {
@@ -184,7 +254,7 @@
184
254
 
185
255
  .checkbox-accent:checked::before,
186
256
  .checkbox-accent:indeterminate::before {
187
- border-color: var(--color-accent-content);
257
+ border-color: var(--dm-validation-content, var(--color-accent-content));
188
258
  }
189
259
 
190
260
  .checkbox-neutral {
@@ -193,7 +263,7 @@
193
263
 
194
264
  .checkbox-neutral:checked::before,
195
265
  .checkbox-neutral:indeterminate::before {
196
- border-color: var(--color-neutral-content);
266
+ border-color: var(--dm-validation-content, var(--color-neutral-content));
197
267
  }
198
268
 
199
269
  .checkbox-base {
@@ -202,7 +272,7 @@
202
272
 
203
273
  .checkbox-base:checked::before,
204
274
  .checkbox-base:indeterminate::before {
205
- border-color: var(--color-base-content);
275
+ border-color: var(--dm-validation-content, var(--color-base-content));
206
276
  }
207
277
 
208
278
  /* Ghost Variant — borderless unchecked state */