@duskmoon-dev/core 1.17.2 → 1.18.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.
package/README.md CHANGED
@@ -140,7 +140,7 @@ Theme switching is instant and uses pure CSS custom properties.
140
140
  | Skeleton | `.skeleton`, `.skeleton-text`, `.skeleton-circle`, `.skeleton-wave` | Loading placeholders |
141
141
  | Snackbar | `.snackbar`, `.snackbar-message`, `.snackbar-action` | Brief notifications |
142
142
  | Toast | `.toast`, `.toast-container`, `.toast-info`, `.toast-success` | Toast notifications |
143
- | Tooltip | `.tooltip`, `.tooltip-content`, `.tooltip-top`, `.tooltip-bottom` | Hover tooltips |
143
+ | Tooltip | `.tooltip[popover]`, `.tooltip-top`, `.tooltip-bottom` | Hint popovers (`interestfor`) |
144
144
 
145
145
  ### Layout (2)
146
146
 
@@ -164,7 +164,7 @@ Theme switching is instant and uses pure CSS custom properties.
164
164
  | Accordion | `.accordion`, `.accordion-item`, `.accordion-header`, `.accordion-content` | Expandable panels |
165
165
  | Bottom Sheet | `.bottomsheet`, `.bottomsheet-handle`, `.bottomsheet-content` | Mobile sheets |
166
166
  | Collapse | `.collapse`, `.collapse-content`, `.collapse-toggle` | Collapsible content |
167
- | Popover | `.popover`, `.popover-content`, `.popover-arrow` | Floating content |
167
+ | Popover | `.popover[popover]`, `.popover-body`, `.popover-arrow` | Floating content (Popover API) |
168
168
 
169
169
  ### Misc (1)
170
170
 
@@ -441,3 +441,5 @@ See [specs/004-oklch-color-system/quickstart.md](./specs/004-oklch-color-system/
441
441
  ## License
442
442
 
443
443
  MIT
444
+
445
+ <!-- release 32244683531 -->
@@ -129,6 +129,56 @@
129
129
  filter: none;
130
130
  }
131
131
 
132
+ /* Semantic Colors — must precede outline/ghost/text/tonal so those variants
133
+ can override the filled background at equal specificity. */
134
+ .btn-info {
135
+ --btn-text-color: var(--color-info-content);
136
+ background-color: var(--color-info);
137
+ border-color: var(--color-info);
138
+ }
139
+
140
+ .btn-info:hover {
141
+ background-color: color-mix(in oklch, var(--color-info), black 10%);
142
+ border-color: color-mix(in oklch, var(--color-info), black 10%);
143
+ filter: none;
144
+ }
145
+
146
+ .btn-success {
147
+ --btn-text-color: var(--color-success-content);
148
+ background-color: var(--color-success);
149
+ border-color: var(--color-success);
150
+ }
151
+
152
+ .btn-success:hover {
153
+ background-color: color-mix(in oklch, var(--color-success), black 10%);
154
+ border-color: color-mix(in oklch, var(--color-success), black 10%);
155
+ filter: none;
156
+ }
157
+
158
+ .btn-warning {
159
+ --btn-text-color: var(--color-warning-content);
160
+ background-color: var(--color-warning);
161
+ border-color: var(--color-warning);
162
+ }
163
+
164
+ .btn-warning:hover {
165
+ background-color: color-mix(in oklch, var(--color-warning), black 10%);
166
+ border-color: color-mix(in oklch, var(--color-warning), black 10%);
167
+ filter: none;
168
+ }
169
+
170
+ .btn-error {
171
+ --btn-text-color: var(--color-error-content);
172
+ background-color: var(--color-error);
173
+ border-color: var(--color-error);
174
+ }
175
+
176
+ .btn-error:hover {
177
+ background-color: color-mix(in oklch, var(--color-error), black 10%);
178
+ border-color: color-mix(in oklch, var(--color-error), black 10%);
179
+ filter: none;
180
+ }
181
+
132
182
  /* Outline / Outlined Variant (.btn-outlined is an alias) */
133
183
  .btn-outline,
134
184
  .btn-outlined {
@@ -488,55 +538,6 @@
488
538
  background-color: var(--color-error-container);
489
539
  }
490
540
 
491
- /* Semantic Colors */
492
- .btn-info {
493
- --btn-text-color: var(--color-info-content);
494
- background-color: var(--color-info);
495
- border-color: var(--color-info);
496
- }
497
-
498
- .btn-info:hover {
499
- background-color: color-mix(in oklch, var(--color-info), black 10%);
500
- border-color: color-mix(in oklch, var(--color-info), black 10%);
501
- filter: none;
502
- }
503
-
504
- .btn-success {
505
- --btn-text-color: var(--color-success-content);
506
- background-color: var(--color-success);
507
- border-color: var(--color-success);
508
- }
509
-
510
- .btn-success:hover {
511
- background-color: color-mix(in oklch, var(--color-success), black 10%);
512
- border-color: color-mix(in oklch, var(--color-success), black 10%);
513
- filter: none;
514
- }
515
-
516
- .btn-warning {
517
- --btn-text-color: var(--color-warning-content);
518
- background-color: var(--color-warning);
519
- border-color: var(--color-warning);
520
- }
521
-
522
- .btn-warning:hover {
523
- background-color: color-mix(in oklch, var(--color-warning), black 10%);
524
- border-color: color-mix(in oklch, var(--color-warning), black 10%);
525
- filter: none;
526
- }
527
-
528
- .btn-error {
529
- --btn-text-color: var(--color-error-content);
530
- background-color: var(--color-error);
531
- border-color: var(--color-error);
532
- }
533
-
534
- .btn-error:hover {
535
- background-color: color-mix(in oklch, var(--color-error), black 10%);
536
- border-color: color-mix(in oklch, var(--color-error), black 10%);
537
- filter: none;
538
- }
539
-
540
541
  /* Size Variants */
541
542
  .btn-xs {
542
543
  --btn-p: 0.5rem;
@@ -1,9 +1,370 @@
1
- /**
2
- * Chat Component Styles
3
- * DuskMoonUI - LLM-oriented chat primitives
4
- */
5
-
6
1
  @layer components {
2
+ /**
3
+ * Scrollable transcript with Scroll-Driven Animations indicators.
4
+ * Set an explicit height / max-height (or place in a flex child with min-height: 0).
5
+ * Pair each .chat[data-chat-tl="N"] with .chat-scroll-indicator[data-chat-tl="N"] (N = 1..24).
6
+ */
7
+ .chat-scroll {
8
+ --chat-scroll-indicator-size: 0.875rem;
9
+ --chat-scroll-indicator-active-size: 1.125rem;
10
+ --chat-scroll-indicator-thickness: 0.1875rem;
11
+ --chat-scroll-indicator-gap: 0.3125rem;
12
+ --chat-scroll-indicator-hover-scale: 1.55;
13
+ --chat-scroll-indicator-neighbor-scale: 1.22;
14
+
15
+ container-type: size;
16
+ container-name: chat-scroll;
17
+ display: grid;
18
+ grid-template-columns: auto minmax(0, 1fr);
19
+ column-gap: 0.75rem;
20
+ align-items: start;
21
+ min-height: 0;
22
+ overflow-x: hidden;
23
+ overflow-y: auto;
24
+ scroll-behavior: smooth;
25
+ overscroll-behavior-y: contain;
26
+ timeline-scope:
27
+ --chat-1,
28
+ --chat-2,
29
+ --chat-3,
30
+ --chat-4,
31
+ --chat-5,
32
+ --chat-6,
33
+ --chat-7,
34
+ --chat-8,
35
+ --chat-9,
36
+ --chat-10,
37
+ --chat-11,
38
+ --chat-12,
39
+ --chat-13,
40
+ --chat-14,
41
+ --chat-15,
42
+ --chat-16,
43
+ --chat-17,
44
+ --chat-18,
45
+ --chat-19,
46
+ --chat-20,
47
+ --chat-21,
48
+ --chat-22,
49
+ --chat-23,
50
+ --chat-24;
51
+ }
52
+
53
+ .chat-scroll-track {
54
+ position: sticky;
55
+ top: 0;
56
+ z-index: 1;
57
+ display: flex;
58
+ flex-direction: column;
59
+ justify-content: center;
60
+ align-items: center;
61
+ gap: var(--chat-scroll-indicator-gap);
62
+ width: calc(
63
+ var(--chat-scroll-indicator-active-size) * var(--chat-scroll-indicator-hover-scale)
64
+ );
65
+ height: 100cqh;
66
+ margin: 0;
67
+ padding: 0.75rem 0;
68
+ overflow: visible;
69
+ list-style: none;
70
+ pointer-events: none;
71
+ }
72
+
73
+ .chat-scroll-body {
74
+ display: flex;
75
+ flex-direction: column;
76
+ min-width: 0;
77
+ }
78
+
79
+ .chat-scroll-indicator {
80
+ display: block;
81
+ flex-shrink: 0;
82
+ width: var(--chat-scroll-indicator-size);
83
+ height: var(--chat-scroll-indicator-thickness);
84
+ border: 0;
85
+ border-radius: 999px;
86
+ padding: 0;
87
+ appearance: none;
88
+ background-color: color-mix(in oklch, var(--color-on-surface) 28%, transparent);
89
+ color: inherit;
90
+ font: inherit;
91
+ opacity: 0.45;
92
+ pointer-events: auto;
93
+ text-decoration: none;
94
+ cursor: pointer;
95
+ transform: scaleX(1);
96
+ transform-origin: center;
97
+ transition:
98
+ transform 140ms ease,
99
+ opacity 140ms ease,
100
+ background-color 140ms ease;
101
+ }
102
+
103
+ .chat-scroll-indicator:hover,
104
+ .chat-scroll-indicator:focus-visible {
105
+ transform: scaleX(var(--chat-scroll-indicator-hover-scale)) scaleY(1.35);
106
+ background-color: var(--color-on-surface);
107
+ opacity: 1;
108
+ }
109
+
110
+ .chat-scroll-indicator:hover + .chat-scroll-indicator,
111
+ .chat-scroll-indicator:has(+ .chat-scroll-indicator:hover) {
112
+ transform: scaleX(var(--chat-scroll-indicator-neighbor-scale)) scaleY(1.15);
113
+ background-color: color-mix(in oklch, var(--color-on-surface) 55%, transparent);
114
+ opacity: 0.75;
115
+ }
116
+
117
+ .chat[data-chat-tl] {
118
+ scroll-margin-block-start: 0.5rem;
119
+ }
120
+
121
+ .chat-scroll-indicator:focus-visible {
122
+ outline: none;
123
+ box-shadow: 0 0 0 3px color-mix(in oklch, var(--color-primary) 20%, transparent);
124
+ }
125
+
126
+ @supports (animation-timeline: --chat-1) {
127
+ .chat-scroll-indicator {
128
+ animation-name: chat-scroll-indicator-activate;
129
+ animation-duration: 1ms;
130
+ animation-timing-function: linear;
131
+ animation-fill-mode: both;
132
+ animation-range: entry 0% exit 100%;
133
+ }
134
+ }
135
+
136
+ .chat[data-chat-tl="1"] {
137
+ view-timeline-name: --chat-1;
138
+ view-timeline-axis: block;
139
+ }
140
+
141
+ .chat[data-chat-tl="2"] {
142
+ view-timeline-name: --chat-2;
143
+ view-timeline-axis: block;
144
+ }
145
+
146
+ .chat[data-chat-tl="3"] {
147
+ view-timeline-name: --chat-3;
148
+ view-timeline-axis: block;
149
+ }
150
+
151
+ .chat[data-chat-tl="4"] {
152
+ view-timeline-name: --chat-4;
153
+ view-timeline-axis: block;
154
+ }
155
+
156
+ .chat[data-chat-tl="5"] {
157
+ view-timeline-name: --chat-5;
158
+ view-timeline-axis: block;
159
+ }
160
+
161
+ .chat[data-chat-tl="6"] {
162
+ view-timeline-name: --chat-6;
163
+ view-timeline-axis: block;
164
+ }
165
+
166
+ .chat[data-chat-tl="7"] {
167
+ view-timeline-name: --chat-7;
168
+ view-timeline-axis: block;
169
+ }
170
+
171
+ .chat[data-chat-tl="8"] {
172
+ view-timeline-name: --chat-8;
173
+ view-timeline-axis: block;
174
+ }
175
+
176
+ .chat[data-chat-tl="9"] {
177
+ view-timeline-name: --chat-9;
178
+ view-timeline-axis: block;
179
+ }
180
+
181
+ .chat[data-chat-tl="10"] {
182
+ view-timeline-name: --chat-10;
183
+ view-timeline-axis: block;
184
+ }
185
+
186
+ .chat[data-chat-tl="11"] {
187
+ view-timeline-name: --chat-11;
188
+ view-timeline-axis: block;
189
+ }
190
+
191
+ .chat[data-chat-tl="12"] {
192
+ view-timeline-name: --chat-12;
193
+ view-timeline-axis: block;
194
+ }
195
+
196
+ .chat[data-chat-tl="13"] {
197
+ view-timeline-name: --chat-13;
198
+ view-timeline-axis: block;
199
+ }
200
+
201
+ .chat[data-chat-tl="14"] {
202
+ view-timeline-name: --chat-14;
203
+ view-timeline-axis: block;
204
+ }
205
+
206
+ .chat[data-chat-tl="15"] {
207
+ view-timeline-name: --chat-15;
208
+ view-timeline-axis: block;
209
+ }
210
+
211
+ .chat[data-chat-tl="16"] {
212
+ view-timeline-name: --chat-16;
213
+ view-timeline-axis: block;
214
+ }
215
+
216
+ .chat[data-chat-tl="17"] {
217
+ view-timeline-name: --chat-17;
218
+ view-timeline-axis: block;
219
+ }
220
+
221
+ .chat[data-chat-tl="18"] {
222
+ view-timeline-name: --chat-18;
223
+ view-timeline-axis: block;
224
+ }
225
+
226
+ .chat[data-chat-tl="19"] {
227
+ view-timeline-name: --chat-19;
228
+ view-timeline-axis: block;
229
+ }
230
+
231
+ .chat[data-chat-tl="20"] {
232
+ view-timeline-name: --chat-20;
233
+ view-timeline-axis: block;
234
+ }
235
+
236
+ .chat[data-chat-tl="21"] {
237
+ view-timeline-name: --chat-21;
238
+ view-timeline-axis: block;
239
+ }
240
+
241
+ .chat[data-chat-tl="22"] {
242
+ view-timeline-name: --chat-22;
243
+ view-timeline-axis: block;
244
+ }
245
+
246
+ .chat[data-chat-tl="23"] {
247
+ view-timeline-name: --chat-23;
248
+ view-timeline-axis: block;
249
+ }
250
+
251
+ .chat[data-chat-tl="24"] {
252
+ view-timeline-name: --chat-24;
253
+ view-timeline-axis: block;
254
+ }
255
+
256
+ .chat-scroll-indicator[data-chat-tl="1"] {
257
+ animation-timeline: --chat-1;
258
+ }
259
+
260
+ .chat-scroll-indicator[data-chat-tl="2"] {
261
+ animation-timeline: --chat-2;
262
+ }
263
+
264
+ .chat-scroll-indicator[data-chat-tl="3"] {
265
+ animation-timeline: --chat-3;
266
+ }
267
+
268
+ .chat-scroll-indicator[data-chat-tl="4"] {
269
+ animation-timeline: --chat-4;
270
+ }
271
+
272
+ .chat-scroll-indicator[data-chat-tl="5"] {
273
+ animation-timeline: --chat-5;
274
+ }
275
+
276
+ .chat-scroll-indicator[data-chat-tl="6"] {
277
+ animation-timeline: --chat-6;
278
+ }
279
+
280
+ .chat-scroll-indicator[data-chat-tl="7"] {
281
+ animation-timeline: --chat-7;
282
+ }
283
+
284
+ .chat-scroll-indicator[data-chat-tl="8"] {
285
+ animation-timeline: --chat-8;
286
+ }
287
+
288
+ .chat-scroll-indicator[data-chat-tl="9"] {
289
+ animation-timeline: --chat-9;
290
+ }
291
+
292
+ .chat-scroll-indicator[data-chat-tl="10"] {
293
+ animation-timeline: --chat-10;
294
+ }
295
+
296
+ .chat-scroll-indicator[data-chat-tl="11"] {
297
+ animation-timeline: --chat-11;
298
+ }
299
+
300
+ .chat-scroll-indicator[data-chat-tl="12"] {
301
+ animation-timeline: --chat-12;
302
+ }
303
+
304
+ .chat-scroll-indicator[data-chat-tl="13"] {
305
+ animation-timeline: --chat-13;
306
+ }
307
+
308
+ .chat-scroll-indicator[data-chat-tl="14"] {
309
+ animation-timeline: --chat-14;
310
+ }
311
+
312
+ .chat-scroll-indicator[data-chat-tl="15"] {
313
+ animation-timeline: --chat-15;
314
+ }
315
+
316
+ .chat-scroll-indicator[data-chat-tl="16"] {
317
+ animation-timeline: --chat-16;
318
+ }
319
+
320
+ .chat-scroll-indicator[data-chat-tl="17"] {
321
+ animation-timeline: --chat-17;
322
+ }
323
+
324
+ .chat-scroll-indicator[data-chat-tl="18"] {
325
+ animation-timeline: --chat-18;
326
+ }
327
+
328
+ .chat-scroll-indicator[data-chat-tl="19"] {
329
+ animation-timeline: --chat-19;
330
+ }
331
+
332
+ .chat-scroll-indicator[data-chat-tl="20"] {
333
+ animation-timeline: --chat-20;
334
+ }
335
+
336
+ .chat-scroll-indicator[data-chat-tl="21"] {
337
+ animation-timeline: --chat-21;
338
+ }
339
+
340
+ .chat-scroll-indicator[data-chat-tl="22"] {
341
+ animation-timeline: --chat-22;
342
+ }
343
+
344
+ .chat-scroll-indicator[data-chat-tl="23"] {
345
+ animation-timeline: --chat-23;
346
+ }
347
+
348
+ .chat-scroll-indicator[data-chat-tl="24"] {
349
+ animation-timeline: --chat-24;
350
+ }
351
+
352
+ @keyframes chat-scroll-indicator-activate {
353
+ 0%,
354
+ 100% {
355
+ width: var(--chat-scroll-indicator-size);
356
+ background-color: color-mix(in oklch, var(--color-on-surface) 28%, transparent);
357
+ opacity: 0.45;
358
+ }
359
+
360
+ 35%,
361
+ 65% {
362
+ width: var(--chat-scroll-indicator-active-size);
363
+ background-color: var(--color-on-surface);
364
+ opacity: 1;
365
+ }
366
+ }
367
+
7
368
  .chat {
8
369
  display: grid;
9
370
  grid-template-columns: auto minmax(0, 1fr);
@@ -65,6 +426,10 @@
65
426
  --chat-bubble-fg: var(--color-on-surface);
66
427
 
67
428
  position: relative;
429
+ display: flex;
430
+ flex-direction: column;
431
+ align-items: stretch;
432
+ gap: 0.5rem;
68
433
  max-width: min(80ch, 100%);
69
434
  padding: 0.625rem 0.875rem;
70
435
  border-radius: 1rem;
@@ -77,6 +442,10 @@
77
442
  word-break: break-word;
78
443
  }
79
444
 
445
+ .chat-bubble-content {
446
+ min-width: 0;
447
+ }
448
+
80
449
  .chat-start .chat-bubble::before,
81
450
  .chat-end .chat-bubble::before,
82
451
  .chat-start .chat-bubble::after,
@@ -259,6 +628,14 @@
259
628
  overflow: hidden;
260
629
  }
261
630
 
631
+ .chat-bubble > .chat-reasoning,
632
+ .chat-bubble > .chat-tool,
633
+ .chat-reasoning .chat-tool,
634
+ .chat-reasoning-body > .chat-tool {
635
+ width: 100%;
636
+ max-width: none;
637
+ }
638
+
262
639
  .chat-reasoning > summary,
263
640
  .chat-tool > summary {
264
641
  cursor: pointer;
@@ -271,12 +648,28 @@
271
648
  font-weight: 500;
272
649
  }
273
650
 
274
- .chat-reasoning > :not(summary) {
651
+ .chat-reasoning-body {
652
+ display: flex;
653
+ flex-direction: column;
654
+ gap: 0.5rem;
655
+ padding: 0 0.75rem 0.75rem;
656
+ color: var(--color-on-surface-variant);
657
+ }
658
+
659
+ .chat-reasoning-body > :not(.chat-tool) {
660
+ font-style: italic;
661
+ }
662
+
663
+ .chat-reasoning > div:not(.chat-tool):not(.chat-reasoning-body) {
275
664
  padding: 0 0.75rem 0.75rem;
276
665
  color: var(--color-on-surface-variant);
277
666
  font-style: italic;
278
667
  }
279
668
 
669
+ .chat-reasoning > .chat-tool {
670
+ margin: 0 0.75rem 0.75rem;
671
+ }
672
+
280
673
  .chat-tool-header {
281
674
  display: flex;
282
675
  align-items: center;
@@ -371,7 +764,8 @@
371
764
  animation-delay: 300ms;
372
765
  }
373
766
 
374
- .chat-bubble-streaming::after {
767
+ .chat-bubble-streaming::after,
768
+ .chat-bubble-content.chat-bubble-streaming::after {
375
769
  content: "";
376
770
  display: inline-block;
377
771
  width: 1px;
@@ -382,6 +776,10 @@
382
776
  animation: chat-stream-caret 1s step-end infinite;
383
777
  }
384
778
 
779
+ .chat-bubble.chat-bubble-streaming:has(.chat-reasoning, .chat-tool, .chat-bubble-content)::after {
780
+ content: none;
781
+ }
782
+
385
783
  .chat-reasoning > summary:focus-visible,
386
784
  .chat-tool > summary:focus-visible {
387
785
  outline: none;
@@ -421,15 +819,26 @@
421
819
  }
422
820
 
423
821
  @media (prefers-reduced-motion: reduce) {
822
+ .chat-scroll {
823
+ scroll-behavior: auto;
824
+ }
825
+
826
+ .chat-scroll-indicator {
827
+ animation: none;
828
+ transition: none;
829
+ }
830
+
424
831
  .chat-typing::before,
425
832
  .chat-typing::after,
426
833
  .chat-typing span,
427
834
  .chat-bubble-streaming::after,
835
+ .chat-bubble-content.chat-bubble-streaming::after,
428
836
  .chat-tool-running .chat-tool-header::before {
429
837
  animation: none;
430
838
  }
431
839
 
432
- .chat-bubble-streaming::after {
840
+ .chat-bubble-streaming::after,
841
+ .chat-bubble-content.chat-bubble-streaming::after {
433
842
  opacity: 1;
434
843
  }
435
844
  }