@mcp-b/react-components 0.5.4 → 0.5.5

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.
@@ -30,6 +30,8 @@ interface AgentChatProps<MessageT extends UIMessage = UIMessage> {
30
30
  emptyState?: React.ReactNode;
31
31
  /** Extra controls rendered in the composer toolbar. */
32
32
  composerTools?: React.ReactNode;
33
+ /** Extra rows rendered in the built-in plus menu after files. */
34
+ composerAddMenuItems?: React.ReactNode;
33
35
  /**
34
36
  * Transient status rendered between the transcript and the composer —
35
37
  * e.g. a "Reconnecting…" pill. `ThinkChat.Messages` fills this from the
@@ -86,6 +88,7 @@ declare function AgentChat<MessageT extends UIMessage = UIMessage>({
86
88
  disabled,
87
89
  emptyState,
88
90
  composerTools,
91
+ composerAddMenuItems,
89
92
  notice,
90
93
  onRegenerate,
91
94
  onApprovalResponse,
@@ -4,7 +4,7 @@ import { Activity, ActivityContent, ActivityPanel, ActivityTrigger } from "./Act
4
4
  import { Context, ContextContent, ContextContentBody, ContextContentHeader, ContextTrigger, getContextUsage, getContextUsedTokens } from "./Context.js";
5
5
  import { Conversation, ConversationContent, ConversationEmptyState, ConversationScrollButton } from "./Conversation.js";
6
6
  import { Message, MessageAction, MessageActions, MessageAttachment, MessageContent, MessageResponse } from "./Message.js";
7
- import { PromptInput, PromptInputApproval, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputFooter, PromptInputPermissionSelector, PromptInputSubmit, PromptInputTextarea, PromptInputTools, getApprovalRequestId, getPendingToolApprovals, usePromptInputAttachments } from "./PromptInput.js";
7
+ import { PromptInput, PromptInputActionAddAttachments, PromptInputActionMenu, PromptInputActionMenuContent, PromptInputActionMenuTrigger, PromptInputApproval, PromptInputAttachments, PromptInputBody, PromptInputButton, PromptInputFooter, PromptInputPermissionSelector, PromptInputSubmit, PromptInputTextarea, PromptInputTools, getApprovalRequestId, getPendingToolApprovals, usePromptInputAttachments } from "./PromptInput.js";
8
8
  import { Reasoning, ReasoningContent, ReasoningTrigger } from "./Reasoning.js";
9
9
  import * as React from "react";
10
10
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
@@ -18,6 +18,17 @@ function AgentChatAttachButton() {
18
18
  children: /* @__PURE__ */ jsx(PlusIcon, {})
19
19
  });
20
20
  }
21
+ function AgentChatAddMenu({ children }) {
22
+ if (!children) return /* @__PURE__ */ jsx(AgentChatAttachButton, {});
23
+ return /* @__PURE__ */ jsxs(PromptInputActionMenu, { children: [/* @__PURE__ */ jsx(PromptInputActionMenuTrigger, { "aria-label": "Add context" }), /* @__PURE__ */ jsxs(PromptInputActionMenuContent, {
24
+ side: "top",
25
+ align: "start",
26
+ sideOffset: 12,
27
+ collisionPadding: 8,
28
+ className: "agent-chat__add-menu",
29
+ children: [/* @__PURE__ */ jsx(PromptInputActionAddAttachments, {}), children]
30
+ })] });
31
+ }
21
32
  function isCompactedPart(message, part, partIndex) {
22
33
  const metadata = message.metadata;
23
34
  if (isTextUIPart(part)) return Array.isArray(metadata?.compactedTextParts) && metadata.compactedTextParts.includes(partIndex);
@@ -88,7 +99,7 @@ function renderDefaultPart(part) {
88
99
  * transport. Use it directly with plain AI SDK `useChat` or a read-only
89
100
  * transcript; if you have a Cloudflare Think agent, use `ThinkChat` instead.
90
101
  */
91
- function AgentChat({ className, messages, status = "ready", onSubmit, onStop, placeholder = "Ask anything...", disabled, emptyState, composerTools, notice, onRegenerate, onApprovalResponse, executionApprovals, contextWindow, renderPart, renderMessageAfter, ref }) {
102
+ function AgentChat({ className, messages, status = "ready", onSubmit, onStop, placeholder = "Ask anything...", disabled, emptyState, composerTools, composerAddMenuItems, notice, onRegenerate, onApprovalResponse, executionApprovals, contextWindow, renderPart, renderMessageAfter, ref }) {
92
103
  const handleSubmit = React.useCallback((message) => {
93
104
  onSubmit?.(message);
94
105
  }, [onSubmit]);
@@ -194,7 +205,7 @@ function AgentChat({ className, messages, status = "ready", onSubmit, onStop, pl
194
205
  disabled
195
206
  }) }),
196
207
  /* @__PURE__ */ jsxs(PromptInputFooter, { children: [/* @__PURE__ */ jsxs(PromptInputTools, { children: [
197
- /* @__PURE__ */ jsx(AgentChatAttachButton, {}),
208
+ /* @__PURE__ */ jsx(AgentChatAddMenu, { children: composerAddMenuItems }),
198
209
  approvalsWired ? /* @__PURE__ */ jsx(PromptInputPermissionSelector, {
199
210
  value: permissionMode,
200
211
  onValueChange: setPermissionMode
@@ -21,6 +21,7 @@ interface McpServerPickerProps {
21
21
  /** Offset from the plus trigger to the menu, useful for prompt composers. */
22
22
  sideOffset?: number;
23
23
  }
24
+ type McpServerPickerItemsProps = Pick<McpServerPickerProps, "servers" | "onConnect">;
24
25
  /**
25
26
  * Prompt plus-menu picker for choosing an MCP server and handing connection
26
27
  * work back to the host app.
@@ -30,5 +31,9 @@ declare function McpServerPicker({
30
31
  onConnect,
31
32
  sideOffset
32
33
  }: McpServerPickerProps): React.JSX.Element;
34
+ declare function McpServerPickerItems({
35
+ servers,
36
+ onConnect
37
+ }: McpServerPickerItemsProps): React.JSX.Element | React.JSX.Element[];
33
38
  //#endregion
34
- export { McpServerCard, McpServerPicker, McpServerPickerProps, McpServerPickerStatus };
39
+ export { McpServerCard, McpServerPicker, McpServerPickerItems, McpServerPickerItemsProps, McpServerPickerProps, McpServerPickerStatus };
@@ -9,8 +9,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
9
  * work back to the host app.
10
10
  */
11
11
  function McpServerPicker({ servers, onConnect, sideOffset = 80 }) {
12
- const groups = groupServers(servers);
13
- const showHeadings = groups.some((group) => group.category);
14
12
  return /* @__PURE__ */ jsx("div", {
15
13
  className: "mcp-server-picker",
16
14
  children: /* @__PURE__ */ jsxs(MenuRoot, { children: [/* @__PURE__ */ jsx(MenuTrigger, { render: /* @__PURE__ */ jsx(Button, {
@@ -28,20 +26,29 @@ function McpServerPicker({ servers, onConnect, sideOffset = 80 }) {
28
26
  collisionPadding: 8,
29
27
  "aria-label": "MCP servers",
30
28
  className: "mcp-server-picker__popup",
31
- children: servers.length === 0 ? /* @__PURE__ */ jsx(MenuItem, {
32
- disabled: true,
33
- className: "mcp-server-picker__empty",
34
- children: "No MCP servers available."
35
- }) : groups.map((group) => /* @__PURE__ */ jsxs(MenuGroup, {
36
- className: "mcp-server-picker__group",
37
- children: [showHeadings ? /* @__PURE__ */ jsx(MenuGroupLabel, { children: group.category || "Servers" }) : null, group.servers.map((server) => /* @__PURE__ */ jsx(McpServerPickerRow, {
38
- server,
39
- onConnect
40
- }, server.id))]
41
- }, group.category))
29
+ children: /* @__PURE__ */ jsx(McpServerPickerItems, {
30
+ servers,
31
+ onConnect
32
+ })
42
33
  })] })
43
34
  });
44
35
  }
36
+ function McpServerPickerItems({ servers, onConnect }) {
37
+ const groups = groupServers(servers);
38
+ const showHeadings = groups.some((group) => group.category);
39
+ if (servers.length === 0) return /* @__PURE__ */ jsx(MenuItem, {
40
+ disabled: true,
41
+ className: "mcp-server-picker__empty",
42
+ children: "No MCP servers available."
43
+ });
44
+ return groups.map((group) => /* @__PURE__ */ jsxs(MenuGroup, {
45
+ className: "mcp-server-picker__group",
46
+ children: [showHeadings ? /* @__PURE__ */ jsx(MenuGroupLabel, { children: group.category || "Servers" }) : null, group.servers.map((server) => /* @__PURE__ */ jsx(McpServerPickerRow, {
47
+ server,
48
+ onConnect
49
+ }, server.id))]
50
+ }, group.category));
51
+ }
45
52
  function McpServerPickerRow({ server, onConnect }) {
46
53
  const descriptionId = React.useId();
47
54
  const statusText = server.statusLabel ?? getStatusLabel(server.status);
@@ -130,4 +137,4 @@ function groupServers(servers) {
130
137
  return groups;
131
138
  }
132
139
  //#endregion
133
- export { McpServerPicker };
140
+ export { McpServerPicker, McpServerPickerItems };
@@ -1,6 +1,6 @@
1
1
  import { A as SelectTriggerProps, M as SelectValueProps, S as SelectProps, f as SelectOption, j as SelectValue, r as SelectContentProps, s as SelectItemProps, t as Select } from "../Select-CRsKCJ9x.js";
2
2
  import { c as ComboboxGroup, d as ComboboxLabel, f as ComboboxList, g as ComboboxTrigger, h as ComboboxSeparator, l as ComboboxInput, m as ComboboxPositioner, p as ComboboxPopup, s as ComboboxEmpty, t as Combobox, u as ComboboxItem } from "../Combobox-D9anamNr.js";
3
- import { h as MenuItemProps, w as MenuProps, y as MenuPopupProps } from "../Menu-B5vDqZe_.js";
3
+ import { h as MenuItemProps, l as MenuContentProps, w as MenuProps } from "../Menu-B5vDqZe_.js";
4
4
  import { c as TabsList, n as TabPanel, t as Tab } from "../Tabs-D9EAq09D.js";
5
5
  import { r as ButtonProps } from "../Button-Ct5I6aTu.js";
6
6
  import * as React from "react";
@@ -261,7 +261,7 @@ declare function PromptInputActionMenuTrigger({
261
261
  children,
262
262
  ...props
263
263
  }: PromptInputActionMenuTriggerProps): React.JSX.Element;
264
- type PromptInputActionMenuContentProps = MenuPopupProps;
264
+ type PromptInputActionMenuContentProps = MenuContentProps;
265
265
  declare function PromptInputActionMenuContent({
266
266
  className,
267
267
  children,
@@ -4,7 +4,7 @@ import { Button } from "./Button.js";
4
4
  import { Tooltip, TooltipPopup, TooltipPortal, TooltipPositioner, TooltipTrigger } from "./Tooltip.js";
5
5
  import { t as AttachmentPreview } from "../attachment-preview-ChtC3HiU.js";
6
6
  import { Combobox, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxList, ComboboxSeparator } from "./Combobox.js";
7
- import { MenuItem, MenuPopup, MenuPortal, MenuPositioner, MenuRadioGroup, MenuRadioItem, MenuRadioItemIndicator, MenuRoot, MenuTrigger } from "./Menu.js";
7
+ import { MenuContent, MenuItem, MenuPopup, MenuPortal, MenuPositioner, MenuRadioGroup, MenuRadioItem, MenuRadioItemIndicator, MenuRoot, MenuTrigger } from "./Menu.js";
8
8
  import { Select, SelectContent, SelectItem, SelectPortal, SelectPositioner, SelectTrigger, SelectValue } from "./Select.js";
9
9
  import { Tab, TabPanel, TabsList } from "./Tabs.js";
10
10
  import * as React from "react";
@@ -538,11 +538,11 @@ function PromptInputActionMenuTrigger({ className, children, ...props }) {
538
538
  }) });
539
539
  }
540
540
  function PromptInputActionMenuContent({ className, children, ...props }) {
541
- return /* @__PURE__ */ jsx(MenuPortal, { children: /* @__PURE__ */ jsx(MenuPositioner, { children: /* @__PURE__ */ jsx(MenuPopup, {
541
+ return /* @__PURE__ */ jsx(MenuContent, {
542
542
  className: cx("prompt-input__action-menu", className),
543
543
  ...props,
544
544
  children
545
- }) }) });
545
+ });
546
546
  }
547
547
  function PromptInputActionMenuItem({ className, ...props }) {
548
548
  return /* @__PURE__ */ jsx(MenuItem, {
@@ -31,6 +31,8 @@ interface ThinkChatMessagesProps extends ThinkChatActivityRendererOptions {
31
31
  emptyState?: React.ReactNode;
32
32
  /** Extra controls rendered inside the composer, next to the send button. */
33
33
  composerTools?: React.ReactNode;
34
+ /** Extra rows rendered in the built-in plus menu after files. */
35
+ composerAddMenuItems?: AgentChatProps["composerAddMenuItems"];
34
36
  /** Composer placeholder text. */
35
37
  placeholder?: string;
36
38
  /** Rendered after each message (e.g. per-message actions). */
@@ -43,6 +43,14 @@
43
43
  margin-inline: auto;
44
44
  }
45
45
 
46
+ .agent-chat__add-menu {
47
+ inline-size: min(32rem, calc(100dvw - 1rem));
48
+ max-block-size: min(28rem, calc(100dvh - 2rem));
49
+ overflow-y: auto;
50
+ overscroll-behavior: contain;
51
+ scrollbar-gutter: stable;
52
+ }
53
+
46
54
  /* Transient status pill between transcript and composer (recovery, errors). */
47
55
  .agent-chat__notice {
48
56
  display: flex;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/react-components",
3
- "version": "0.5.4",
3
+ "version": "0.5.5",
4
4
  "description": "MCP-B React components built on Base UI and shared design tokens, including Cloudflare Think chat primitives.",
5
5
  "homepage": "https://design-system.sigvelo.com",
6
6
  "bugs": {
@@ -49,7 +49,7 @@
49
49
  "anser": "^2.3.5",
50
50
  "shiki": "^3.23.0",
51
51
  "streamdown": "^2.5.0",
52
- "@mcp-b/design-tokens": "0.5.4"
52
+ "@mcp-b/design-tokens": "0.5.5"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@ai-sdk/react": "^3.0.194",