@botiverse/raft-ui 0.10.7 → 0.12.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/CHANGELOG.md CHANGED
@@ -1,3 +1,29 @@
1
+ ## [0.12.0](https://github.com/botiverse/raft-design/compare/v0.11.0...v0.12.0) (2026-10-21)
2
+
3
+ ### Breaking
4
+
5
+ - `ComboboxSelect` always takes typing on a phone, as on a desktop: tapping the field focuses it and typing filters; `create` and remote search work in the field. The phone-only pick-only mode and bottom sheet from 0.10.5 are gone, with their props `sheetThreshold`, `sheetTitle` and `messages.search` / `done` / `close`. A pick-only field uses `Select`. The list still picks its side once and doesn't flip while the keyboard opens. ([#635](https://github.com/botiverse/raft-design/pull/635))
6
+
7
+ ### Added
8
+
9
+ - `ComboboxSelect` takes `listMaxHeight` (a CSS length or pixels, default `16rem`, the whole list's height); the side the list opens on follows it. ([#635](https://github.com/botiverse/raft-design/pull/635))
10
+ - Jump controls that float over a conversation, from `@botiverse/raft-ui/wip`: `MessageListJumpControls`, `MessageListJumpPill` (a Button `outline md`), `MessageListJumpPillGroup` and `MessageListJumpPillDismiss`. ([#637](https://github.com/botiverse/raft-design/pull/637))
11
+ - A message an assistant sent for its owner, from `@botiverse/raft-ui/wip`: `MessageItemDelegatedBy`, `MessageItemDelegatedByName`, `MessageItemDelegatedByButton`, `MessageItemDelegatedAvatar` (with `deleted`) and `MessageQuotedPreviewAuthorDelegatedBy`. ([#633](https://github.com/botiverse/raft-design/pull/633))
12
+
13
+ ### Fixed
14
+
15
+ - The 32px and 36px buttons' hit area reaches 44px; the overhang now counts the 1.5px border. ([#637](https://github.com/botiverse/raft-design/pull/637))
16
+ - Toast title and description use `text-callout` (desktop line height 20 to 22px). ([#637](https://github.com/botiverse/raft-design/pull/637))
17
+ - In a message header the name, notes (model, role, badge text) and time stand on one baseline. ([#639](https://github.com/botiverse/raft-design/pull/639))
18
+ - `MessageItemSenderGroup`: the gap before a role squeezed to nothing collapses with it. ([#633](https://github.com/botiverse/raft-design/pull/633))
19
+ - `VirtualList`: a jump holds its target row by key, so rows prepended while it settles don't move it; the focused row stays mounted across a window switch. ([#636](https://github.com/botiverse/raft-design/pull/636))
20
+
21
+ ## [0.11.0](https://github.com/botiverse/raft-design/compare/v0.10.7...v0.11.0) (2026-10-21)
22
+
23
+ ### Added
24
+
25
+ - `VirtualList`: a virtualized list for long, variable-height content such as a conversation, exported from the main entry. Rows are measured in block flow, so their margins collapse as in a plain list; it holds its anchor through items added above or below, jumps exactly to an item (`scrollTo` with `align`), lays out multi-column rows, and keeps mounted the row that holds focus (so End, Home, paging and wheel scrolling don't lose it) and the rows a text selection reaches into. The scroller takes native HTML attributes and its ref as `domRef`; styles are in `.r-virtual-list`. The implementation borrows from DeepSeek web's virtual list. ([#627](https://github.com/botiverse/raft-design/pull/627))
26
+
1
27
  ## [0.10.7](https://github.com/botiverse/raft-design/compare/v0.10.6...v0.10.7) (2026-10-21)
2
28
 
3
29
  ### Fixed
@@ -140,7 +140,7 @@
140
140
  width: var(--anchor-width, max-content);
141
141
  min-width: 13.75rem;
142
142
  max-width: var(--available-width);
143
- max-height: min(var(--available-height), 24rem);
143
+ max-height: min(var(--available-height), max(24rem, var(--combobox-select-list-max-height, 0px)));
144
144
  overflow: hidden;
145
145
  border: 0;
146
146
  border-radius: 10px;
@@ -152,7 +152,8 @@
152
152
  outline: 0;
153
153
  }
154
154
  .r-combobox-select__list {
155
- max-height: 16rem;
155
+ box-sizing: border-box;
156
+ max-height: var(--combobox-select-list-max-height, 16rem);
156
157
  overflow-y: auto;
157
158
  overscroll-behavior: contain;
158
159
  scroll-padding-block: 6px;
@@ -270,120 +271,14 @@
270
271
  background: var(--fill-muted);
271
272
  color: var(--foreground-disabled);
272
273
  }
273
- /* On a phone the field is a trigger, not a text input: a select-like button
274
- that shows the value. Its hit area covers the whole field; the clear button
275
- sits above it. */
276
- .r-combobox-select__trigger {
277
- box-sizing: border-box;
278
- min-width: 0;
279
- min-height: inherit;
280
- flex: 1;
281
- display: flex;
282
- align-items: center;
283
- padding: 0;
284
- border: 0;
285
- outline: 0;
286
- background: transparent;
287
- color: inherit;
288
- font: inherit;
289
- text-align: start;
290
- cursor: default;
291
- -webkit-tap-highlight-color: transparent;
292
- }
293
- .r-combobox-select__trigger::after {
294
- content: "";
295
- position: absolute;
296
- inset: 0;
297
- border-radius: inherit;
298
- }
299
- .r-combobox-select__trigger:disabled {
300
- color: inherit;
301
- }
302
- .r-combobox-select__value {
303
- min-width: 0;
304
- overflow: hidden;
305
- text-overflow: ellipsis;
306
- white-space: nowrap;
307
- }
308
- .r-combobox-select__placeholder {
309
- min-width: 0;
310
- overflow: hidden;
311
- text-overflow: ellipsis;
312
- white-space: nowrap;
313
- color: var(--foreground-hint);
314
- }
315
- .r-combobox-select__trigger .r-combobox-select__chips {
316
- margin-inline-start: -6px;
317
- }
318
- .r-combobox-select__trigger .r-combobox-select__chip {
319
- padding-inline-end: 8px;
320
- }
321
- .r-combobox-select__clear {
322
- position: relative;
323
- z-index: 1;
324
- }
325
- .r-combobox-select__arrow {
326
- pointer-events: none;
327
- }
328
- .r-combobox-select__control--trigger[data-popup-open] .r-combobox-select__arrow > svg {
329
- transform: rotate(180deg);
330
- }
331
- /* The phone's anchored list fits the room on its side instead of flipping. */
274
+ /* On a phone the list keeps the side it opened on and fits the room there
275
+ instead of flipping (combobox-select.tsx), and the input stays at 16px or
276
+ more at every size: iOS zooms into a smaller one as it takes focus. */
332
277
  .r-combobox-select__popup--anchored .r-combobox-select__list {
333
- box-sizing: border-box;
334
- max-height: min(calc(16rem + 12px), var(--available-height, 100vh));
335
- }
336
- /* The phone's bottom sheet: the field's label as its title, the search input
337
- at its top, then the whole list, scrolling in the rest of the sheet. */
338
- .r-combobox-select__sheet-popup {
339
- height: 82dvh;
340
- }
341
- .r-combobox-select__sheet {
342
- display: flex;
343
- flex: 1;
344
- flex-direction: column;
345
- min-height: 0;
346
- }
347
- .r-combobox-select__sheet-header {
348
- flex-direction: row;
349
- align-items: center;
350
- justify-content: space-between;
351
- gap: 8px;
352
- padding-inline-end: 8px;
353
- }
354
- .r-combobox-select__sheet-title {
355
- min-width: 0;
356
- flex: 1;
357
- }
358
- .r-combobox-select__sheet-search {
359
- flex: 0 0 auto;
360
- padding: 4px 16px 8px;
361
- }
362
- .r-combobox-select__search-icon {
363
- width: 16px;
364
- height: 16px;
365
- flex: 0 0 auto;
366
- color: var(--foreground-hint);
367
- }
368
- .r-combobox-select__sheet-body {
369
- min-height: 0;
370
- overflow-y: auto;
371
- overscroll-behavior: contain;
372
- padding: 0 8px calc(16px + env(safe-area-inset-bottom, 0px));
373
- }
374
- .r-combobox-select__sheet .r-combobox-select__list {
375
- max-height: none;
376
- overflow: visible;
377
- padding: 0;
378
- }
379
- .r-combobox-select__sheet .r-combobox-select__option {
380
- min-height: 52px;
381
- padding: 0 12px;
382
- font-size: var(--text-body);
383
- line-height: var(--text-body--line-height);
278
+ max-height: min(var(--combobox-select-list-max-height, 16rem), var(--available-height, 100vh));
384
279
  }
385
- .r-combobox-select__sheet .r-combobox-select__group-label {
386
- padding: 12px 12px 4px;
280
+ .r-combobox-select__control--phone .r-combobox-select__input {
281
+ font-size: max(1em, 16px);
387
282
  }
388
283
  @keyframes r-combobox-select-spin {
389
284
  to {
@@ -0,0 +1,64 @@
1
+ /*
2
+ * VirtualList. The list is its own native scroll container (vertical overflow scrolls; `overflow-anchor: none`,
3
+ * because the list compensates size changes above the view itself); its native scrollbar is hidden unless
4
+ * `showScrollbar`. Plain CSS: every selector is written out.
5
+ *
6
+ * Classes: `.r-virtual-list` (the scroll container, `data-slot="virtual-list"`) with the modifiers
7
+ * `--x-scrollable` (with `columns`), `--show-scrollbar`, `--printable`, `--empty-centered` and
8
+ * `--ios-compensation-enabled`; `.r-virtual-list__empty` (`data-slot="virtual-list-empty"`, with `--center`).
9
+ * The spacer (`data-slot="virtual-list-items"`) and the rows' element (`data-slot="virtual-list-visible-items"`)
10
+ * take their few styles inline, from VirtualList.tsx.
11
+ *
12
+ * In the `components` layer, so a utility in the consumer's `className` (`h-*`, `max-h-*`, `overflow-*`)
13
+ * overrides these rules.
14
+ *
15
+ * CSS variables the list writes as inline styles, for sticky children to read:
16
+ * --virtual-list-transform-y on the rows' element: its translateY (the offset of the first
17
+ * mounted row, less its top margin), "0px" with virtualization off
18
+ * --virtual-list-ios-compensation-y on the rows' element: the iOS momentum-scroll compensation
19
+ * applied to the spacer as translateY(-value)
20
+ * --virtual-list-width on `.r-virtual-list`: the list's offsetWidth
21
+ */
22
+ @layer components {
23
+ .r-virtual-list {
24
+ max-height: inherit;
25
+ overflow-anchor: none;
26
+ outline: none;
27
+ min-width: 1px;
28
+ height: 100%;
29
+ overflow-x: hidden;
30
+ overflow-y: auto;
31
+ }
32
+ .r-virtual-list.r-virtual-list--ios-compensation-enabled {
33
+ overscroll-behavior: none;
34
+ }
35
+ .r-virtual-list.r-virtual-list--x-scrollable {
36
+ overflow-x: auto;
37
+ }
38
+ .r-virtual-list:not(.r-virtual-list--show-scrollbar) {
39
+ scrollbar-width: none;
40
+ }
41
+ .r-virtual-list:not(.r-virtual-list--show-scrollbar)::-webkit-scrollbar {
42
+ width: 0;
43
+ height: 0;
44
+ display: none;
45
+ }
46
+ .r-virtual-list.r-virtual-list--empty-centered {
47
+ flex-direction: column;
48
+ display: flex;
49
+ }
50
+ .r-virtual-list__empty.r-virtual-list__empty--center {
51
+ flex: 1;
52
+ justify-content: center;
53
+ align-items: center;
54
+ min-height: 0;
55
+ display: flex;
56
+ }
57
+ @media print {
58
+ .r-virtual-list.r-virtual-list--printable {
59
+ max-height: none !important;
60
+ height: auto !important;
61
+ overflow: visible !important;
62
+ }
63
+ }
64
+ }