@botiverse/raft-ui 0.63.1 → 0.65.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 +51 -0
- package/dist/components/activity-inbox/activity-inbox-sidebar.recipe.mjs +1 -1
- package/dist/components/activity-inbox/activity-inbox-toolbar.recipe.mjs +6 -1
- package/dist/components/alert-dialog/alert-dialog.mjs +3 -3
- package/dist/components/announcement-dialog/announcement-dialog.mjs +2 -2
- package/dist/components/app-link-card/app-link-card.d.mts +56 -0
- package/dist/components/app-link-card/app-link-card.mjs +207 -0
- package/dist/components/app-link-card/index.d.mts +2 -0
- package/dist/components/app-rail/app-rail.recipe.mjs +12 -7
- package/dist/components/app-shell/app-shell.mjs +1 -1
- package/dist/components/avatar/avatar.mjs +1 -0
- package/dist/components/badge/badge.mjs +6 -1
- package/dist/components/banner/banner.mjs +1 -1
- package/dist/components/button/button-split.d.mts +38 -0
- package/dist/components/button/button-split.mjs +126 -0
- package/dist/components/button/button.mjs +13 -8
- package/dist/components/button/index.d.mts +2 -1
- package/dist/components/code-block/code-block.recipe.mjs +1 -1
- package/dist/components/combobox/combobox.mjs +4 -4
- package/dist/components/combobox-select/combobox-select.css +6 -3
- package/dist/components/comment/comment-margin.mjs +2 -1
- package/dist/components/composer/composer-suggestion-list.mjs +1 -1
- package/dist/components/composer/composer-toolbar-label.mjs +1 -1
- package/dist/components/composer/composer.mjs +1 -1
- package/dist/components/composer/composer.recipe.mjs +38 -26
- package/dist/components/conversation-panel/conversation-panel-empty-state.mjs +1 -1
- package/dist/components/conversation-panel/conversation-panel.recipe.mjs +3 -2
- package/dist/components/dialog/dialog-sheet-context.mjs +1 -1
- package/dist/components/dialog/dialog.mjs +7 -7
- package/dist/components/drawer/drawer.mjs +3 -2
- package/dist/components/drawer/drawer.recipe.mjs +5 -3
- package/dist/components/empty-state/empty-state.mjs +1 -1
- package/dist/components/field/field.mjs +1 -1
- package/dist/components/files/files.recipe.mjs +1 -1
- package/dist/components/filter-chip/filter-chip.mjs +1 -1
- package/dist/components/form-section/form-section.mjs +1 -1
- package/dist/components/icon-tile/icon-tile.mjs +3 -3
- package/dist/components/inbox-item/inbox-item.recipe.mjs +4 -2
- package/dist/components/input/input.recipe.mjs +1 -1
- package/dist/components/input-group/input-group.mjs +1 -1
- package/dist/components/lightbox/lightbox.mjs +1 -1
- package/dist/components/list-row/list-row.recipe.mjs +2 -2
- package/dist/components/message-action-card/message-action-card-content.recipe.mjs +1 -1
- package/dist/components/message-action-card/message-action-card.recipe.mjs +1 -1
- package/dist/components/message-item/index.d.mts +2 -2
- package/dist/components/message-item/message-item-content.d.mts +14 -0
- package/dist/components/message-item/message-item-content.mjs +146 -1
- package/dist/components/message-item/message-item.recipe.d.mts +3 -0
- package/dist/components/message-item/message-item.recipe.mjs +3 -2
- package/dist/components/message-item/message-reaction.recipe.mjs +4 -3
- package/dist/components/message-list/message-list.recipe.mjs +3 -1
- package/dist/components/mode-bar/mode-bar.mjs +1 -1
- package/dist/components/notification-center/notification-center.mjs +1 -1
- package/dist/components/panel/panel-action.recipe.mjs +5 -5
- package/dist/components/panel/panel-header.recipe.mjs +10 -9
- package/dist/components/panel/panel.recipe.mjs +2 -2
- package/dist/components/picker-trigger-button/picker-trigger-button.mjs +1 -1
- package/dist/components/profile-panel/profile-panel.recipe.mjs +1 -1
- package/dist/components/scroll-area/scroll-area.css +74 -33
- package/dist/components/search/search-entity.recipe.mjs +3 -2
- package/dist/components/search/search-message.recipe.mjs +1 -0
- package/dist/components/search/search-thread.recipe.mjs +1 -1
- package/dist/components/search/search-trigger.mjs +1 -1
- package/dist/components/search/search.recipe.mjs +7 -3
- package/dist/components/segmented-control/segmented-control.mjs +9 -8
- package/dist/components/select/select.mjs +2 -2
- package/dist/components/sidebar/sidebar-item.recipe.mjs +5 -4
- package/dist/components/sidebar/sidebar-section.recipe.mjs +5 -2
- package/dist/components/sidebar/sidebar.recipe.mjs +3 -3
- package/dist/components/switch/switch.mjs +3 -3
- package/dist/components/tabs/tabs.mjs +1 -1
- package/dist/components/task-board/task-board-column.recipe.mjs +1 -1
- package/dist/components/task-list/task-list-section.recipe.mjs +1 -1
- package/dist/components/tasks/tasks-panel.recipe.mjs +4 -3
- package/dist/components/text-selection-toolbar/text-selection-toolbar.recipe.mjs +1 -1
- package/dist/components/textarea/textarea.mjs +1 -1
- package/dist/components/thread-panel/thread-panel.recipe.mjs +3 -3
- package/dist/components/toggle-group/toggle-group.mjs +1 -1
- package/dist/foundation.css +100 -5
- package/dist/lib/head-edges.mjs +38 -8
- package/dist/lib/list-cell.mjs +1 -0
- package/dist/styles.css +54 -7
- package/dist/tokens.json +260 -4
- package/dist/wip.d.mts +6 -1
- package/dist/wip.mjs +4 -1
- package/package.json +1 -1
|
@@ -8,7 +8,7 @@ const inputGroup = tv({
|
|
|
8
8
|
root: [
|
|
9
9
|
"group/input-group relative flex w-full min-w-0 items-center",
|
|
10
10
|
"has-data-[input-group-trim=inline-end]:[--ig-control-pr:0]",
|
|
11
|
-
"h-control overflow-hidden rounded-control border-[1.5px] border-line-field bg-layer-card text-foreground",
|
|
11
|
+
"h-control overflow-hidden rounded-(--control-radius) border-[1.5px] border-line-field bg-layer-card text-foreground",
|
|
12
12
|
"shadow-none transition-shadow duration-90 ease-out has-focus-visible:shadow-focus",
|
|
13
13
|
"has-[[data-slot=input-group-control][data-invalid]]:border-danger-strong",
|
|
14
14
|
"has-[[data-slot=input-group-control]:disabled]:cursor-not-allowed has-[[data-slot=input-group-control]:disabled]:border-line-hairline has-[[data-slot=input-group-control]:disabled]:bg-fill-muted",
|
|
@@ -28,7 +28,7 @@ const lightbox = tv({ slots: {
|
|
|
28
28
|
],
|
|
29
29
|
toolbar: [
|
|
30
30
|
"pointer-events-auto shrink-0 flex items-center gap-3",
|
|
31
|
-
"h-[calc(
|
|
31
|
+
"h-[calc(var(--header-height)+env(safe-area-inset-top,0px))] pt-[env(safe-area-inset-top,0px)]",
|
|
32
32
|
"pl-[calc(16px+env(safe-area-inset-left,0px))] pr-[calc(16px+env(safe-area-inset-right,0px))]",
|
|
33
33
|
"**:data-lightbox-close:static **:data-lightbox-close:inset-auto",
|
|
34
34
|
"**:data-lightbox-close:top-auto **:data-lightbox-close:right-auto",
|
|
@@ -32,8 +32,8 @@ const listRow = tv({
|
|
|
32
32
|
},
|
|
33
33
|
variants: {
|
|
34
34
|
variant: {
|
|
35
|
-
default: { root: "min-h-16 [--list-row-rule-start:63px]" },
|
|
36
|
-
plain: { root: "[--list-row-rule-start:16px]" },
|
|
35
|
+
default: { root: "min-h-16 pointer-coarse:min-h-14 pointer-coarse:py-2 [--list-row-rule-start:63px]" },
|
|
36
|
+
plain: { root: "py-(--settings-row-inset) [--list-row-rule-start:16px]" },
|
|
37
37
|
entry: { root: "" }
|
|
38
38
|
},
|
|
39
39
|
interactive: {
|
|
@@ -24,7 +24,7 @@ const messageActionCardContent = tv({ slots: {
|
|
|
24
24
|
"@max-sm/action-card:min-h-0 @max-sm/action-card:py-0"
|
|
25
25
|
],
|
|
26
26
|
scopeList: ["mt-0 stack-y-1.5"],
|
|
27
|
-
scopeListViewport: ["overflow-y-auto overscroll-contain", "max-h-[
|
|
27
|
+
scopeListViewport: ["overflow-y-auto overscroll-contain", "max-h-[136px] stack-y-1.5 pr-1"],
|
|
28
28
|
scopeListLabel: ["text-footnote font-medium text-foreground-hint"],
|
|
29
29
|
scope: ["min-w-0 border p-1.5", "rounded-control border-line-hairline bg-layer-card px-2.5 py-2"],
|
|
30
30
|
scopeName: ["break-all font-mono", "text-mono-meta font-normal text-foreground"],
|
|
@@ -11,7 +11,7 @@ const messageActionCard = tv({
|
|
|
11
11
|
headerIcon: [
|
|
12
12
|
"flex shrink-0 items-center justify-center",
|
|
13
13
|
"[&>svg]:shrink-0",
|
|
14
|
-
"size-[27px] rounded-
|
|
14
|
+
"size-[27px] rounded-chip bg-fill-muted text-foreground-muted",
|
|
15
15
|
"[&>svg]:size-3.5"
|
|
16
16
|
],
|
|
17
17
|
headerTitle: ["min-w-0 flex-1", "pt-[calc((27px-1lh)/2)]"],
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MessageItem, MessageItemProps } from "./message-item-root.mjs";
|
|
2
2
|
import { MessageItemAvatarSlot, MessageItemAvatarSlotProps, MessageItemContinuationTime, MessageItemContinuationTimeProps, MessageItemGutter, MessageItemGutterProps } from "./message-item-gutter.mjs";
|
|
3
|
-
import { MessageItemAttachments, MessageItemAttachmentsProps, MessageItemBody, MessageItemBodyProps, MessageItemContent, MessageItemContentProps, MessageItemEdited, MessageItemEditedProps, MessageItemEmbedded, MessageItemEmbeddedProps, MessageItemFooter, MessageItemFooterProps, MessageItemSearchMatch, MessageItemSearchMatchProps } from "./message-item-content.mjs";
|
|
3
|
+
import { MessageItemAttachments, MessageItemAttachmentsProps, MessageItemBody, MessageItemBodyProps, MessageItemContent, MessageItemContentProps, MessageItemEdited, MessageItemEditedProps, MessageItemEmbedded, MessageItemEmbeddedProps, MessageItemFooter, MessageItemFooterProps, MessageItemSearchMatch, MessageItemSearchMatchProps, MessageItemTrailing, MessageItemTrailingProps } from "./message-item-content.mjs";
|
|
4
4
|
import { MessageItemHeader, MessageItemHeaderProps, MessageItemInlineStatus, MessageItemInlineStatusProps, MessageItemMeta, MessageItemMetaProps, MessageItemSender, MessageItemSenderBadges, MessageItemSenderBadgesProps, MessageItemSenderButton, MessageItemSenderButtonProps, MessageItemSenderGroup, MessageItemSenderGroupProps, MessageItemSenderProps, MessageItemTime, MessageItemTimeProps } from "./message-item-header.mjs";
|
|
5
5
|
import { MessageItemDelegatedAvatar, MessageItemDelegatedAvatarProps, MessageItemDelegatedBy, MessageItemDelegatedByButton, MessageItemDelegatedByButtonProps, MessageItemDelegatedByName, MessageItemDelegatedByNameProps, MessageItemDelegatedByProps } from "./message-item-delegated.mjs";
|
|
6
6
|
import { MessageItemToolbar, MessageItemToolbarButton, MessageItemToolbarButtonProps, MessageItemToolbarProps } from "./message-item-toolbar.mjs";
|
|
@@ -9,4 +9,4 @@ import { MessageReactionAddButton, MessageReactionAddButtonProps, MessageReactio
|
|
|
9
9
|
import { MessageReferenceChipVariant, MessageReferenceTextVariant } from "./message-reference.recipe.mjs";
|
|
10
10
|
import { MessageReferenceChip, MessageReferenceChipProps, MessageReferenceIcon, MessageReferenceIconProps, MessageReferenceIndicator, MessageReferenceIndicatorProps, MessageReferenceLabel, MessageReferenceLabelProps, MessageReferencePending, MessageReferencePendingProps, MessageReferenceReadMark, MessageReferenceReadMarkProps, MessageReferenceSuffix, MessageReferenceSuffixProps, MessageReferenceText, MessageReferenceTextProps, MessageReferenceUnavailable, MessageReferenceUnavailableProps } from "./message-reference.mjs";
|
|
11
11
|
import { MessageMultiSelect, MessageMultiSelectCheckbox, MessageMultiSelectCheckboxProps, MessageMultiSelectProps, MessageMultiSelectToolbar, MessageMultiSelectToolbarActions, MessageMultiSelectToolbarActionsProps, MessageMultiSelectToolbarProps } from "./message-multi-select.mjs";
|
|
12
|
-
export { MessageItem, MessageItemAttachments, type MessageItemAttachmentsProps, MessageItemAvatarSlot, type MessageItemAvatarSlotProps, MessageItemBadge, type MessageItemBadgeProps, MessageItemBadgeSeparator, type MessageItemBadgeSeparatorProps, type MessageItemBadgeStatus, MessageItemBody, type MessageItemBodyProps, MessageItemContent, type MessageItemContentProps, MessageItemContinuationTime, type MessageItemContinuationTimeProps, MessageItemDelegatedAvatar, type MessageItemDelegatedAvatarProps, MessageItemDelegatedBy, MessageItemDelegatedByButton, type MessageItemDelegatedByButtonProps, MessageItemDelegatedByName, type MessageItemDelegatedByNameProps, type MessageItemDelegatedByProps, MessageItemEdited, type MessageItemEditedProps, MessageItemEmbedded, type MessageItemEmbeddedProps, MessageItemFooter, type MessageItemFooterProps, MessageItemGutter, type MessageItemGutterProps, MessageItemHeader, type MessageItemHeaderProps, MessageItemInlineStatus, type MessageItemInlineStatusProps, MessageItemMeta, type MessageItemMetaProps, type MessageItemProps, MessageItemReadReceipt, type MessageItemReadReceiptProps, MessageItemSavedIndicator, type MessageItemSavedIndicatorProps, MessageItemSearchMatch, type MessageItemSearchMatchProps, MessageItemSender, MessageItemSenderBadges, type MessageItemSenderBadgesProps, MessageItemSenderButton, type MessageItemSenderButtonProps, MessageItemSenderGroup, type MessageItemSenderGroupProps, type MessageItemSenderProps, MessageItemTime, type MessageItemTimeProps, MessageItemToolbar, MessageItemToolbarButton, type MessageItemToolbarButtonProps, type MessageItemToolbarProps, MessageMultiSelect, MessageMultiSelectCheckbox, type MessageMultiSelectCheckboxProps, type MessageMultiSelectProps, MessageMultiSelectToolbar, MessageMultiSelectToolbarActions, type MessageMultiSelectToolbarActionsProps, type MessageMultiSelectToolbarProps, MessageReactionAddButton, type MessageReactionAddButtonProps, MessageReactionChip, type MessageReactionChipProps, MessageReactionCount, type MessageReactionCountProps, MessageReactionErrorIndicator, type MessageReactionErrorIndicatorProps, MessageReactionGlyph, type MessageReactionGlyphProps, MessageReactionPickerContent, type MessageReactionPickerContentProps, MessageReactionPickerStatic, type MessageReactionPickerStaticProps, MessageReactionQuickButton, type MessageReactionQuickButtonProps, MessageReactionQuickRow, type MessageReactionQuickRowProps, MessageReactionTooltipContent, type MessageReactionTooltipContentProps, MessageReactionTooltipMeta, type MessageReactionTooltipMetaProps, MessageReactionTooltipName, type MessageReactionTooltipNameProps, MessageReactionTooltipNameText, type MessageReactionTooltipNameTextProps, MessageReactionTooltipNames, type MessageReactionTooltipNamesProps, MessageReactionTooltipSeparator, type MessageReactionTooltipSeparatorProps, MessageReferenceChip, type MessageReferenceChipProps, type MessageReferenceChipVariant, MessageReferenceIcon, type MessageReferenceIconProps, MessageReferenceIndicator, type MessageReferenceIndicatorProps, MessageReferenceLabel, type MessageReferenceLabelProps, MessageReferencePending, type MessageReferencePendingProps, MessageReferenceReadMark, type MessageReferenceReadMarkProps, MessageReferenceSuffix, type MessageReferenceSuffixProps, MessageReferenceText, type MessageReferenceTextProps, type MessageReferenceTextVariant, MessageReferenceUnavailable, type MessageReferenceUnavailableProps };
|
|
12
|
+
export { MessageItem, MessageItemAttachments, type MessageItemAttachmentsProps, MessageItemAvatarSlot, type MessageItemAvatarSlotProps, MessageItemBadge, type MessageItemBadgeProps, MessageItemBadgeSeparator, type MessageItemBadgeSeparatorProps, type MessageItemBadgeStatus, MessageItemBody, type MessageItemBodyProps, MessageItemContent, type MessageItemContentProps, MessageItemContinuationTime, type MessageItemContinuationTimeProps, MessageItemDelegatedAvatar, type MessageItemDelegatedAvatarProps, MessageItemDelegatedBy, MessageItemDelegatedByButton, type MessageItemDelegatedByButtonProps, MessageItemDelegatedByName, type MessageItemDelegatedByNameProps, type MessageItemDelegatedByProps, MessageItemEdited, type MessageItemEditedProps, MessageItemEmbedded, type MessageItemEmbeddedProps, MessageItemFooter, type MessageItemFooterProps, MessageItemGutter, type MessageItemGutterProps, MessageItemHeader, type MessageItemHeaderProps, MessageItemInlineStatus, type MessageItemInlineStatusProps, MessageItemMeta, type MessageItemMetaProps, type MessageItemProps, MessageItemReadReceipt, type MessageItemReadReceiptProps, MessageItemSavedIndicator, type MessageItemSavedIndicatorProps, MessageItemSearchMatch, type MessageItemSearchMatchProps, MessageItemSender, MessageItemSenderBadges, type MessageItemSenderBadgesProps, MessageItemSenderButton, type MessageItemSenderButtonProps, MessageItemSenderGroup, type MessageItemSenderGroupProps, type MessageItemSenderProps, MessageItemTime, type MessageItemTimeProps, MessageItemToolbar, MessageItemToolbarButton, type MessageItemToolbarButtonProps, type MessageItemToolbarProps, MessageItemTrailing, type MessageItemTrailingProps, MessageMultiSelect, MessageMultiSelectCheckbox, type MessageMultiSelectCheckboxProps, type MessageMultiSelectProps, MessageMultiSelectToolbar, MessageMultiSelectToolbarActions, type MessageMultiSelectToolbarActionsProps, type MessageMultiSelectToolbarProps, MessageReactionAddButton, type MessageReactionAddButtonProps, MessageReactionChip, type MessageReactionChipProps, MessageReactionCount, type MessageReactionCountProps, MessageReactionErrorIndicator, type MessageReactionErrorIndicatorProps, MessageReactionGlyph, type MessageReactionGlyphProps, MessageReactionPickerContent, type MessageReactionPickerContentProps, MessageReactionPickerStatic, type MessageReactionPickerStaticProps, MessageReactionQuickButton, type MessageReactionQuickButtonProps, MessageReactionQuickRow, type MessageReactionQuickRowProps, MessageReactionTooltipContent, type MessageReactionTooltipContentProps, MessageReactionTooltipMeta, type MessageReactionTooltipMetaProps, MessageReactionTooltipName, type MessageReactionTooltipNameProps, MessageReactionTooltipNameText, type MessageReactionTooltipNameTextProps, MessageReactionTooltipNames, type MessageReactionTooltipNamesProps, MessageReactionTooltipSeparator, type MessageReactionTooltipSeparatorProps, MessageReferenceChip, type MessageReferenceChipProps, type MessageReferenceChipVariant, MessageReferenceIcon, type MessageReferenceIconProps, MessageReferenceIndicator, type MessageReferenceIndicatorProps, MessageReferenceLabel, type MessageReferenceLabelProps, MessageReferencePending, type MessageReferencePendingProps, MessageReferenceReadMark, type MessageReferenceReadMarkProps, MessageReferenceSuffix, type MessageReferenceSuffixProps, MessageReferenceText, type MessageReferenceTextProps, type MessageReferenceTextVariant, MessageReferenceUnavailable, type MessageReferenceUnavailableProps };
|
|
@@ -19,4 +19,18 @@ export type MessageItemAttachmentsProps = useRender.ComponentProps<"div">;
|
|
|
19
19
|
export declare function MessageItemAttachments({ className, render, ...props }: MessageItemAttachmentsProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
20
20
|
export type MessageItemFooterProps = useRender.ComponentProps<"div">;
|
|
21
21
|
export declare function MessageItemFooter({ className, render, ...props }: MessageItemFooterProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
22
|
+
export type MessageItemTrailingProps = useRender.ComponentProps<"span">;
|
|
23
|
+
/**
|
|
24
|
+
* Something small that ends the message (the faces of the agents that read it,
|
|
25
|
+
* a read mark): the last child of `MessageItemBody`. It takes no column: it sits
|
|
26
|
+
* at the inline end of the body's last line, and the last line keeps room for it,
|
|
27
|
+
* so the text wraps under it only when that line is full. When the body ends with
|
|
28
|
+
* a block that isn't text (a code block, a table, an image), it sits on a line of
|
|
29
|
+
* its own under that block. Logical properties, so it is right in RTL too.
|
|
30
|
+
*
|
|
31
|
+
* It finds the body's last block itself and stamps it (`data-trailing-line`, or
|
|
32
|
+
* `data-trailing="block"` on the body), so the CSS needs no structural selector,
|
|
33
|
+
* and one shared ResizeObserver sets the room (`--message-trailing-width`).
|
|
34
|
+
*/
|
|
35
|
+
export declare function MessageItemTrailing({ className, render, ref, ...props }: MessageItemTrailingProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
22
36
|
//#endregion
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { messageItem } from "./message-item.recipe.mjs";
|
|
2
|
+
import { useCallback, useLayoutEffect, useRef } from "react";
|
|
2
3
|
import { mergeProps } from "@base-ui/react/merge-props";
|
|
3
4
|
import { useRender } from "@base-ui/react/use-render";
|
|
4
5
|
//#region src/components/message-item/message-item-content.tsx
|
|
@@ -77,5 +78,149 @@ function MessageItemFooter({ className, render, ...props }) {
|
|
|
77
78
|
state: { slot: "message-item-footer" }
|
|
78
79
|
});
|
|
79
80
|
}
|
|
81
|
+
/** The space kept before a trailing slot on the body's last line. */
|
|
82
|
+
const TRAILING_GAP_PX = 8;
|
|
83
|
+
const BODY_SELECTOR = "[data-slot=\"message-item-body\"]";
|
|
84
|
+
const TEXT_BLOCKS = /* @__PURE__ */ new Set([
|
|
85
|
+
"P",
|
|
86
|
+
"H1",
|
|
87
|
+
"H2",
|
|
88
|
+
"H3",
|
|
89
|
+
"H4",
|
|
90
|
+
"H5",
|
|
91
|
+
"H6",
|
|
92
|
+
"SPAN"
|
|
93
|
+
]);
|
|
94
|
+
const BLOCKS = /* @__PURE__ */ new Set([
|
|
95
|
+
...TEXT_BLOCKS,
|
|
96
|
+
"UL",
|
|
97
|
+
"OL",
|
|
98
|
+
"BLOCKQUOTE",
|
|
99
|
+
"PRE",
|
|
100
|
+
"TABLE",
|
|
101
|
+
"DIV",
|
|
102
|
+
"FIGURE",
|
|
103
|
+
"IMG"
|
|
104
|
+
]);
|
|
105
|
+
const slotOfBody = /* @__PURE__ */ new WeakMap();
|
|
106
|
+
const pendingWidths = /* @__PURE__ */ new Map();
|
|
107
|
+
const pendingStamps = /* @__PURE__ */ new Map();
|
|
108
|
+
let frame = 0;
|
|
109
|
+
function flush() {
|
|
110
|
+
frame = 0;
|
|
111
|
+
for (const [body, width] of pendingWidths) body.style.setProperty("--message-trailing-width", `${Math.ceil(width) + TRAILING_GAP_PX}px`);
|
|
112
|
+
for (const [body, slot] of pendingStamps) if (body.contains(slot)) stampLastLine(body, slot);
|
|
113
|
+
pendingWidths.clear();
|
|
114
|
+
pendingStamps.clear();
|
|
115
|
+
}
|
|
116
|
+
let sharedObserver = null;
|
|
117
|
+
function trailingObserver() {
|
|
118
|
+
if (typeof ResizeObserver === "undefined") return null;
|
|
119
|
+
sharedObserver ??= new ResizeObserver((entries) => {
|
|
120
|
+
for (const entry of entries) {
|
|
121
|
+
const target = entry.target;
|
|
122
|
+
const slot = slotOfBody.get(target);
|
|
123
|
+
if (slot) {
|
|
124
|
+
pendingStamps.set(target, slot);
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
const body = target.closest(BODY_SELECTOR);
|
|
128
|
+
if (!body) continue;
|
|
129
|
+
const box = entry.borderBoxSize?.[0];
|
|
130
|
+
pendingWidths.set(body, box ? box.inlineSize : entry.contentRect.width);
|
|
131
|
+
}
|
|
132
|
+
if (!frame) frame = requestAnimationFrame(flush);
|
|
133
|
+
});
|
|
134
|
+
return sharedObserver;
|
|
135
|
+
}
|
|
136
|
+
/** Marks the text block the slot ends (`data-trailing-line`), or the body as ending in a block. */
|
|
137
|
+
function stampLastLine(body, slot) {
|
|
138
|
+
const block = lastBlock(body, slot);
|
|
139
|
+
const line = block ? lastLine(block) : null;
|
|
140
|
+
const previous = body.querySelector("[data-trailing-line]");
|
|
141
|
+
if (previous && previous !== line) previous.removeAttribute("data-trailing-line");
|
|
142
|
+
if (line && !line.hasAttribute("data-trailing-line")) line.setAttribute("data-trailing-line", "");
|
|
143
|
+
const ending = line ? "line" : "block";
|
|
144
|
+
if (body.dataset.trailing !== ending) body.dataset.trailing = ending;
|
|
145
|
+
}
|
|
146
|
+
/** The body's last block before the slot, through wrappers that only hold blocks (a markdown root). */
|
|
147
|
+
function lastBlock(body, slot) {
|
|
148
|
+
let el = slot.previousElementSibling;
|
|
149
|
+
while (el && !BLOCKS.has(el.tagName)) el = el.previousElementSibling;
|
|
150
|
+
while (el && el.tagName === "DIV" && !el.hasAttribute("data-slot") && el.lastElementChild && BLOCKS.has(el.lastElementChild.tagName)) el = el.lastElementChild;
|
|
151
|
+
return el && body.contains(el) ? el : null;
|
|
152
|
+
}
|
|
153
|
+
/** The text block that ends a last block, or null when it ends with something else. */
|
|
154
|
+
function lastLine(block) {
|
|
155
|
+
if (TEXT_BLOCKS.has(block.tagName)) return block;
|
|
156
|
+
if (block.tagName === "UL" || block.tagName === "OL") {
|
|
157
|
+
const item = block.lastElementChild;
|
|
158
|
+
if (!item || item.tagName !== "LI") return null;
|
|
159
|
+
const inner = item.lastElementChild;
|
|
160
|
+
if (inner && inner.tagName === "P") return inner;
|
|
161
|
+
return inner && BLOCKS.has(inner.tagName) ? null : item;
|
|
162
|
+
}
|
|
163
|
+
if (block.tagName === "BLOCKQUOTE") {
|
|
164
|
+
const inner = block.lastElementChild;
|
|
165
|
+
return inner && inner.tagName === "P" ? inner : null;
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Something small that ends the message (the faces of the agents that read it,
|
|
171
|
+
* a read mark): the last child of `MessageItemBody`. It takes no column: it sits
|
|
172
|
+
* at the inline end of the body's last line, and the last line keeps room for it,
|
|
173
|
+
* so the text wraps under it only when that line is full. When the body ends with
|
|
174
|
+
* a block that isn't text (a code block, a table, an image), it sits on a line of
|
|
175
|
+
* its own under that block. Logical properties, so it is right in RTL too.
|
|
176
|
+
*
|
|
177
|
+
* It finds the body's last block itself and stamps it (`data-trailing-line`, or
|
|
178
|
+
* `data-trailing="block"` on the body), so the CSS needs no structural selector,
|
|
179
|
+
* and one shared ResizeObserver sets the room (`--message-trailing-width`).
|
|
180
|
+
*/
|
|
181
|
+
function MessageItemTrailing({ className, render, ref, ...props }) {
|
|
182
|
+
const { trailing } = messageItem();
|
|
183
|
+
const own = useRef(null);
|
|
184
|
+
useLayoutEffect(() => {
|
|
185
|
+
const slot = own.current;
|
|
186
|
+
const body = slot?.closest(BODY_SELECTOR);
|
|
187
|
+
if (slot && body) stampLastLine(body, slot);
|
|
188
|
+
});
|
|
189
|
+
useLayoutEffect(() => {
|
|
190
|
+
const slot = own.current;
|
|
191
|
+
const body = slot?.closest(BODY_SELECTOR);
|
|
192
|
+
const observer = trailingObserver();
|
|
193
|
+
if (slot && observer) observer.observe(slot);
|
|
194
|
+
if (slot && body && observer) {
|
|
195
|
+
slotOfBody.set(body, slot);
|
|
196
|
+
observer.observe(body);
|
|
197
|
+
}
|
|
198
|
+
return () => {
|
|
199
|
+
if (slot && observer) observer.unobserve(slot);
|
|
200
|
+
if (body) {
|
|
201
|
+
if (observer) observer.unobserve(body);
|
|
202
|
+
slotOfBody.delete(body);
|
|
203
|
+
body.querySelector("[data-trailing-line]")?.removeAttribute("data-trailing-line");
|
|
204
|
+
delete body.dataset.trailing;
|
|
205
|
+
body.style.removeProperty("--message-trailing-width");
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}, []);
|
|
209
|
+
const setRef = useCallback((el) => {
|
|
210
|
+
own.current = el;
|
|
211
|
+
if (typeof ref === "function") ref(el);
|
|
212
|
+
else if (ref) ref.current = el;
|
|
213
|
+
}, [ref]);
|
|
214
|
+
const defaultProps = {
|
|
215
|
+
className: trailing({ className }),
|
|
216
|
+
ref: setRef
|
|
217
|
+
};
|
|
218
|
+
return useRender({
|
|
219
|
+
defaultTagName: "span",
|
|
220
|
+
render,
|
|
221
|
+
props: mergeProps(defaultProps, props),
|
|
222
|
+
state: { slot: "message-item-trailing" }
|
|
223
|
+
});
|
|
224
|
+
}
|
|
80
225
|
//#endregion
|
|
81
|
-
export { MessageItemAttachments, MessageItemBody, MessageItemContent, MessageItemEdited, MessageItemEmbedded, MessageItemFooter, MessageItemSearchMatch };
|
|
226
|
+
export { MessageItemAttachments, MessageItemBody, MessageItemContent, MessageItemEdited, MessageItemEmbedded, MessageItemFooter, MessageItemSearchMatch, MessageItemTrailing };
|
|
@@ -25,6 +25,7 @@ export declare const messageItem: import("tailwind-variants/lite").TVReturnType<
|
|
|
25
25
|
delegatedByButton: string[];
|
|
26
26
|
delegatedAvatar: string[];
|
|
27
27
|
edited: string[];
|
|
28
|
+
trailing: string[];
|
|
28
29
|
body: string[];
|
|
29
30
|
searchMatch: string[];
|
|
30
31
|
embedded: string[];
|
|
@@ -57,6 +58,7 @@ export declare const messageItem: import("tailwind-variants/lite").TVReturnType<
|
|
|
57
58
|
delegatedByButton: string[];
|
|
58
59
|
delegatedAvatar: string[];
|
|
59
60
|
edited: string[];
|
|
61
|
+
trailing: string[];
|
|
60
62
|
body: string[];
|
|
61
63
|
searchMatch: string[];
|
|
62
64
|
embedded: string[];
|
|
@@ -89,6 +91,7 @@ export declare const messageItem: import("tailwind-variants/lite").TVReturnType<
|
|
|
89
91
|
delegatedByButton: string[];
|
|
90
92
|
delegatedAvatar: string[];
|
|
91
93
|
edited: string[];
|
|
94
|
+
trailing: string[];
|
|
92
95
|
body: string[];
|
|
93
96
|
searchMatch: string[];
|
|
94
97
|
embedded: string[];
|
|
@@ -81,6 +81,7 @@ const messageItem = tv({
|
|
|
81
81
|
"dark:shadow-[0_0_0_3px_var(--mi-row-fill,transparent),0_0_0_3px_var(--layer-canvas)]"
|
|
82
82
|
],
|
|
83
83
|
edited: ["ms-1 whitespace-nowrap", "text-caption text-foreground-hint"],
|
|
84
|
+
trailing: ["absolute end-0 bottom-0 z-10 flex h-lh items-center", "select-none! **:select-none!"],
|
|
84
85
|
body: [
|
|
85
86
|
"wrap-break-word select-text",
|
|
86
87
|
"**:select-text",
|
|
@@ -95,13 +96,13 @@ const messageItem = tv({
|
|
|
95
96
|
"absolute z-20 flex items-center",
|
|
96
97
|
"opacity-(--mi-toolbar-opacity,0)",
|
|
97
98
|
"[pointer-events:var(--mi-toolbar-pe,none)]",
|
|
98
|
-
"top-[-18px] right-3 gap-1 overflow-visible rounded-container p-1",
|
|
99
|
+
"top-[-18px] md:pointer-fine:top-[calc(-1*(var(--control-height)+8px)/2)] right-3 gap-1 overflow-visible rounded-container p-1",
|
|
99
100
|
"bg-layer-popover ring-1 ring-line-seam ring-inset shadow-float"
|
|
100
101
|
],
|
|
101
102
|
toolbarButton: [
|
|
102
103
|
"inline-flex shrink-0 items-center justify-center",
|
|
103
104
|
"[&_svg]:shrink-0",
|
|
104
|
-
"size-7 rounded-chip border-0 bg-transparent p-0",
|
|
105
|
+
"size-7 rounded-chip md:pointer-fine:size-control md:pointer-fine:rounded-control border-0 bg-transparent p-0",
|
|
105
106
|
"text-foreground-muted hover:bg-fill-medium active:bg-fill-medium",
|
|
106
107
|
"data-popup-open:bg-fill-medium data-active:text-foreground",
|
|
107
108
|
"outline-none focus-visible:shadow-focus",
|
|
@@ -45,20 +45,21 @@ const messageReaction = tv({ slots: {
|
|
|
45
45
|
],
|
|
46
46
|
quickRow: [
|
|
47
47
|
"flex shrink-0 items-center",
|
|
48
|
-
"justify-
|
|
49
|
-
"[&>[role=menuitem]]:size-9 [&>[role=menuitem]]:p-0 *:[[role=menuitem]]:justify-center"
|
|
48
|
+
"justify-start gap-0.5 bg-layer-popover p-0",
|
|
49
|
+
"[&>[role=menuitem]]:size-9 md:pointer-fine:[&>[role=menuitem]]:size-control [&>[role=menuitem]]:p-0 *:[[role=menuitem]]:justify-center"
|
|
50
50
|
],
|
|
51
51
|
quickButton: [
|
|
52
52
|
"flex items-center justify-center",
|
|
53
53
|
"bg-transparent transition-colors",
|
|
54
54
|
"size-9 rounded-chip p-0 text-xl leading-none text-foreground-muted",
|
|
55
|
+
"md:pointer-fine:size-control md:pointer-fine:rounded-control",
|
|
55
56
|
"hover:bg-brand-soft data-highlighted:bg-brand-soft active:bg-brand-soft",
|
|
56
57
|
"outline-none focus-visible:shadow-focus"
|
|
57
58
|
],
|
|
58
59
|
pickerContent: [
|
|
59
60
|
"inline-flex items-center",
|
|
60
61
|
"min-w-0 flex-row gap-0.5 p-1",
|
|
61
|
-
"[&>[role=menuitem]]:size-9 [&>[role=menuitem]]:p-0"
|
|
62
|
+
"[&>[role=menuitem]]:size-9 md:pointer-fine:[&>[role=menuitem]]:size-control [&>[role=menuitem]]:p-0"
|
|
62
63
|
],
|
|
63
64
|
pickerStatic: [
|
|
64
65
|
"inline-flex items-center",
|
|
@@ -41,7 +41,9 @@ const messageListJump = tv({
|
|
|
41
41
|
"rounded-s-none border-s-0",
|
|
42
42
|
"text-foreground-muted hover:text-foreground",
|
|
43
43
|
"[&_svg:not([class*='size-'])]:size-4",
|
|
44
|
-
"after:-inset-y-[calc(--spacing(1.5)+1.5px)] after:right-[calc(-0.75rem-1.5px)] after:left-0"
|
|
44
|
+
"after:-inset-y-[calc(--spacing(1.5)+1.5px)] after:right-[calc(-0.75rem-1.5px)] after:left-0",
|
|
45
|
+
"md:pointer-fine:after:-inset-y-[calc(var(--control-hit-inset)+1.5px)]",
|
|
46
|
+
"md:pointer-fine:after:right-[calc(-2*var(--control-hit-inset)-1.5px)] md:pointer-fine:after:left-0"
|
|
45
47
|
]
|
|
46
48
|
},
|
|
47
49
|
variants: { side: {
|
|
@@ -15,7 +15,7 @@ import { useRender } from "@base-ui/react/use-render";
|
|
|
15
15
|
const modeBar = tv({ slots: {
|
|
16
16
|
root: [
|
|
17
17
|
"flex shrink-0 items-start",
|
|
18
|
-
"min-h-10 gap-4 px-
|
|
18
|
+
"min-h-10 gap-4 px-(--surface-inset) py-2.5 max-md:px-4",
|
|
19
19
|
"bg-layer-hud font-sans text-callout text-foreground-on-hud"
|
|
20
20
|
],
|
|
21
21
|
content: ["min-w-0 flex-1 wrap-break-word"],
|
|
@@ -46,7 +46,7 @@ const notificationCenter = tv({
|
|
|
46
46
|
itemRow: ["flex items-start", "gap-3"],
|
|
47
47
|
itemIcon: [
|
|
48
48
|
"flex shrink-0 items-center justify-center",
|
|
49
|
-
"mt-0 size-[35px] rounded-
|
|
49
|
+
"mt-0 size-[35px] rounded-control bg-fill-muted text-foreground-muted",
|
|
50
50
|
"[&_svg]:size-[18px]"
|
|
51
51
|
],
|
|
52
52
|
itemContent: ["min-w-0 flex-1"],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { barButtonHit, barIconInset } from "../../lib/head-edges.mjs";
|
|
2
2
|
import { tv } from "../../lib/tv.mjs";
|
|
3
3
|
//#region src/components/panel/panel-action.recipe.ts
|
|
4
4
|
const panelActionBase = tv({ base: [
|
|
@@ -6,14 +6,14 @@ const panelActionBase = tv({ base: [
|
|
|
6
6
|
"overflow-visible font-sans leading-none tabular-nums select-none outline-none",
|
|
7
7
|
"transition-all duration-100",
|
|
8
8
|
"[&>svg]:pointer-events-none [&>svg]:shrink-0",
|
|
9
|
-
"h-
|
|
10
|
-
"px-2 md:pointer-fine:px-[
|
|
11
|
-
|
|
9
|
+
"h-(--bar-button-size) min-w-(--bar-button-size) rounded-(--bar-button-radius) border-[1.5px] border-transparent bg-transparent py-0",
|
|
10
|
+
"px-2 md:pointer-fine:px-[calc((var(--bar-button-size)-var(--control-icon-size)-3px)/2)]",
|
|
11
|
+
barButtonHit,
|
|
12
12
|
"text-foreground",
|
|
13
13
|
"hover:bg-fill-medium active:bg-fill-medium",
|
|
14
14
|
"focus-visible:shadow-focus",
|
|
15
15
|
"[&>svg]:size-control-icon",
|
|
16
|
-
|
|
16
|
+
barIconInset
|
|
17
17
|
] });
|
|
18
18
|
const panelAction = tv({
|
|
19
19
|
extend: panelActionBase,
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { barIconInset, headEdges } from "../../lib/head-edges.mjs";
|
|
2
2
|
import { tv } from "../../lib/tv.mjs";
|
|
3
3
|
//#region src/components/panel/panel-header.recipe.ts
|
|
4
4
|
/**
|
|
5
5
|
* Where a head's edge controls sit, shared by every head (panel, section,
|
|
6
6
|
* drawer, thread): see lib/head-edges.ts. Both sides pad by the content
|
|
7
|
-
* margin
|
|
7
|
+
* margin (16px on a phone, 20px from 768px by touch, 16px with a mouse), so a filled thing (a sticker,
|
|
8
8
|
* a pill, a filled Button) puts its shape on it, and the first and last
|
|
9
9
|
* frameless icon button are pulled out by their icon inset so their icon box
|
|
10
|
-
* lands on it
|
|
11
|
-
* layout, 16px on a phone, mirrored at the two ends.
|
|
10
|
+
* lands on it, mirrored at the two ends.
|
|
12
11
|
*/
|
|
13
12
|
const panelHeadEdges = headEdges;
|
|
14
13
|
/**
|
|
@@ -17,10 +16,11 @@ const panelHeadEdges = headEdges;
|
|
|
17
16
|
* button: an action hidden at some width (a thread's Close below 1024px) then
|
|
18
17
|
* leaves the next one on the edge.
|
|
19
18
|
*/
|
|
20
|
-
const panelHeadActions = ["flex shrink-0 items-center gap-0.5 md:pointer-fine:gap-1",
|
|
19
|
+
const panelHeadActions = ["flex shrink-0 items-center gap-0.5 md:pointer-fine:gap-1", barIconInset];
|
|
21
20
|
/**
|
|
22
21
|
* `header` and `sectionHeader` share one bar, expressed through
|
|
23
|
-
* `compoundSlots`: a
|
|
22
|
+
* `compoundSlots`: a header-height row (the shell header height, 56px on a
|
|
23
|
+
* phone and 44px on a desktop) with a seam under it.
|
|
24
24
|
* On a phone the section head sits on the frame.
|
|
25
25
|
*/
|
|
26
26
|
const panelHeader = tv({
|
|
@@ -29,14 +29,15 @@ const panelHeader = tv({
|
|
|
29
29
|
sectionHeader: [],
|
|
30
30
|
headerIcon: [
|
|
31
31
|
"flex size-[27px] shrink-0 items-center justify-center",
|
|
32
|
+
"md:pointer-fine:size-(--bar-button-size) md:pointer-fine:rounded-(--bar-button-radius)",
|
|
32
33
|
"rounded-sticker border-[1.5px] border-sticker-ink bg-brand text-sticker-ink ring-[1.5px] ring-sticker-edge",
|
|
33
34
|
"not-data-[icon-kind=avatar]:[&_svg]:size-3.5 not-data-[icon-kind=avatar]:[&_svg]:stroke-2",
|
|
34
35
|
"data-[icon-kind=avatar]:size-auto data-[icon-kind=avatar]:border-transparent data-[icon-kind=avatar]:bg-transparent"
|
|
35
36
|
],
|
|
36
|
-
headerContent: "flex min-w-0 flex-1 flex-col justify-center",
|
|
37
|
+
headerContent: ["flex min-w-0 flex-1 flex-col justify-center", "md:pointer-fine:flex-row md:pointer-fine:items-baseline md:pointer-fine:justify-start md:pointer-fine:gap-2"],
|
|
37
38
|
heading: "flex min-w-0 items-center gap-2",
|
|
38
39
|
title: "truncate font-sans text-headline font-bold text-foreground",
|
|
39
|
-
meta: "min-w-0 truncate font-sans text-caption text-foreground-hint",
|
|
40
|
+
meta: ["min-w-0 truncate font-sans text-caption text-foreground-hint", "md:pointer-fine:flex-1 md:pointer-fine:shrink-1000"],
|
|
40
41
|
status: [
|
|
41
42
|
"inline-flex shrink-0 items-center gap-1 border-0 bg-transparent p-0",
|
|
42
43
|
"font-sans text-caption font-medium normal-case text-foreground-hint",
|
|
@@ -57,7 +58,7 @@ const panelHeader = tv({
|
|
|
57
58
|
compoundSlots: [{
|
|
58
59
|
slots: ["header", "sectionHeader"],
|
|
59
60
|
class: [
|
|
60
|
-
"flex h-(--shell-header-height,
|
|
61
|
+
"flex h-(--shell-header-height,var(--header-height)) shrink-0 items-center gap-3 max-md:gap-2",
|
|
61
62
|
panelHeadEdges,
|
|
62
63
|
"border-b border-line-seam bg-layer-canvas text-foreground",
|
|
63
64
|
"max-md:sticky max-md:top-0 max-md:z-30"
|
|
@@ -3,11 +3,11 @@ import { tv } from "../../lib/tv.mjs";
|
|
|
3
3
|
const panel = tv({
|
|
4
4
|
slots: {
|
|
5
5
|
root: ["[--panel-footer-clearance:10rem]", "bg-layer-canvas text-foreground"],
|
|
6
|
-
header: ["[@media(max-height:600px)]:h-
|
|
6
|
+
header: ["[@media(max-height:600px)]:h-(--header-height-short)"],
|
|
7
7
|
body: ["relative min-h-0 flex-1 overflow-hidden"],
|
|
8
8
|
scrollViewport: ["h-full min-h-0 overflow-y-auto overscroll-contain", "[overflow-anchor:auto] [-webkit-overflow-scrolling:touch]"],
|
|
9
9
|
scrollContent: ["min-h-full"],
|
|
10
|
-
section: ["border-t px-
|
|
10
|
+
section: ["border-t px-(--surface-inset) py-4", "border-line-hairline"],
|
|
11
11
|
footer: [
|
|
12
12
|
"relative flex shrink-0 items-center pt-3",
|
|
13
13
|
"bg-layer-canvas",
|
|
@@ -4,7 +4,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
4
4
|
import { Button } from "@base-ui/react/button";
|
|
5
5
|
//#region src/components/picker-trigger-button/picker-trigger-button.tsx
|
|
6
6
|
const pickerTriggerButton = tv({ base: [
|
|
7
|
-
"relative inline-flex h-8 shrink-0 items-center justify-center",
|
|
7
|
+
"relative inline-flex h-8 md:pointer-fine:h-control shrink-0 items-center justify-center",
|
|
8
8
|
"whitespace-nowrap select-none",
|
|
9
9
|
"outline-[1px] outline-offset-2 outline-transparent transition-colors duration-100 focus-visible:outline-transparent",
|
|
10
10
|
"disabled:pointer-events-none disabled:transform-none",
|
|
@@ -587,10 +587,7 @@
|
|
|
587
587
|
block-size var(--r-scroll-area-duration) var(--r-scroll-area-easing);
|
|
588
588
|
}
|
|
589
589
|
|
|
590
|
-
/* Shown
|
|
591
|
-
.r-scroll-area.r-scroll-area--hover-trigger:hover
|
|
592
|
-
> .r-scroll-area__gutters
|
|
593
|
-
> .r-scroll-area__gutter,
|
|
590
|
+
/* Shown always (trigger="none"), and while scrolling or dragging (every trigger). */
|
|
594
591
|
.r-scroll-area.r-scroll-area--none-trigger > .r-scroll-area__gutters > .r-scroll-area__gutter,
|
|
595
592
|
.r-scroll-area
|
|
596
593
|
> .r-scroll-area__gutters.r-scroll-area__gutters--scrolling
|
|
@@ -602,31 +599,7 @@
|
|
|
602
599
|
transition-duration: var(--r-scroll-area-duration-fade-in);
|
|
603
600
|
}
|
|
604
601
|
|
|
605
|
-
/*
|
|
606
|
-
* trigger="scroll": a hidden gutter doesn't catch presses meant for the
|
|
607
|
-
* content under it. A gutter the pointer is already on (it was shown by
|
|
608
|
-
* scrolling) stays visible and usable after `hideDelay`, until the pointer
|
|
609
|
-
* leaves it; a hidden gutter can't become hovered, so it never shows on hover.
|
|
610
|
-
*/
|
|
611
|
-
.r-scroll-area.r-scroll-area--scroll-trigger
|
|
612
|
-
> .r-scroll-area__gutters
|
|
613
|
-
> .r-scroll-area__gutter:hover {
|
|
614
|
-
opacity: 1;
|
|
615
|
-
transition-duration: var(--r-scroll-area-duration-fade-in);
|
|
616
|
-
}
|
|
617
|
-
.r-scroll-area.r-scroll-area--scroll-trigger
|
|
618
|
-
> .r-scroll-area__gutters:not(.r-scroll-area__gutters--scrolling):not(
|
|
619
|
-
.r-scroll-area__gutters--dragging
|
|
620
|
-
)
|
|
621
|
-
> .r-scroll-area__gutter:not(:hover) {
|
|
622
|
-
pointer-events: none;
|
|
623
|
-
}
|
|
624
|
-
|
|
625
|
-
/* Pointed at, or while dragged: the thumb thickens and darkens. */
|
|
626
|
-
.r-scroll-area
|
|
627
|
-
> .r-scroll-area__gutters
|
|
628
|
-
> .r-scroll-area__gutter--vertical:hover
|
|
629
|
-
> .r-scroll-area__thumb,
|
|
602
|
+
/* While dragged: the thumb thickens and darkens. */
|
|
630
603
|
.r-scroll-area
|
|
631
604
|
> .r-scroll-area__gutters
|
|
632
605
|
> .r-scroll-area__gutter--vertical.r-scroll-area__gutter--dragging
|
|
@@ -634,10 +607,6 @@
|
|
|
634
607
|
background: var(--r-scroll-area-thumb-color-hover);
|
|
635
608
|
inline-size: var(--r-scroll-area-thumb-size-hover);
|
|
636
609
|
}
|
|
637
|
-
.r-scroll-area
|
|
638
|
-
> .r-scroll-area__gutters
|
|
639
|
-
> .r-scroll-area__gutter--horizontal:hover
|
|
640
|
-
> .r-scroll-area__thumb,
|
|
641
610
|
.r-scroll-area
|
|
642
611
|
> .r-scroll-area__gutters
|
|
643
612
|
> .r-scroll-area__gutter--horizontal.r-scroll-area__gutter--dragging
|
|
@@ -646,6 +615,78 @@
|
|
|
646
615
|
block-size: var(--r-scroll-area-thumb-size-hover);
|
|
647
616
|
}
|
|
648
617
|
|
|
618
|
+
/*
|
|
619
|
+
* Hover only with a pointer that hovers (design/foundations/states.md): on a
|
|
620
|
+
* touch screen the last thing tapped stays `:hover`, which would leave the
|
|
621
|
+
* scrollbars shown, the thumb thick and a hidden gutter catching taps.
|
|
622
|
+
*/
|
|
623
|
+
@media (hover: hover) {
|
|
624
|
+
/* trigger="hover": shown while the pointer is over the area. */
|
|
625
|
+
.r-scroll-area.r-scroll-area--hover-trigger:hover
|
|
626
|
+
> .r-scroll-area__gutters
|
|
627
|
+
> .r-scroll-area__gutter {
|
|
628
|
+
opacity: 1;
|
|
629
|
+
transition-duration: var(--r-scroll-area-duration-fade-in);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/*
|
|
633
|
+
* trigger="scroll": a hidden gutter doesn't catch presses meant for the
|
|
634
|
+
* content under it. A gutter the pointer is already on (it was shown by
|
|
635
|
+
* scrolling) stays visible and usable after `hideDelay`, until the pointer
|
|
636
|
+
* leaves it; a hidden gutter can't become hovered, so it never shows on hover.
|
|
637
|
+
*/
|
|
638
|
+
.r-scroll-area.r-scroll-area--scroll-trigger
|
|
639
|
+
> .r-scroll-area__gutters
|
|
640
|
+
> .r-scroll-area__gutter:hover {
|
|
641
|
+
opacity: 1;
|
|
642
|
+
transition-duration: var(--r-scroll-area-duration-fade-in);
|
|
643
|
+
}
|
|
644
|
+
.r-scroll-area.r-scroll-area--scroll-trigger
|
|
645
|
+
> .r-scroll-area__gutters:not(.r-scroll-area__gutters--scrolling):not(
|
|
646
|
+
.r-scroll-area__gutters--dragging
|
|
647
|
+
)
|
|
648
|
+
> .r-scroll-area__gutter:not(:hover) {
|
|
649
|
+
pointer-events: none;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/* Pointed at: the thumb thickens and darkens, as while dragged. */
|
|
653
|
+
.r-scroll-area
|
|
654
|
+
> .r-scroll-area__gutters
|
|
655
|
+
> .r-scroll-area__gutter--vertical:hover
|
|
656
|
+
> .r-scroll-area__thumb {
|
|
657
|
+
background: var(--r-scroll-area-thumb-color-hover);
|
|
658
|
+
inline-size: var(--r-scroll-area-thumb-size-hover);
|
|
659
|
+
}
|
|
660
|
+
.r-scroll-area
|
|
661
|
+
> .r-scroll-area__gutters
|
|
662
|
+
> .r-scroll-area__gutter--horizontal:hover
|
|
663
|
+
> .r-scroll-area__thumb {
|
|
664
|
+
background: var(--r-scroll-area-thumb-color-hover);
|
|
665
|
+
block-size: var(--r-scroll-area-thumb-size-hover);
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/*
|
|
670
|
+
* Where nothing hovers, trigger="hover" and "scroll" both show the scrollbars
|
|
671
|
+
* only while the area scrolls or a thumb is dragged, and a hidden gutter
|
|
672
|
+
* never catches a tap: it goes to the content under it. A scrollbar shown by
|
|
673
|
+
* scrolling takes the finger, so its thumb can be dragged; the drag keeps it.
|
|
674
|
+
*/
|
|
675
|
+
@media (hover: none) {
|
|
676
|
+
.r-scroll-area.r-scroll-area--hover-trigger
|
|
677
|
+
> .r-scroll-area__gutters:not(.r-scroll-area__gutters--scrolling):not(
|
|
678
|
+
.r-scroll-area__gutters--dragging
|
|
679
|
+
)
|
|
680
|
+
> .r-scroll-area__gutter,
|
|
681
|
+
.r-scroll-area.r-scroll-area--scroll-trigger
|
|
682
|
+
> .r-scroll-area__gutters:not(.r-scroll-area__gutters--scrolling):not(
|
|
683
|
+
.r-scroll-area__gutters--dragging
|
|
684
|
+
)
|
|
685
|
+
> .r-scroll-area__gutter {
|
|
686
|
+
pointer-events: none;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
|
649
690
|
/*
|
|
650
691
|
* Scroll-driven thumbs: the browser moves each thumb from the scroll itself,
|
|
651
692
|
* on the compositor, with no script per scroll. The container names its
|
|
@@ -5,7 +5,8 @@ const searchEntity = tv({ slots: {
|
|
|
5
5
|
entity: [
|
|
6
6
|
"flex min-w-0 w-full items-center gap-3 text-left",
|
|
7
7
|
"rounded-none border-0 py-3 text-foreground",
|
|
8
|
-
"pointer-
|
|
8
|
+
"md:pointer-fine:py-2",
|
|
9
|
+
"pointer-coarse:min-h-14 pointer-coarse:py-2",
|
|
9
10
|
listCell,
|
|
10
11
|
listCellStates,
|
|
11
12
|
"disabled:cursor-default",
|
|
@@ -15,7 +16,7 @@ const searchEntity = tv({ slots: {
|
|
|
15
16
|
entityLeading: ["relative flex shrink-0"],
|
|
16
17
|
entityIcon: [
|
|
17
18
|
"flex items-center justify-center overflow-hidden",
|
|
18
|
-
"size-[27px] rounded-
|
|
19
|
+
"size-[27px] rounded-chip bg-fill-muted text-foreground-muted",
|
|
19
20
|
"[&_svg]:size-3.5"
|
|
20
21
|
],
|
|
21
22
|
entityActivity: [
|