@botiverse/raft-ui 0.12.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,19 @@
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
+
1
17
  ## [0.12.0](https://github.com/botiverse/raft-design/compare/v0.11.0...v0.12.0) (2026-10-21)
2
18
 
3
19
  ### Breaking
@@ -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;
@@ -163,7 +172,7 @@
163
172
  box-sizing: border-box;
164
173
  width: 100%;
165
174
  min-height: 36px;
166
- padding: 0 10px;
175
+ padding: 6px 10px;
167
176
  display: flex;
168
177
  align-items: center;
169
178
  justify-content: space-between;
@@ -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);
package/dist/index.d.mts CHANGED
@@ -1254,7 +1254,7 @@ export declare function InputGroup({ className, ...props }: InputGroupProps): im
1254
1254
  type InputGroupAddonProps = ComponentPropsWithRef<"div"> & Pick<VariantProps<typeof inputGroup>, "align" | "variant">;
1255
1255
  declare function InputGroupAddonRoot({ align, variant, className, ...props }: InputGroupAddonProps): import("react").JSX.Element;
1256
1256
  type InputGroupAddonTextProps = ComponentPropsWithRef<"span"> & Pick<VariantProps<typeof inputGroup>, "align" | "variant">;
1257
- declare function TextAddon({ align, variant, className, ...props }: InputGroupAddonTextProps): import("react").JSX.Element;
1257
+ declare function TextAddon({ align, variant, className, ref, title, ...props }: InputGroupAddonTextProps): import("react").JSX.Element;
1258
1258
  export declare const InputGroupAddon: typeof InputGroupAddonRoot & {
1259
1259
  Text: typeof TextAddon;
1260
1260
  };
@@ -1315,7 +1315,7 @@ export declare function ComboboxCollection(props: ComboboxCollectionProps): impo
1315
1315
  type ComboboxChipsProps = StyledProps<Combobox$1.Chips.Props>;
1316
1316
  export declare function ComboboxChips({ className, ...props }: ComboboxChipsProps): import("react").JSX.Element;
1317
1317
  type ComboboxChipProps = StyledProps<Combobox$1.Chip.Props>;
1318
- export declare function ComboboxChip({ className, ...props }: ComboboxChipProps): import("react").JSX.Element;
1318
+ export declare function ComboboxChip({ className, ref, title, ...props }: ComboboxChipProps): import("react").JSX.Element;
1319
1319
  type ComboboxChipRemoveProps = StyledProps<Combobox$1.ChipRemove.Props>;
1320
1320
  export declare function ComboboxChipRemove({ className, children, ...props }: ComboboxChipRemoveProps): import("react").JSX.Element;
1321
1321
  //#endregion
@@ -1337,7 +1337,7 @@ export declare function Select<Value, Multiple extends boolean | undefined = fal
1337
1337
  type SelectTriggerProps = StyledProps<Select$1.Trigger.Props> & DataAttributes$1;
1338
1338
  export declare function SelectTrigger({ className, children, render, "data-invalid": dataInvalid, ...props }: SelectTriggerProps): import("react").JSX.Element;
1339
1339
  type SelectValueProps = StyledProps<Select$1.Value.Props>;
1340
- export declare function SelectValue({ className, ...props }: SelectValueProps): import("react").JSX.Element;
1340
+ export declare function SelectValue({ className, ref, title, ...props }: SelectValueProps): import("react").JSX.Element;
1341
1341
  type SelectIconProps = StyledProps<Select$1.Icon.Props>;
1342
1342
  export declare function SelectIcon({ className, children, ...props }: SelectIconProps): import("react").JSX.Element;
1343
1343
  type SelectPortalProps = Select$1.Portal.Props;
@@ -1357,7 +1357,7 @@ export declare function SelectItemLeading({ className, ...props }: SelectItemLea
1357
1357
  type SelectItemIndicatorProps = StyledProps<Select$1.ItemIndicator.Props>;
1358
1358
  export declare function SelectItemIndicator({ className, children, ...props }: SelectItemIndicatorProps): import("react").JSX.Element;
1359
1359
  type SelectItemTextProps = StyledProps<Select$1.ItemText.Props>;
1360
- export declare function SelectItemText({ className, id, ...props }: SelectItemTextProps): import("react").JSX.Element;
1360
+ export declare function SelectItemText({ className, id, ref, title, ...props }: SelectItemTextProps): import("react").JSX.Element;
1361
1361
  type SelectItemDescriptionProps = StyledProps<ComponentPropsWithRef<"span">>;
1362
1362
  /**
1363
1363
  * A second line under an option's label: what it means, not its name again.
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { cn } from "./cn.mjs";
2
- import { $ as MessageReactionTooltipNameText, $t as DropdownMenuShortcut, A as MessageTextSelectionToolbarButton, An as DialogClose, At as MessageItem, B as MessageReferenceUnavailable, Bn as DialogTrigger, Bt as DropdownMenuCheckboxItemIndicator, C as MessageQuotedPreviewUnavailable, Cn as TooltipContent, Ct as MessageItemEdited, D as MessageEmbedHeader, Dn as Badge, Dt as MessageItemAvatarSlot, E as MessageEmbedFooter, En as TooltipTrigger, Et as MessageItemSearchMatch, F as MessageReferenceChip, Fn as DialogNav, Ft as AvatarGroup, G as MessageReactionGlyph, Gn as useParentOverlayKind, Gt as DropdownMenuItemLabel, H as MessageReactionChip, Hn as buttonVariants, Ht as DropdownMenuFooter, I as MessageReferenceIndicator, In as DialogOverlay, It as AvatarGroupCount, J as MessageReactionQuickButton, Jn as useThemeScopeProps, Jt as DropdownMenuPortal, K as MessageReactionPickerContent, Kn as withOverlayLayer, Kt as DropdownMenuLabel, L as MessageReferenceLabel, Ln as DialogPortal, Lt as AvatarImage, M as MessageMultiSelect, Mn as DialogDescription, Mt as Avatar, N as MessageMultiSelectCheckbox, Nn as DialogFooter, Nt as AvatarBadge, O as messageEmbed, On as Dialog, Ot as MessageItemContinuationTime, P as MessageMultiSelectToolbar, Pn as DialogHeader, Pt as AvatarFallback, Q as MessageReactionTooltipName, Qt as DropdownMenuSeparator, R as MessageReferencePending, Rn as DialogSurface, Rt as DropdownMenu, S as MessageQuotedPreviewTimestamp, Sn as Tooltip, St as MessageItemContent, T as MessageEmbedContent, Tn as TooltipProvider, Tt as MessageItemFooter, U as MessageReactionCount, Un as Spinner, Ut as DropdownMenuItem, V as MessageReactionAddButton, Vn as Button, Vt as DropdownMenuContent, W as MessageReactionErrorIndicator, Wn as defaultNativeButton, Wt as DropdownMenuItemCount, X as MessageReactionTooltipContent, Xn as ThemeStateContext, Xt as DropdownMenuRadioItem, Y as MessageReactionQuickRow, Yn as useTheme, Yt as DropdownMenuRadioGroup, Z as MessageReactionTooltipMeta, Zn as tv, Zt as DropdownMenuRadioItemIndicator, _ as MessageQuotedPreviewContent, _n as ScrollAreaViewport, _t as MessageItemSenderButton, a as MessageListDateDivider, an as Panel, at as MessageItemSavedIndicator, b as MessageQuotedPreviewText, bn as CheckboxIndicator, bt as MessageItemAttachments, c as MessageList, cn as PanelHeaderRoot, d as MessageQuotedPreviewAttachments, dn as PanelSection, en as DropdownMenuSubmenu, et as MessageReactionTooltipNames, f as MessageQuotedPreviewAuthor, fn as ScrollArea, ft as MessageItemHeader, g as MessageQuotedPreviewChannel, gn as ScrollAreaThumb, gt as MessageItemSenderBadges, h as MessageQuotedPreviewAuthorName, hn as ScrollAreaScrollbar, ht as MessageItemSender, in as KbdGroup, it as MessageItemReadReceipt, j as MessageTextSelectionToolbarSeparator, jn as DialogContent, jt as searchHit, k as MessageTextSelectionToolbar, kn as DialogBody, kt as MessageItemGutter, l as MessageQuotedPreview, ln as PanelScrollContent, m as MessageQuotedPreviewAuthorMeta, mn as ScrollAreaCorner, mt as MessageItemMeta, nn as DropdownMenuTrigger, nt as MessageItemBadge, o as MessageListHistoryLimited, on as PanelBody, ot as MessageItemToolbar, pn as ScrollAreaContent, pt as MessageItemInlineStatus, q as MessageReactionPickerStatic, qn as resolveThemeScopeProps, qt as DropdownMenuPopup, rn as Kbd, rt as MessageItemBadgeSeparator, s as MessageListNotice, sn as PanelFooter, st as MessageItemToolbarButton, tn as DropdownMenuSubmenuTrigger, tt as MessageReactionTooltipSeparator, u as MessageQuotedPreviewAttachment, un as PanelScrollViewport, v as MessageQuotedPreviewHeader, vn as useMobileViewport, vt as MessageItemSenderGroup, w as MessageEmbed, wn as TooltipPortal, wt as MessageItemEmbedded, x as MessageQuotedPreviewThread, xn as PRESENCE_COLOR, xt as MessageItemBody, y as MessageQuotedPreviewLoading, yn as Checkbox, yt as MessageItemTime, z as MessageReferenceText, zn as DialogTitle, zt as DropdownMenuCheckboxItem } from "./message-list-CxawdwMF.mjs";
2
+ import { $ as MessageReactionTooltipNameText, $t as DropdownMenuSeparator, A as MessageTextSelectionToolbarButton, An as DialogBody, At as MessageItem, B as MessageReferenceUnavailable, Bn as DialogTitle, Bt as DropdownMenuCheckboxItem, C as MessageQuotedPreviewUnavailable, Cn as Tooltip, Ct as MessageItemEdited, D as MessageEmbedHeader, Dn as TooltipTrigger, Dt as MessageItemAvatarSlot, E as MessageEmbedFooter, En as TooltipProvider, Et as MessageItemSearchMatch, F as MessageReferenceChip, Fn as DialogHeader, Ft as AvatarGroup, G as MessageReactionGlyph, Gn as defaultNativeButton, Gt as DropdownMenuItemCount, H as MessageReactionChip, Hn as Button, Ht as DropdownMenuContent, I as MessageReferenceIndicator, In as DialogNav, It as AvatarGroupCount, J as MessageReactionQuickButton, Jn as resolveThemeScopeProps, Jt as DropdownMenuPopup, K as MessageReactionPickerContent, Kn as useParentOverlayKind, Kt as DropdownMenuItemLabel, L as MessageReferenceLabel, Ln as DialogOverlay, Lt as AvatarImage, M as MessageMultiSelect, Mn as DialogContent, Mt as Avatar, N as MessageMultiSelectCheckbox, Nn as DialogDescription, Nt as AvatarBadge, O as messageEmbed, On as Badge, Ot as MessageItemContinuationTime, P as MessageMultiSelectToolbar, Pn as DialogFooter, Pt as AvatarFallback, Q as MessageReactionTooltipName, Qn as tv, Qt as DropdownMenuRadioItemIndicator, R as MessageReferencePending, Rn as DialogPortal, Rt as useOverflowTitle, S as MessageQuotedPreviewTimestamp, Sn as PRESENCE_COLOR, St as MessageItemContent, T as MessageEmbedContent, Tn as TooltipPortal, Tt as MessageItemFooter, U as MessageReactionCount, Un as buttonVariants, Ut as DropdownMenuFooter, V as MessageReactionAddButton, Vn as DialogTrigger, Vt as DropdownMenuCheckboxItemIndicator, W as MessageReactionErrorIndicator, Wn as Spinner, Wt as DropdownMenuItem, X as MessageReactionTooltipContent, Xn as useTheme, Xt as DropdownMenuRadioGroup, Y as MessageReactionQuickRow, Yn as useThemeScopeProps, Yt as DropdownMenuPortal, Z as MessageReactionTooltipMeta, Zn as ThemeStateContext, Zt as DropdownMenuRadioItem, _ as MessageQuotedPreviewContent, _n as ScrollAreaThumb, _t as MessageItemSenderButton, a as MessageListDateDivider, an as KbdGroup, at as MessageItemSavedIndicator, b as MessageQuotedPreviewText, bn as Checkbox, bt as MessageItemAttachments, c as MessageList, cn as PanelFooter, d as MessageQuotedPreviewAttachments, dn as PanelScrollViewport, en as DropdownMenuShortcut, et as MessageReactionTooltipNames, f as MessageQuotedPreviewAuthor, fn as PanelSection, ft as MessageItemHeader, g as MessageQuotedPreviewChannel, gn as ScrollAreaScrollbar, gt as MessageItemSenderBadges, h as MessageQuotedPreviewAuthorName, hn as ScrollAreaCorner, ht as MessageItemSender, in as Kbd, it as MessageItemReadReceipt, j as MessageTextSelectionToolbarSeparator, jn as DialogClose, jt as searchHit, k as MessageTextSelectionToolbar, kn as Dialog, kt as MessageItemGutter, l as MessageQuotedPreview, ln as PanelHeaderRoot, m as MessageQuotedPreviewAuthorMeta, mn as ScrollAreaContent, mt as MessageItemMeta, nn as DropdownMenuSubmenuTrigger, nt as MessageItemBadge, o as MessageListHistoryLimited, on as Panel, ot as MessageItemToolbar, pn as ScrollArea, pt as MessageItemInlineStatus, q as MessageReactionPickerStatic, qn as withOverlayLayer, qt as DropdownMenuLabel, rn as DropdownMenuTrigger, rt as MessageItemBadgeSeparator, s as MessageListNotice, sn as PanelBody, st as MessageItemToolbarButton, tn as DropdownMenuSubmenu, tt as MessageReactionTooltipSeparator, u as MessageQuotedPreviewAttachment, un as PanelScrollContent, v as MessageQuotedPreviewHeader, vn as ScrollAreaViewport, vt as MessageItemSenderGroup, w as MessageEmbed, wn as TooltipContent, wt as MessageItemEmbedded, x as MessageQuotedPreviewThread, xn as CheckboxIndicator, xt as MessageItemBody, y as MessageQuotedPreviewLoading, yn as useMobileViewport, yt as MessageItemTime, z as MessageReferenceText, zn as DialogSurface, zt as DropdownMenu } from "./message-list-DP03T8gF.mjs";
3
3
  import { Dialog as Dialog$1 } from "@base-ui/react/dialog";
4
4
  import { AlertTriangle, Bell, Check, CheckCircle2, ChevronDown, ChevronLeft, ChevronRight, Copy, FileText, Image, Info, Upload, X, Zap } from "lucide-react";
5
5
  import { Children, cloneElement, createContext, createElement, isValidElement, use, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
@@ -1056,9 +1056,9 @@ const listRow = tv({
1056
1056
  },
1057
1057
  interactive: {
1058
1058
  true: { root: [
1059
- "not-disabled:not-aria-disabled:not-data-selected:hover:press-overlay",
1059
+ "not-disabled:not-aria-disabled:not-data-selected:hover:row-hover-overlay",
1060
1060
  "not-disabled:not-aria-disabled:not-data-selected:active:press-overlay",
1061
- "not-data-selected:data-popup-open:press-overlay"
1061
+ "not-data-selected:data-popup-open:row-open-overlay not-disabled:not-aria-disabled:not-data-selected:data-popup-open:hover:row-open-overlay"
1062
1062
  ] },
1063
1063
  false: {}
1064
1064
  },
@@ -1972,7 +1972,7 @@ const sidebarItemRecipe = tv({
1972
1972
  },
1973
1973
  variants: {
1974
1974
  interactive: {
1975
- true: { sidebarItem: ["hover:bg-fill-pressed active:bg-fill-pressed not-data-active:data-popup-open:bg-fill-pressed", "focus-visible:shadow-focus"] },
1975
+ true: { sidebarItem: ["hover:bg-fill-row-hover active:bg-fill-pressed not-data-active:data-popup-open:bg-fill-row-open", "focus-visible:shadow-focus"] },
1976
1976
  false: { sidebarItem: "cursor-default" }
1977
1977
  },
1978
1978
  wrap: {
@@ -3686,17 +3686,26 @@ const field = tv({
3686
3686
  root: ["group/field flex flex-col gap-1.5"],
3687
3687
  item: [
3688
3688
  "group/field-item flex items-start gap-2",
3689
+ "*:min-w-0",
3689
3690
  "*:data-[slot=checkbox]:mt-[calc((1lh-1.25rem)/2)]",
3690
3691
  "*:data-[slot=radio-group-item]:mt-[calc((1lh-1.25rem)/2)]",
3691
3692
  "*:data-[slot=switch]:mt-[calc((1lh-1.875rem)/2)]"
3692
3693
  ],
3693
3694
  label: [
3694
- "block",
3695
+ "block wrap-anywhere",
3695
3696
  "group-data-disabled/field:text-foreground-disabled",
3696
3697
  "font-sans font-semibold text-foreground-muted"
3697
3698
  ],
3698
- description: ["group-data-disabled/field:text-foreground-disabled", "text-caption text-foreground-hint"],
3699
- error: ["group-data-disabled/field:text-foreground-disabled", "text-caption font-semibold text-danger-strong"]
3699
+ description: [
3700
+ "wrap-anywhere",
3701
+ "group-data-disabled/field:text-foreground-disabled",
3702
+ "text-caption text-foreground-hint"
3703
+ ],
3704
+ error: [
3705
+ "wrap-anywhere",
3706
+ "group-data-disabled/field:text-foreground-disabled",
3707
+ "text-caption font-semibold text-danger-strong"
3708
+ ]
3700
3709
  },
3701
3710
  variants: { size: {
3702
3711
  sm: {
@@ -3786,8 +3795,8 @@ const inputGroup = tv({
3786
3795
  "[&>svg:not([class*='size-'])]:size-4.5"
3787
3796
  ],
3788
3797
  text: [
3789
- "flex shrink-0 items-center px-3",
3790
- "select-none whitespace-nowrap",
3798
+ "block min-w-0 max-w-1/2 shrink-0 content-center truncate px-3",
3799
+ "select-none",
3791
3800
  "font-mono text-mono-code",
3792
3801
  "text-(--ig-text-fg,var(--ig-text-fg-default,var(--foreground-hint)))"
3793
3802
  ],
@@ -3895,12 +3904,15 @@ function InputGroupAddonRoot({ align = "inline-start", variant = "default", clas
3895
3904
  ...props
3896
3905
  });
3897
3906
  }
3898
- function TextAddon({ align = "inline-start", variant = "default", className, ...props }) {
3907
+ function TextAddon({ align = "inline-start", variant = "default", className, ref, title, ...props }) {
3899
3908
  const { text } = inputGroup({
3900
3909
  align,
3901
3910
  variant
3902
3911
  });
3912
+ const overflowRef = useOverflowTitle(ref, title);
3903
3913
  return /* @__PURE__ */ jsx("span", {
3914
+ ref: overflowRef,
3915
+ title,
3904
3916
  "data-slot": "input-group-text",
3905
3917
  "data-align": align,
3906
3918
  "data-variant": variant,
@@ -3977,6 +3989,7 @@ const combobox = tv({
3977
3989
  positioner: ["isolate z-50 outline-none"],
3978
3990
  content: [
3979
3991
  "h-auto max-h-(--available-height) min-w-[220px] overflow-hidden",
3992
+ "max-w-[min(var(--available-width),max(var(--anchor-width),24rem))]",
3980
3993
  "outline-none",
3981
3994
  "rounded-container bg-layer-popover text-foreground",
3982
3995
  "shadow-float ring-1 ring-line-seam"
@@ -3987,8 +4000,8 @@ const combobox = tv({
3987
4000
  item: [
3988
4001
  "flex w-full shrink-0 cursor-default select-none items-center justify-between overflow-hidden",
3989
4002
  "text-left outline-none transition-colors",
3990
- "min-h-9 gap-2.5 rounded-control px-2.5 py-0",
3991
- "font-sans text-callout font-medium text-foreground",
4003
+ "min-h-9 gap-2.5 rounded-control px-2.5 py-1.5",
4004
+ "font-sans text-callout font-medium text-foreground wrap-anywhere",
3992
4005
  "bg-transparent hover:bg-brand-soft data-highlighted:bg-brand-soft",
3993
4006
  "data-selected:font-bold",
3994
4007
  "data-disabled:pointer-events-none data-disabled:text-foreground-disabled",
@@ -4016,12 +4029,13 @@ const combobox = tv({
4016
4029
  "transition-shadow duration-90 ease-out has-focus-visible:shadow-focus"
4017
4030
  ],
4018
4031
  chip: [
4019
- "inline-flex items-center",
4032
+ "inline-flex min-w-0 max-w-full items-center overflow-hidden",
4033
+ "[&>:not([data-slot=combobox-chip-remove])]:min-w-0 [&>:not([data-slot=combobox-chip-remove])]:truncate",
4020
4034
  "h-7 gap-1.5 rounded-chip bg-fill-muted pr-0.5 pl-2",
4021
4035
  "text-footnote font-semibold text-foreground"
4022
4036
  ],
4023
4037
  chipRemove: [
4024
- "inline-flex items-center justify-center outline-none transition-colors",
4038
+ "inline-flex shrink-0 items-center justify-center outline-none transition-colors",
4025
4039
  "size-[22px] rounded-sticker text-foreground-hint",
4026
4040
  "hover:bg-fill-pressed active:bg-fill-pressed focus-visible:shadow-focus",
4027
4041
  "[&>svg]:size-3.5"
@@ -4202,7 +4216,7 @@ function ComboboxSeparator({ className, ...props }) {
4202
4216
  ...props
4203
4217
  });
4204
4218
  }
4205
- function ComboboxContent({ align = "start", alignOffset = 0, anchor, arrowPadding, collisionAvoidance, collisionBoundary, collisionPadding, disableAnchorTracking = true, positionMethod = "fixed", side = "bottom", sideOffset, sticky, portalProps, className, initialFocus = false, finalFocus = false, ...props }) {
4219
+ function ComboboxContent({ align = "start", alignOffset = 0, anchor, arrowPadding, collisionAvoidance, collisionBoundary, collisionPadding = 8, disableAnchorTracking = true, positionMethod = "fixed", side = "bottom", sideOffset, sticky, portalProps, className, initialFocus = false, finalFocus = false, ...props }) {
4206
4220
  const { positioner, content } = combobox();
4207
4221
  return /* @__PURE__ */ jsx(ComboboxPortal, {
4208
4222
  ...portalProps,
@@ -4322,9 +4336,12 @@ function ComboboxChips({ className, ...props }) {
4322
4336
  ...props
4323
4337
  });
4324
4338
  }
4325
- function ComboboxChip({ className, ...props }) {
4339
+ function ComboboxChip({ className, ref, title, ...props }) {
4326
4340
  const { chip } = combobox();
4341
+ const overflowRef = useOverflowTitle(ref, title);
4327
4342
  return /* @__PURE__ */ jsx(Combobox$1.Chip, {
4343
+ ref: overflowRef,
4344
+ title,
4328
4345
  "data-slot": "combobox-chip",
4329
4346
  className: chip({ className }),
4330
4347
  ...props
@@ -4403,6 +4420,7 @@ const select = tv({
4403
4420
  positioner: ["isolate z-50 outline-none"],
4404
4421
  content: [
4405
4422
  "relative max-h-(--available-height) min-w-[max(var(--anchor-width),220px)] overflow-hidden",
4423
+ "max-w-[min(var(--available-width),max(var(--anchor-width),24rem))]",
4406
4424
  "outline-none",
4407
4425
  "rounded-container bg-layer-popover p-1.5 text-foreground",
4408
4426
  "shadow-float ring-1 ring-line-seam"
@@ -4429,9 +4447,9 @@ const select = tv({
4429
4447
  "[&>svg:not([class*='stroke-'])]:stroke-2"
4430
4448
  ],
4431
4449
  itemIndicator: ["pointer-events-none ml-auto flex shrink-0 items-center justify-center", "text-foreground [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:stroke-2 [&>svg_*]:stroke-2"],
4432
- itemText: ["min-w-0 flex-1 truncate"],
4450
+ itemText: ["min-w-0 flex-1 line-clamp-2 wrap-anywhere"],
4433
4451
  itemDescription: [
4434
- "order-last min-w-0 basis-full",
4452
+ "order-last min-w-0 basis-full wrap-anywhere",
4435
4453
  "[[data-slot=select-item-leading]~&]:ps-[calc(--spacing(4)+--spacing(2.5))]",
4436
4454
  "font-sans text-caption font-normal text-foreground-hint"
4437
4455
  ],
@@ -4510,9 +4528,12 @@ function SelectTrigger({ className, children, render, "data-invalid": dataInvali
4510
4528
  })
4511
4529
  });
4512
4530
  }
4513
- function SelectValue({ className, ...props }) {
4531
+ function SelectValue({ className, ref, title, ...props }) {
4514
4532
  const { value } = select();
4533
+ const overflowRef = useOverflowTitle(ref, title);
4515
4534
  return /* @__PURE__ */ jsx(Select$1.Value, {
4535
+ ref: overflowRef,
4536
+ title,
4516
4537
  "data-slot": "select-value",
4517
4538
  className: value({ className }),
4518
4539
  ...props
@@ -4545,7 +4566,7 @@ function SelectPopup({ className, ...props }) {
4545
4566
  ...props
4546
4567
  });
4547
4568
  }
4548
- function SelectContent({ align = "start", alignItemWithTrigger = false, alignOffset = 0, anchor, arrowPadding, collisionAvoidance, collisionBoundary, collisionPadding, disableAnchorTracking = true, positionMethod = "fixed", side = "bottom", sideOffset, sticky, portalProps, className, ...props }) {
4569
+ function SelectContent({ align = "start", alignItemWithTrigger = false, alignOffset = 0, anchor, arrowPadding, collisionAvoidance, collisionBoundary, collisionPadding = 8, disableAnchorTracking = true, positionMethod = "fixed", side = "bottom", sideOffset, sticky, portalProps, className, ...props }) {
4549
4570
  const { positioner, content } = select();
4550
4571
  const positionerNode = /* @__PURE__ */ jsx(Select$1.Positioner, {
4551
4572
  align,
@@ -4623,8 +4644,9 @@ function SelectItemIndicator({ className, children, ...props }) {
4623
4644
  children: children ?? defaultIndicator
4624
4645
  });
4625
4646
  }
4626
- function SelectItemText({ className, id, ...props }) {
4647
+ function SelectItemText({ className, id, ref, title, ...props }) {
4627
4648
  const { itemText } = select();
4649
+ const overflowRef = useOverflowTitle(ref, title);
4628
4650
  const generatedId = useId();
4629
4651
  const textId = id ?? generatedId;
4630
4652
  const setTextId = useContext(SelectItemPartsContext)?.setTextId;
@@ -4633,6 +4655,8 @@ function SelectItemText({ className, id, ...props }) {
4633
4655
  return () => setTextId?.(void 0);
4634
4656
  }, [setTextId, textId]);
4635
4657
  return /* @__PURE__ */ jsx(Select$1.ItemText, {
4658
+ ref: overflowRef,
4659
+ title,
4636
4660
  id: textId,
4637
4661
  "data-slot": "select-item-text",
4638
4662
  className: itemText({ className }),
@@ -8063,8 +8087,13 @@ function OtterIndicator({ status, className, ...props }) {
8063
8087
  const table = tv({ slots: {
8064
8088
  root: ["w-full border-collapse caption-bottom", "font-sans text-callout text-foreground"],
8065
8089
  header: [],
8066
- body: ["[&>tr:last-child>td]:border-b-0 [&>tr:last-child>th]:border-b-0", "[&>tr]:hover:bg-fill-pressed"],
8067
- row: ["aria-selected:bg-info-soft aria-selected:hover:bg-info-soft", "data-[selected=true]:bg-info-soft data-[selected=true]:hover:bg-info-soft"],
8090
+ body: ["[&>tr:last-child>td]:border-b-0 [&>tr:last-child>th]:border-b-0", "[&>tr]:hover:bg-fill-row-hover"],
8091
+ row: [
8092
+ "not-aria-selected:not-data-[selected=true]:data-popup-open:bg-fill-row-open",
8093
+ "not-aria-selected:not-data-[selected=true]:has-data-popup-open:bg-fill-row-open",
8094
+ "aria-selected:bg-info-soft aria-selected:hover:bg-info-soft",
8095
+ "data-[selected=true]:bg-info-soft data-[selected=true]:hover:bg-info-soft"
8096
+ ],
8068
8097
  head: [
8069
8098
  "text-left whitespace-nowrap",
8070
8099
  "border-b border-line-hairline px-3 py-2",
@@ -8425,7 +8454,8 @@ const files = tv({ slots: {
8425
8454
  "group/file-row flex w-full min-w-0 gap-3 px-3",
8426
8455
  "transition-colors",
8427
8456
  "items-center rounded-container border border-line-hairline bg-layer-card py-2.5 pr-1.5 pl-2.5 shadow-none",
8428
- "[@media(hover:hover)]:has-[[data-slot=file-row-open]:hover]:press-overlay has-[[data-slot=file-row-open]:active]:press-overlay",
8457
+ "[@media(hover:hover)]:has-[[data-slot=file-row-open]:hover]:row-hover-overlay has-[[data-slot=file-row-open]:active]:press-overlay",
8458
+ "has-data-popup-open:row-open-overlay",
8429
8459
  "has-[[data-slot=file-row-open]:focus-visible]:shadow-focus"
8430
8460
  ],
8431
8461
  rowOpen: [
@@ -15716,7 +15746,8 @@ const inboxItem = tv({
15716
15746
  "[[data-slot=inbox-item]+&]:before:block has-data-[slot=inbox-item-selection]:before:left-11",
15717
15747
  "has-data-[slot=inbox-item-leading]:before:left-16",
15718
15748
  "has-data-[slot=inbox-item-selection]:has-data-[slot=inbox-item-leading]:before:left-23",
15719
- "hover:bg-fill-pressed",
15749
+ "hover:bg-fill-row-hover",
15750
+ "not-data-[active=true]:data-popup-open:bg-fill-row-open not-data-[active=true]:has-data-popup-open:bg-fill-row-open",
15720
15751
  "data-[active=true]:bg-info-soft data-[active=true]:hover:bg-info-soft",
15721
15752
  "data-disabled:pointer-events-none data-disabled:hover:bg-transparent",
15722
15753
  "has-[[data-slot=inbox-item-open]:focus-visible]:keyboard:inset-ring-2 has-[[data-slot=inbox-item-open]:focus-visible]:keyboard:inset-ring-foreground",
@@ -16201,7 +16232,8 @@ const searchEntity = tv({ slots: {
16201
16232
  "relative rounded-none border-0 bg-transparent px-4 py-3 text-foreground shadow-none",
16202
16233
  "max-md:min-h-16",
16203
16234
  "not-first:before:absolute not-first:before:top-0 not-first:before:right-0 not-first:before:left-[55px] not-first:before:border-t not-first:before:border-line-hairline",
16204
- "hover:bg-fill-pressed active:bg-fill-pressed",
16235
+ "hover:bg-fill-row-hover active:bg-fill-pressed",
16236
+ "not-data-[selected=true]:data-popup-open:bg-fill-row-open",
16205
16237
  "disabled:cursor-default disabled:hover:bg-transparent disabled:active:bg-transparent",
16206
16238
  "data-[selected=true]:bg-brand-soft data-[selected=true]:hover:bg-brand-soft",
16207
16239
  "outline-none focus-visible:keyboard:inset-ring-2 focus-visible:keyboard:inset-ring-foreground"
@@ -16340,7 +16372,8 @@ const searchMessage = tv({ slots: {
16340
16372
  "w-full text-left transition-colors",
16341
16373
  "relative block rounded-none border-0 bg-transparent px-4 py-3 text-foreground shadow-none",
16342
16374
  "not-first:before:absolute not-first:before:top-0 not-first:before:right-0 not-first:before:left-4 not-first:before:border-t not-first:before:border-line-hairline",
16343
- "hover:bg-fill-pressed active:bg-fill-pressed",
16375
+ "hover:bg-fill-row-hover active:bg-fill-pressed",
16376
+ "not-data-[selected=true]:data-popup-open:bg-fill-row-open",
16344
16377
  "disabled:cursor-default disabled:hover:bg-transparent disabled:active:bg-transparent",
16345
16378
  "data-[selected=true]:bg-brand-soft data-[selected=true]:hover:bg-brand-soft",
16346
16379
  "outline-none focus-visible:keyboard:inset-ring-2 focus-visible:keyboard:inset-ring-foreground"
@@ -1524,6 +1524,52 @@ function DropdownMenuCheckboxItemIndicator({ className, ...props }) {
1524
1524
  });
1525
1525
  }
1526
1526
  //#endregion
1527
+ //#region src/lib/use-overflow-title.ts
1528
+ function cut(element) {
1529
+ return element.scrollWidth > element.clientWidth + 1 || element.scrollHeight > element.clientHeight + 1;
1530
+ }
1531
+ function assign(ref, node) {
1532
+ if (typeof ref === "function") ref(node);
1533
+ else if (ref) ref.current = node;
1534
+ }
1535
+ /**
1536
+ * Gives a value that is cut off (an ellipsis, a clamp) its whole text as its
1537
+ * `title`, and takes it away again when the value fits: a value that shows in
1538
+ * full needs no tooltip repeating it (design/patterns/forms.md#long-values-in-fields).
1539
+ * It watches the element and its children, so a part whose text sits in a
1540
+ * child that truncates (a chip's label) is covered too. A `title` the caller
1541
+ * passes wins, and is never touched.
1542
+ */
1543
+ function useOverflowTitle(ref, title) {
1544
+ const cleanup = useRef(void 0);
1545
+ const own = title !== void 0;
1546
+ return useCallback((node) => {
1547
+ cleanup.current?.();
1548
+ cleanup.current = void 0;
1549
+ assign(ref, node);
1550
+ const view = node?.ownerDocument.defaultView;
1551
+ if (!node || own || !view || !("ResizeObserver" in view)) return;
1552
+ const update = () => {
1553
+ const text = node.textContent?.trim() ?? "";
1554
+ if (text && (cut(node) || Array.from(node.children).some(cut))) node.title = text;
1555
+ else node.removeAttribute("title");
1556
+ };
1557
+ const resize = new view.ResizeObserver(update);
1558
+ resize.observe(node);
1559
+ for (const child of Array.from(node.children)) resize.observe(child);
1560
+ const mutation = new view.MutationObserver(update);
1561
+ mutation.observe(node, {
1562
+ childList: true,
1563
+ characterData: true,
1564
+ subtree: true
1565
+ });
1566
+ cleanup.current = () => {
1567
+ resize.disconnect();
1568
+ mutation.disconnect();
1569
+ };
1570
+ }, [own, ref]);
1571
+ }
1572
+ //#endregion
1527
1573
  //#region src/components/avatar/avatar.tsx
1528
1574
  const avatar = tv$1({
1529
1575
  slots: {
@@ -1817,7 +1863,8 @@ const messageItem = tv$1({
1817
1863
  "min-h-0 px-2 py-1 border-t-8 border-transparent bg-clip-padding",
1818
1864
  "hover:[--mi-ct-color:var(--foreground-hint)] has-data-popup-open:[--mi-ct-color:var(--foreground-hint)]",
1819
1865
  "bg-(--mi-row-fill) [--mi-row-fill:initial]",
1820
- "hover:[--mi-row-fill:var(--fill-pressed)] data-popup-open:[--mi-row-fill:var(--fill-pressed)] has-data-popup-open:[--mi-row-fill:var(--fill-pressed)]",
1866
+ "hover:[--mi-row-fill:var(--fill-message-hover)]",
1867
+ "data-popup-open:[--mi-row-fill:var(--fill-row-open)] has-data-popup-open:[--mi-row-fill:var(--fill-row-open)]",
1821
1868
  "has-data-[slot=message-item-search-match]:[--mi-row-fill:var(--info-soft)] has-data-[slot=message-item-search-match]:hover:[--mi-row-fill:var(--info-soft)]",
1822
1869
  "has-[[data-slot=message-multi-select-checkbox][data-checked]]:[--mi-row-fill:var(--info-soft)]",
1823
1870
  "has-[[data-slot=message-multi-select-checkbox][data-checked]]:hover:[--mi-row-fill:var(--info-soft)]"
@@ -3174,4 +3221,4 @@ function MessageListJumpPillDismiss({ className, children, render, nativeButton,
3174
3221
  });
3175
3222
  }
3176
3223
  //#endregion
3177
- export { MessageReactionTooltipNameText as $, DropdownMenuShortcut as $t, MessageTextSelectionToolbarButton as A, DialogClose as An, MessageItem as At, MessageReferenceUnavailable as B, DialogTrigger as Bn, DropdownMenuCheckboxItemIndicator as Bt, MessageQuotedPreviewUnavailable as C, TooltipContent as Cn, MessageItemEdited as Ct, MessageEmbedHeader as D, Badge as Dn, MessageItemAvatarSlot as Dt, MessageEmbedFooter as E, TooltipTrigger as En, MessageItemSearchMatch as Et, MessageReferenceChip as F, DialogNav as Fn, AvatarGroup as Ft, MessageReactionGlyph as G, useParentOverlayKind as Gn, DropdownMenuItemLabel as Gt, MessageReactionChip as H, buttonVariants as Hn, DropdownMenuFooter as Ht, MessageReferenceIndicator as I, DialogOverlay as In, AvatarGroupCount as It, MessageReactionQuickButton as J, useThemeScopeProps as Jn, DropdownMenuPortal as Jt, MessageReactionPickerContent as K, withOverlayLayer as Kn, DropdownMenuLabel as Kt, MessageReferenceLabel as L, DialogPortal as Ln, AvatarImage as Lt, MessageMultiSelect as M, DialogDescription as Mn, Avatar$1 as Mt, MessageMultiSelectCheckbox as N, DialogFooter as Nn, AvatarBadge as Nt, messageEmbed as O, Dialog$1 as On, MessageItemContinuationTime as Ot, MessageMultiSelectToolbar as P, DialogHeader as Pn, AvatarFallback as Pt, MessageReactionTooltipName as Q, DropdownMenuSeparator as Qt, MessageReferencePending as R, DialogSurface as Rn, DropdownMenu as Rt, MessageQuotedPreviewTimestamp as S, Tooltip$1 as Sn, MessageItemContent as St, MessageEmbedContent as T, TooltipProvider as Tn, MessageItemFooter as Tt, MessageReactionCount as U, Spinner as Un, DropdownMenuItem as Ut, MessageReactionAddButton as V, Button$1 as Vn, DropdownMenuContent as Vt, MessageReactionErrorIndicator as W, defaultNativeButton as Wn, DropdownMenuItemCount as Wt, MessageReactionTooltipContent as X, ThemeStateContext as Xn, DropdownMenuRadioItem as Xt, MessageReactionQuickRow as Y, useTheme as Yn, DropdownMenuRadioGroup as Yt, MessageReactionTooltipMeta as Z, tv$1 as Zn, DropdownMenuRadioItemIndicator as Zt, MessageQuotedPreviewContent as _, ScrollAreaViewport as _n, MessageItemSenderButton as _t, MessageListDateDivider as a, Panel as an, MessageItemSavedIndicator as at, MessageQuotedPreviewText as b, CheckboxIndicator as bn, MessageItemAttachments as bt, MessageList as c, PanelHeaderRoot as cn, MessageItemDelegatedAvatar as ct, MessageQuotedPreviewAttachments as d, PanelSection as dn, MessageItemDelegatedByName as dt, DropdownMenuSubmenu as en, MessageReactionTooltipNames as et, MessageQuotedPreviewAuthor as f, ScrollArea$1 as fn, MessageItemHeader as ft, MessageQuotedPreviewChannel as g, ScrollAreaThumb as gn, MessageItemSenderBadges as gt, MessageQuotedPreviewAuthorName as h, ScrollAreaScrollbar as hn, MessageItemSender as ht, MessageListJumpPillGroup as i, KbdGroup as in, MessageItemReadReceipt as it, MessageTextSelectionToolbarSeparator as j, DialogContent as jn, searchHit as jt, MessageTextSelectionToolbar as k, DialogBody as kn, MessageItemGutter as kt, MessageQuotedPreview as l, PanelScrollContent as ln, MessageItemDelegatedBy as lt, MessageQuotedPreviewAuthorMeta as m, ScrollAreaCorner as mn, MessageItemMeta as mt, MessageListJumpPill as n, DropdownMenuTrigger as nn, MessageItemBadge as nt, MessageListHistoryLimited as o, PanelBody as on, MessageItemToolbar as ot, MessageQuotedPreviewAuthorDelegatedBy as p, ScrollAreaContent as pn, MessageItemInlineStatus as pt, MessageReactionPickerStatic as q, resolveThemeScopeProps as qn, DropdownMenuPopup as qt, MessageListJumpPillDismiss as r, Kbd as rn, MessageItemBadgeSeparator as rt, MessageListNotice as s, PanelFooter as sn, MessageItemToolbarButton as st, MessageListJumpControls as t, DropdownMenuSubmenuTrigger as tn, MessageReactionTooltipSeparator as tt, MessageQuotedPreviewAttachment as u, PanelScrollViewport as un, MessageItemDelegatedByButton as ut, MessageQuotedPreviewHeader as v, useMobileViewport as vn, MessageItemSenderGroup as vt, MessageEmbed as w, TooltipPortal as wn, MessageItemEmbedded as wt, MessageQuotedPreviewThread as x, PRESENCE_COLOR as xn, MessageItemBody as xt, MessageQuotedPreviewLoading as y, Checkbox$1 as yn, MessageItemTime as yt, MessageReferenceText as z, DialogTitle as zn, DropdownMenuCheckboxItem as zt };
3224
+ export { MessageReactionTooltipNameText as $, DropdownMenuSeparator as $t, MessageTextSelectionToolbarButton as A, DialogBody as An, MessageItem as At, MessageReferenceUnavailable as B, DialogTitle as Bn, DropdownMenuCheckboxItem as Bt, MessageQuotedPreviewUnavailable as C, Tooltip$1 as Cn, MessageItemEdited as Ct, MessageEmbedHeader as D, TooltipTrigger as Dn, MessageItemAvatarSlot as Dt, MessageEmbedFooter as E, TooltipProvider as En, MessageItemSearchMatch as Et, MessageReferenceChip as F, DialogHeader as Fn, AvatarGroup as Ft, MessageReactionGlyph as G, defaultNativeButton as Gn, DropdownMenuItemCount as Gt, MessageReactionChip as H, Button$1 as Hn, DropdownMenuContent as Ht, MessageReferenceIndicator as I, DialogNav as In, AvatarGroupCount as It, MessageReactionQuickButton as J, resolveThemeScopeProps as Jn, DropdownMenuPopup as Jt, MessageReactionPickerContent as K, useParentOverlayKind as Kn, DropdownMenuItemLabel as Kt, MessageReferenceLabel as L, DialogOverlay as Ln, AvatarImage as Lt, MessageMultiSelect as M, DialogContent as Mn, Avatar$1 as Mt, MessageMultiSelectCheckbox as N, DialogDescription as Nn, AvatarBadge as Nt, messageEmbed as O, Badge as On, MessageItemContinuationTime as Ot, MessageMultiSelectToolbar as P, DialogFooter as Pn, AvatarFallback as Pt, MessageReactionTooltipName as Q, tv$1 as Qn, DropdownMenuRadioItemIndicator as Qt, MessageReferencePending as R, DialogPortal as Rn, useOverflowTitle as Rt, MessageQuotedPreviewTimestamp as S, PRESENCE_COLOR as Sn, MessageItemContent as St, MessageEmbedContent as T, TooltipPortal as Tn, MessageItemFooter as Tt, MessageReactionCount as U, buttonVariants as Un, DropdownMenuFooter as Ut, MessageReactionAddButton as V, DialogTrigger as Vn, DropdownMenuCheckboxItemIndicator as Vt, MessageReactionErrorIndicator as W, Spinner as Wn, DropdownMenuItem as Wt, MessageReactionTooltipContent as X, useTheme as Xn, DropdownMenuRadioGroup as Xt, MessageReactionQuickRow as Y, useThemeScopeProps as Yn, DropdownMenuPortal as Yt, MessageReactionTooltipMeta as Z, ThemeStateContext as Zn, DropdownMenuRadioItem as Zt, MessageQuotedPreviewContent as _, ScrollAreaThumb as _n, MessageItemSenderButton as _t, MessageListDateDivider as a, KbdGroup as an, MessageItemSavedIndicator as at, MessageQuotedPreviewText as b, Checkbox$1 as bn, MessageItemAttachments as bt, MessageList as c, PanelFooter as cn, MessageItemDelegatedAvatar as ct, MessageQuotedPreviewAttachments as d, PanelScrollViewport as dn, MessageItemDelegatedByName as dt, DropdownMenuShortcut as en, MessageReactionTooltipNames as et, MessageQuotedPreviewAuthor as f, PanelSection as fn, MessageItemHeader as ft, MessageQuotedPreviewChannel as g, ScrollAreaScrollbar as gn, MessageItemSenderBadges as gt, MessageQuotedPreviewAuthorName as h, ScrollAreaCorner as hn, MessageItemSender as ht, MessageListJumpPillGroup as i, Kbd as in, MessageItemReadReceipt as it, MessageTextSelectionToolbarSeparator as j, DialogClose as jn, searchHit as jt, MessageTextSelectionToolbar as k, Dialog$1 as kn, MessageItemGutter as kt, MessageQuotedPreview as l, PanelHeaderRoot as ln, MessageItemDelegatedBy as lt, MessageQuotedPreviewAuthorMeta as m, ScrollAreaContent as mn, MessageItemMeta as mt, MessageListJumpPill as n, DropdownMenuSubmenuTrigger as nn, MessageItemBadge as nt, MessageListHistoryLimited as o, Panel as on, MessageItemToolbar as ot, MessageQuotedPreviewAuthorDelegatedBy as p, ScrollArea$1 as pn, MessageItemInlineStatus as pt, MessageReactionPickerStatic as q, withOverlayLayer as qn, DropdownMenuLabel as qt, MessageListJumpPillDismiss as r, DropdownMenuTrigger as rn, MessageItemBadgeSeparator as rt, MessageListNotice as s, PanelBody as sn, MessageItemToolbarButton as st, MessageListJumpControls as t, DropdownMenuSubmenu as tn, MessageReactionTooltipSeparator as tt, MessageQuotedPreviewAttachment as u, PanelScrollContent as un, MessageItemDelegatedByButton as ut, MessageQuotedPreviewHeader as v, ScrollAreaViewport as vn, MessageItemSenderGroup as vt, MessageEmbed as w, TooltipContent as wn, MessageItemEmbedded as wt, MessageQuotedPreviewThread as x, CheckboxIndicator as xn, MessageItemBody as xt, MessageQuotedPreviewLoading as y, useMobileViewport as yn, MessageItemTime as yt, MessageReferenceText as z, DialogSurface as zn, DropdownMenu as zt };
package/dist/style.css CHANGED
@@ -1138,6 +1138,14 @@
1138
1138
  overflow: hidden;
1139
1139
  }
1140
1140
 
1141
+ .r-combobox-select__option .r-combobox-select__text {
1142
+ -webkit-line-clamp: 2;
1143
+ white-space: normal;
1144
+ overflow-wrap: anywhere;
1145
+ -webkit-box-orient: vertical;
1146
+ display: -webkit-box;
1147
+ }
1148
+
1141
1149
  .r-combobox-select__actions {
1142
1150
  flex: none;
1143
1151
  align-items: center;
@@ -1239,7 +1247,7 @@
1239
1247
  justify-content: space-between;
1240
1248
  align-items: center;
1241
1249
  gap: 10px;
1242
- padding: 0 10px;
1250
+ padding: 6px 10px;
1243
1251
  font-weight: 500;
1244
1252
  transition: background-color .12s, color .12s;
1245
1253
  display: flex;
package/dist/styles.css CHANGED
@@ -283,6 +283,9 @@
283
283
  --color-foreground-on-frame-active: var(--foreground-on-frame-active);
284
284
  --color-fill-frame-pressed: var(--fill-frame-pressed);
285
285
  --color-fill-pressed: var(--fill-pressed);
286
+ --color-fill-row-hover: var(--fill-row-hover);
287
+ --color-fill-message-hover: var(--fill-message-hover);
288
+ --color-fill-row-open: var(--fill-row-open);
286
289
  --color-layer-code: var(--layer-code);
287
290
  --color-foreground-link: var(--foreground-link);
288
291
  --color-sticker-ink: var(--sticker-ink);
@@ -490,6 +493,18 @@ body {
490
493
  background-image: linear-gradient(var(--fill-pressed), var(--fill-pressed));
491
494
  }
492
495
 
496
+ /* A row laid over a solid surface (a list row on a card, a file row) hovers
497
+ with the lighter row step, as an overlay too, so press (press-overlay)
498
+ replaces it instead of stacking on it. */
499
+ @utility row-hover-overlay {
500
+ background-image: linear-gradient(var(--fill-row-hover), var(--fill-row-hover));
501
+ }
502
+
503
+ /* The same row with its menu open: fill-row-open, as an overlay. */
504
+ @utility row-open-overlay {
505
+ background-image: linear-gradient(var(--fill-row-open), var(--fill-row-open));
506
+ }
507
+
493
508
  @utility press-overlay-sticker {
494
509
  background-image: linear-gradient(var(--sticker-pressed), var(--sticker-pressed));
495
510
  }
package/dist/tokens.json CHANGED
@@ -1527,6 +1527,63 @@
1527
1527
  }
1528
1528
  }
1529
1529
  }
1530
+ },
1531
+ "row-hover": {
1532
+ "$description": "Hover on a whole row (sidebar, list, inbox, search result, table, file row): one perceptible step (OKLab dE about 2.8 in both modes), below every selection tint, so text keeps its contrast.",
1533
+ "$value": {
1534
+ "colorSpace": "oklch",
1535
+ "components": [0.1813, 0.005, 17.62],
1536
+ "alpha": 0.04
1537
+ },
1538
+ "$extensions": {
1539
+ "build.botiverse.raft": {
1540
+ "modes": {
1541
+ "dark": {
1542
+ "colorSpace": "oklch",
1543
+ "components": [0.9843, 0.004, 106.47],
1544
+ "alpha": 0.03
1545
+ }
1546
+ }
1547
+ }
1548
+ }
1549
+ },
1550
+ "message-hover": {
1551
+ "$description": "Hover on a message: the lightest perceptible step (OKLab dE about 2.1 in both modes), because a message is a large block someone reads with the pointer resting on it.",
1552
+ "$value": {
1553
+ "colorSpace": "oklch",
1554
+ "components": [0.1813, 0.005, 17.62],
1555
+ "alpha": 0.03
1556
+ },
1557
+ "$extensions": {
1558
+ "build.botiverse.raft": {
1559
+ "modes": {
1560
+ "dark": {
1561
+ "colorSpace": "oklch",
1562
+ "components": [0.9843, 0.004, 106.47],
1563
+ "alpha": 0.022
1564
+ }
1565
+ }
1566
+ }
1567
+ }
1568
+ },
1569
+ "row-open": {
1570
+ "$description": "Any row with its menu open (right-click, its menu button, press and hold): one step over a hover (OKLab dE 3.4 to 4.3 on every row surface), because on a phone, which has no hover, it is the only sign of which row the menu acts on. Still under info-soft and brand-soft on every surface.",
1571
+ "$value": {
1572
+ "colorSpace": "oklch",
1573
+ "components": [0.1813, 0.005, 17.62],
1574
+ "alpha": 0.05
1575
+ },
1576
+ "$extensions": {
1577
+ "build.botiverse.raft": {
1578
+ "modes": {
1579
+ "dark": {
1580
+ "colorSpace": "oklch",
1581
+ "components": [0.9843, 0.004, 106.47],
1582
+ "alpha": 0.04
1583
+ }
1584
+ }
1585
+ }
1586
+ }
1530
1587
  }
1531
1588
  },
1532
1589
  "line": {
package/dist/wip.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { An as DialogClose, Bn as DialogTrigger, Jn as useThemeScopeProps, On as Dialog, Vn as Button$1, Wn as defaultNativeButton, Yn as useTheme, Zn as tv, ct as MessageItemDelegatedAvatar, dt as MessageItemDelegatedByName, i as MessageListJumpPillGroup, jn as DialogContent, lt as MessageItemDelegatedBy, n as MessageListJumpPill, p as MessageQuotedPreviewAuthorDelegatedBy, r as MessageListJumpPillDismiss, t as MessageListJumpControls, ut as MessageItemDelegatedByButton, zn as DialogTitle } from "./message-list-CxawdwMF.mjs";
1
+ import { Bn as DialogTitle, Gn as defaultNativeButton, Hn as Button$1, Mn as DialogContent, Qn as tv, Rt as useOverflowTitle, Vn as DialogTrigger, Xn as useTheme, Yn as useThemeScopeProps, ct as MessageItemDelegatedAvatar, dt as MessageItemDelegatedByName, i as MessageListJumpPillGroup, jn as DialogClose, kn as Dialog, lt as MessageItemDelegatedBy, n as MessageListJumpPill, p as MessageQuotedPreviewAuthorDelegatedBy, r as MessageListJumpPillDismiss, t as MessageListJumpControls, ut as MessageItemDelegatedByButton } from "./message-list-DP03T8gF.mjs";
2
2
  import { Check, ChevronDown, LoaderCircle, Plus, X } from "lucide-react";
3
3
  import { createContext, use, useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
4
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -70,19 +70,21 @@ const defaultMessages = {
70
70
  remove: (label) => `Remove ${label}`
71
71
  };
72
72
  const defaultRenderCreateLabel = (query) => `Create “${query}”`;
73
+ /** An option's or a chip's text, with its whole value as the title when it is cut off. */
74
+ function OverflowText({ children }) {
75
+ return /* @__PURE__ */ jsx("span", {
76
+ ref: useOverflowTitle(),
77
+ className: "r-combobox-select__text",
78
+ children
79
+ });
80
+ }
73
81
  function recordLabel(record, renderLabel) {
74
82
  return record.option === void 0 ? record.label : renderLabel?.(record.option) ?? record.label;
75
83
  }
76
84
  function renderOptionContent({ record, selected, renderLabel, renderOption, renderCreateLabel }) {
77
- if (record.createQuery !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Plus, { "aria-hidden": true }), /* @__PURE__ */ jsx("span", {
78
- className: "r-combobox-select__text",
79
- children: renderCreateLabel(record.label)
80
- })] });
85
+ if (record.createQuery !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Plus, { "aria-hidden": true }), /* @__PURE__ */ jsx(OverflowText, { children: renderCreateLabel(record.label) })] });
81
86
  const content = record.option === void 0 ? record.label : renderOption?.(record.option, { selected }) ?? recordLabel(record, renderLabel);
82
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
83
- className: "r-combobox-select__text",
84
- children: content
85
- }), /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
87
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(OverflowText, { children: content }), /* @__PURE__ */ jsx(Combobox.ItemIndicator, {
86
88
  className: "r-combobox-select__indicator",
87
89
  children: /* @__PURE__ */ jsx(Check, { "aria-hidden": true })
88
90
  })] });
@@ -96,10 +98,7 @@ function renderSelectedChip({ record, index, tagLimit, strings, renderLabel, ren
96
98
  "data-overflow": overflow || void 0,
97
99
  "aria-label": record.label,
98
100
  "aria-description": strings.chipDescription,
99
- children: [/* @__PURE__ */ jsx("span", {
100
- className: "r-combobox-select__text",
101
- children: content
102
- }), /* @__PURE__ */ jsx(Combobox.ChipRemove, {
101
+ children: [/* @__PURE__ */ jsx(OverflowText, { children: content }), /* @__PURE__ */ jsx(Combobox.ChipRemove, {
103
102
  className: "r-combobox-select__remove",
104
103
  "aria-label": strings.remove(record.label),
105
104
  children: /* @__PURE__ */ jsx(X, { "aria-hidden": true })
@@ -472,6 +471,7 @@ function ComboboxSelect({ options, multiple, value, defaultValue, onValueChange,
472
471
  children: /* @__PURE__ */ jsx(Combobox.Positioner, {
473
472
  sideOffset: 4,
474
473
  align: "start",
474
+ collisionPadding: 8,
475
475
  ...phone ? {
476
476
  side: listSide,
477
477
  collisionAvoidance: PHONE_LIST_COLLISION
@@ -634,7 +634,7 @@ const comment = tv({
634
634
  cardTrigger: [
635
635
  "absolute -inset-px z-10 cursor-pointer",
636
636
  "rounded-container border-0 bg-transparent p-0",
637
- "hover:bg-fill-pressed active:bg-fill-pressed",
637
+ "hover:bg-fill-row-hover active:bg-fill-pressed",
638
638
  "outline-none focus-visible:shadow-focus"
639
639
  ],
640
640
  cardQuote: ["sr-only"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botiverse/raft-ui",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "React components and CSS foundations for the Raft Design System.",
5
5
  "keywords": [
6
6
  "agent-skills",