@botiverse/raft-ui 0.11.0 → 0.13.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,39 @@
1
+ ## [0.13.0](https://github.com/botiverse/raft-design/compare/v0.12.0...v0.13.0) (2026-10-21)
2
+
3
+ ### Added
4
+
5
+ - Tokens `fill-row-hover` (4% ink light, 3% dark), `fill-message-hover` (3% / 2.2%) and `fill-row-open` (5% / 4%), with utilities `row-hover-overlay` and `row-open-overlay`. ([#641](https://github.com/botiverse/raft-design/pull/641), [#643](https://github.com/botiverse/raft-design/pull/643))
6
+
7
+ ### Changed
8
+
9
+ - Rows hover with their own light step instead of the press overlay (`fill-pressed`, 7.8%): messages with `fill-message-hover`; sidebar items, list, inbox, search, table and file rows with `fill-row-hover`. Hover stays lighter than selection; press is unchanged. ([#641](https://github.com/botiverse/raft-design/pull/641))
10
+ - A row with its menu open (right-click, ⋯ menu, phone long-press) takes `fill-row-open`, the one marker of which row the menu belongs to; selection still wins. Comment cards hover with `fill-row-hover`. ([#643](https://github.com/botiverse/raft-design/pull/643))
11
+ - Select and Combobox default `collisionPadding` to 8px. ([#642](https://github.com/botiverse/raft-design/pull/642))
12
+
13
+ ### Fixed
14
+
15
+ - Long values stay inside form fields on narrow screens: Field labels, descriptions and errors wrap; a FieldItem label next to a checkbox, radio or switch shrinks; an InputGroup text prefix takes at most half the field and truncates; SelectValue, ComboboxSelect values and chips truncate with the full value as `title`; options wrap to 2 lines then clamp; Select and Combobox popups never get wider than the screen less 8px each side. ([#642](https://github.com/botiverse/raft-design/pull/642))
16
+
17
+ ## [0.12.0](https://github.com/botiverse/raft-design/compare/v0.11.0...v0.12.0) (2026-10-21)
18
+
19
+ ### Breaking
20
+
21
+ - `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))
22
+
23
+ ### Added
24
+
25
+ - `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))
26
+ - 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))
27
+ - 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))
28
+
29
+ ### Fixed
30
+
31
+ - 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))
32
+ - Toast title and description use `text-callout` (desktop line height 20 to 22px). ([#637](https://github.com/botiverse/raft-design/pull/637))
33
+ - 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))
34
+ - `MessageItemSenderGroup`: the gap before a role squeezed to nothing collapses with it. ([#633](https://github.com/botiverse/raft-design/pull/633))
35
+ - `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))
36
+
1
37
  ## [0.11.0](https://github.com/botiverse/raft-design/compare/v0.10.7...v0.11.0) (2026-10-21)
2
38
 
3
39
  ### Added
@@ -77,6 +77,15 @@
77
77
  text-overflow: ellipsis;
78
78
  white-space: nowrap;
79
79
  }
80
+ /* An option wraps onto a second line before it is cut off, so two long values
81
+ that share a beginning can still be told apart (forms.md#long-values-in-fields). */
82
+ .r-combobox-select__option .r-combobox-select__text {
83
+ display: -webkit-box;
84
+ -webkit-box-orient: vertical;
85
+ -webkit-line-clamp: 2;
86
+ white-space: normal;
87
+ overflow-wrap: anywhere;
88
+ }
80
89
  .r-combobox-select__actions {
81
90
  display: inline-flex;
82
91
  align-items: center;
@@ -140,7 +149,7 @@
140
149
  width: var(--anchor-width, max-content);
141
150
  min-width: 13.75rem;
142
151
  max-width: var(--available-width);
143
- max-height: min(var(--available-height), 24rem);
152
+ max-height: min(var(--available-height), max(24rem, var(--combobox-select-list-max-height, 0px)));
144
153
  overflow: hidden;
145
154
  border: 0;
146
155
  border-radius: 10px;
@@ -152,7 +161,8 @@
152
161
  outline: 0;
153
162
  }
154
163
  .r-combobox-select__list {
155
- max-height: 16rem;
164
+ box-sizing: border-box;
165
+ max-height: var(--combobox-select-list-max-height, 16rem);
156
166
  overflow-y: auto;
157
167
  overscroll-behavior: contain;
158
168
  scroll-padding-block: 6px;
@@ -162,7 +172,7 @@
162
172
  box-sizing: border-box;
163
173
  width: 100%;
164
174
  min-height: 36px;
165
- padding: 0 10px;
175
+ padding: 6px 10px;
166
176
  display: flex;
167
177
  align-items: center;
168
178
  justify-content: space-between;
@@ -270,120 +280,14 @@
270
280
  background: var(--fill-muted);
271
281
  color: var(--foreground-disabled);
272
282
  }
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. */
283
+ /* On a phone the list keeps the side it opened on and fits the room there
284
+ instead of flipping (combobox-select.tsx), and the input stays at 16px or
285
+ more at every size: iOS zooms into a smaller one as it takes focus. */
332
286
  .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);
287
+ max-height: min(var(--combobox-select-list-max-height, 16rem), var(--available-height, 100vh));
384
288
  }
385
- .r-combobox-select__sheet .r-combobox-select__group-label {
386
- padding: 12px 12px 4px;
289
+ .r-combobox-select__control--phone .r-combobox-select__input {
290
+ font-size: max(1em, 16px);
387
291
  }
388
292
  @keyframes r-combobox-select-spin {
389
293
  to {
@@ -11,7 +11,10 @@
11
11
  hairline < seam < strong for line
12
12
  layer = places on the elevation ladder; fill = neutral interaction fills
13
13
  (resting/hover/active/disabled surfaces): fill-muted and fill-strong are
14
- opaque, the -pressed overlays are translucent ink laid over a surface.
14
+ opaque, the -pressed and -hover overlays are translucent ink laid over a
15
+ surface (a row hovers with fill-row-hover or fill-message-hover, and a
16
+ row with its menu open takes fill-row-open, all lighter than any
17
+ selection tint; press keeps fill-pressed).
15
18
  Families: {family}(-{slot})
16
19
  family = brand | attention | info | success | warning | danger | inactive
17
20
  slot = -strong (deep shade: readable text, rings) > bare (solid fill)
@@ -21,8 +24,8 @@
21
24
  an opted-in family always gets both)
22
25
  Washes: ink-{alpha%} (2..40) — neutral overlays, hairlines, hover fills.
23
26
  Opacity rule: layer tokens are opaque in every theme, except the two
24
- backdrops (overlays by contract); among fills only the -pressed overlays are
25
- translucent.
27
+ backdrops (overlays by contract); among fills only the -pressed and -hover
28
+ overlays are translucent.
26
29
  Interaction fills: transparent resting → ink-N directly; solid family fill →
27
30
  the family's -hover/-active pair; neutral or tinted surface → step up its ladder.
28
31
  Escape hatches: ink ramp for one-off washes; inline oklch() literals for
@@ -168,6 +171,19 @@
168
171
  --fill-strong: oklch(0.936 0.0006 17.62);
169
172
  --fill-frame-pressed: oklch(0.1813 0.005 17.62 / 0.122);
170
173
  --fill-pressed: oklch(0.1813 0.005 17.62 / 0.078);
174
+ /* Hover on a whole row (sidebar, list, inbox, search result, table, file row):
175
+ one perceptible step (OKLab dE about 2.8 in both modes), below every
176
+ selection tint, so text keeps its contrast. */
177
+ --fill-row-hover: oklch(0.1813 0.005 17.62 / 0.04);
178
+ /* Hover on a message: the lightest perceptible step (OKLab dE about 2.1 in
179
+ both modes), because a message is a large block someone reads with the
180
+ pointer resting on it. */
181
+ --fill-message-hover: oklch(0.1813 0.005 17.62 / 0.03);
182
+ /* Any row with its menu open (right-click, its menu button, press and hold):
183
+ one step over a hover (OKLab dE 3.4 to 4.3 on every row surface), because on
184
+ a phone, which has no hover, it is the only sign of which row the menu acts
185
+ on. Still under info-soft and brand-soft on every surface. */
186
+ --fill-row-open: oklch(0.1813 0.005 17.62 / 0.05);
171
187
  --line-strong: oklch(0.1813 0.005 17.62);
172
188
  --line-seam: oklch(0.1813 0.005 17.62 / 0.451);
173
189
  --line-hairline: oklch(0.1813 0.005 17.62 / 0.149);
@@ -326,6 +342,9 @@
326
342
  --fill-strong: oklch(0.3474 0.0051 106.66);
327
343
  --fill-frame-pressed: oklch(0.9843 0.004 106.47 / 0.078);
328
344
  --fill-pressed: oklch(0.9843 0.004 106.47 / 0.078);
345
+ --fill-row-hover: oklch(0.9843 0.004 106.47 / 0.03);
346
+ --fill-message-hover: oklch(0.9843 0.004 106.47 / 0.022);
347
+ --fill-row-open: oklch(0.9843 0.004 106.47 / 0.04);
329
348
  --line-strong: oklch(0.9211 0.004 106.48);
330
349
  --line-seam: oklch(0.9843 0.004 106.47 / 0.259);
331
350
  --line-hairline: oklch(0.9843 0.004 106.47 / 0.102);
@@ -407,6 +426,9 @@
407
426
  --fill-strong: oklch(0.3474 0.0051 106.66);
408
427
  --fill-frame-pressed: oklch(0.9843 0.004 106.47 / 0.078);
409
428
  --fill-pressed: oklch(0.9843 0.004 106.47 / 0.078);
429
+ --fill-row-hover: oklch(0.9843 0.004 106.47 / 0.03);
430
+ --fill-message-hover: oklch(0.9843 0.004 106.47 / 0.022);
431
+ --fill-row-open: oklch(0.9843 0.004 106.47 / 0.04);
410
432
  --line-strong: oklch(0.9211 0.004 106.48);
411
433
  --line-seam: oklch(0.9843 0.004 106.47 / 0.259);
412
434
  --line-hairline: oklch(0.9843 0.004 106.47 / 0.102);