@tangle-network/ui 7.0.0 → 8.0.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/dist/index.d.ts CHANGED
@@ -2,9 +2,9 @@ export { B as Button, a as ButtonProps, b as buttonVariants } from './button-CMQ
2
2
  export { Avatar, AvatarFallback, AvatarImage, Badge, BadgeProps, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DropZone, DropZoneProps, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EmptyState, EmptyStateProps, InlineCode, InlineCodeProps, Input, InputProps, Label, Progress, SegmentedControl, SegmentedControlOption, SegmentedControlProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SidebarDropZone, SidebarDropZoneProps, Skeleton, SkeletonCard, SkeletonTable, StatCard, StatCardProps, Switch, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TerminalCursor, TerminalDisplay, TerminalInput, TerminalLine, Textarea, TextareaProps, ThemeToggle, Toast, ToastContainer, ToastProvider, UploadFile, UploadProgress, UploadProgressProps, badgeVariants, useTheme, useToast } from './primitives.js';
3
3
  export { Logo, LogoProps, TangleKnot } from '@tangle-network/brand';
4
4
  export { A as ArtifactPane, a as ArtifactPaneProps } from './artifact-pane-DvJyPWV4.js';
5
- export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatInput, ChatInputProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, PendingFile, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from './chat.js';
5
+ export { AgentTimeline, AgentTimelineArtifactItem, AgentTimelineCustomItem, AgentTimelineItem, AgentTimelineMessageItem, AgentTimelineProps, AgentTimelineStatusItem, AgentTimelineTone, AgentTimelineToolGroupItem, AgentTimelineToolItem, ChatContainer, ChatContainerProps, ChatMessage, ChatMessageProps, MessageList, MessageListProps, MessageRole, ThinkingIndicator, ThinkingIndicatorProps, UserMessage, UserMessageProps } from './chat.js';
6
6
  export { ExpandedToolDetail, ExpandedToolDetailProps, InlineThinkingItem, InlineThinkingItemProps, InlineToolItem, InlineToolItemProps, LiveDuration, RunGroup, RunGroupProps } from './run.js';
7
- export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallGroup, d as ToolCallGroupProps, e as ToolCallStatus, f as ToolCallStep, g as ToolCallStepProps, h as ToolCallType, p as parseToolEvent } from './tool-call-feed-Bs3MyQMT.js';
7
+ export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallStatus, d as ToolCallType, p as parseToolEvent } from './tool-call-feed-D9iofJgW.js';
8
8
  export { OpenUIAction, OpenUIActionsNode, OpenUIArtifactRenderer, OpenUIArtifactRendererProps, OpenUIBadgeNode, OpenUICardNode, OpenUICodeNode, OpenUIComponentNode, OpenUIGridNode, OpenUIHeadingNode, OpenUIKeyValueNode, OpenUIMarkdownNode, OpenUIPrimitive, OpenUISeparatorNode, OpenUIStackNode, OpenUIStatNode, OpenUITableNode, OpenUITextNode } from './openui.js';
9
9
  export { FileArtifactPane, FileArtifactPaneProps, FileFormat, FileNode, FilePreview, FilePreviewProps, FileTabData, FileTabs, FileTabsProps, FileTree, FileTreeProps, FileTreeVisibilityOptions, RichFileTree, RichFileTreeGitEntry, RichFileTreeGitStatus, RichFileTreeProps, RichFileTreeThemeVars, detectFileFormat, fileExtension, filterFileTree, getCodeLanguage, getFormatLabel, getSyntaxLanguage } from './files.js';
10
10
  export { Markdown, MarkdownProps } from './markdown.js';
package/dist/index.js CHANGED
@@ -133,18 +133,17 @@ import {
133
133
  import {
134
134
  AgentTimeline,
135
135
  ChatContainer,
136
- ChatInput,
137
136
  ChatMessage,
138
137
  MessageList,
139
138
  ThinkingIndicator,
140
139
  UserMessage
141
- } from "./chunk-5CS3I7Y3.js";
140
+ } from "./chunk-UOLL2YHG.js";
142
141
  import {
143
142
  useAutoScroll,
144
143
  useRunCollapseState,
145
144
  useRunGroups
146
145
  } from "./chunk-AZWDI2JG.js";
147
- import "./chunk-LQS34IGP.js";
146
+ import "./chunk-47XH56SV.js";
148
147
  import {
149
148
  ToolCallFeed,
150
149
  parseToolEvent
@@ -156,9 +155,7 @@ import {
156
155
  import {
157
156
  ExpandedToolDetail,
158
157
  InlineToolItem,
159
- LiveDuration,
160
- ToolCallGroup,
161
- ToolCallStep
158
+ LiveDuration
162
159
  } from "./chunk-RKQDBRTC.js";
163
160
  import {
164
161
  TOOL_CATEGORY_ICONS,
@@ -354,7 +351,6 @@ export {
354
351
  CardHeader,
355
352
  CardTitle,
356
353
  ChatContainer,
357
- ChatInput,
358
354
  ChatMessage,
359
355
  CodeBlock,
360
356
  CommandPreview,
@@ -453,8 +449,6 @@ export {
453
449
  ToastContainer,
454
450
  ToastProvider,
455
451
  ToolCallFeed,
456
- ToolCallGroup,
457
- ToolCallStep,
458
452
  UploadProgress,
459
453
  UserMenu,
460
454
  UserMessage,
package/dist/run.d.ts CHANGED
@@ -5,7 +5,7 @@ import { R as Run } from './run-PfLmDAox.js';
5
5
  import { S as SessionPart, a as ToolPart, R as ReasoningPart } from './parts-dj7AcUg0.js';
6
6
  import { AgentBranding } from './types.js';
7
7
  import { C as CustomToolRenderer } from './tool-display-z4JcDmMQ.js';
8
- export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallGroup, d as ToolCallGroupProps, e as ToolCallStatus, f as ToolCallStep, g as ToolCallStepProps, h as ToolCallType, p as parseToolEvent } from './tool-call-feed-Bs3MyQMT.js';
8
+ export { F as FeedSegment, T as ToolCallData, a as ToolCallFeed, b as ToolCallFeedProps, c as ToolCallStatus, d as ToolCallType, p as parseToolEvent } from './tool-call-feed-D9iofJgW.js';
9
9
  import './message-BHWbxBtT.js';
10
10
 
11
11
  interface RunGroupProps {
package/dist/run.js CHANGED
@@ -1,4 +1,4 @@
1
- import "./chunk-LQS34IGP.js";
1
+ import "./chunk-47XH56SV.js";
2
2
  import {
3
3
  ToolCallFeed,
4
4
  parseToolEvent
@@ -10,9 +10,7 @@ import {
10
10
  import {
11
11
  ExpandedToolDetail,
12
12
  InlineToolItem,
13
- LiveDuration,
14
- ToolCallGroup,
15
- ToolCallStep
13
+ LiveDuration
16
14
  } from "./chunk-RKQDBRTC.js";
17
15
  import "./chunk-ULDNFLIM.js";
18
16
  import "./chunk-AAUNOHVL.js";
@@ -30,7 +28,5 @@ export {
30
28
  LiveDuration,
31
29
  RunGroup,
32
30
  ToolCallFeed,
33
- ToolCallGroup,
34
- ToolCallStep,
35
31
  parseToolEvent
36
32
  };
@@ -4,7 +4,7 @@ import { R as Run, G as GroupedMessage } from './run-PfLmDAox.js';
4
4
  import { S as SessionMessage } from './message-BHWbxBtT.js';
5
5
  import { S as SessionPart } from './parts-dj7AcUg0.js';
6
6
  import { R as RegisterActiveSessionOptions, g as ActiveSessionTransportMode, c as ActiveSessionConnectionState } from './active-sessions-store-CeOmXgv5.js';
7
- import { F as FeedSegment } from './tool-call-feed-Bs3MyQMT.js';
7
+ import { F as FeedSegment } from './tool-call-feed-D9iofJgW.js';
8
8
  import 'nanostores';
9
9
  import 'react/jsx-runtime';
10
10
 
@@ -1,29 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { ReactNode } from 'react';
3
2
 
4
3
  type ToolCallType = "bash" | "read" | "write" | "edit" | "glob" | "grep" | "list" | "download" | "inspect" | "audit" | "unknown";
5
4
  type ToolCallStatus = "running" | "success" | "error";
6
- interface ToolCallStepProps {
7
- type: ToolCallType;
8
- label: string;
9
- status: ToolCallStatus;
10
- detail?: string;
11
- output?: string;
12
- /** Override syntax highlighting language; inferred from detail path if omitted */
13
- language?: string;
14
- duration?: number;
15
- className?: string;
16
- }
17
- declare function ToolCallStep({ type, label, status, detail, output, language, duration, className, }: ToolCallStepProps): react_jsx_runtime.JSX.Element;
18
- /**
19
- * ToolCallGroup — groups multiple tool calls under a heading.
20
- */
21
- interface ToolCallGroupProps {
22
- title?: string;
23
- children: ReactNode;
24
- className?: string;
25
- }
26
- declare function ToolCallGroup({ title, children, className }: ToolCallGroupProps): react_jsx_runtime.JSX.Element;
27
5
 
28
6
  interface ToolCallData {
29
7
  id: string;
@@ -65,4 +43,4 @@ declare function parseToolEvent(event: {
65
43
  data: Record<string, unknown>;
66
44
  }): ToolCallData | null;
67
45
 
68
- export { type FeedSegment as F, type ToolCallData as T, ToolCallFeed as a, type ToolCallFeedProps as b, ToolCallGroup as c, type ToolCallGroupProps as d, type ToolCallStatus as e, ToolCallStep as f, type ToolCallStepProps as g, type ToolCallType as h, parseToolEvent as p };
46
+ export { type FeedSegment as F, type ToolCallData as T, ToolCallFeed as a, type ToolCallFeedProps as b, type ToolCallStatus as c, type ToolCallType as d, parseToolEvent as p };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/ui",
3
- "version": "7.0.0",
3
+ "version": "8.0.0",
4
4
  "description": "Generic React UI components for Tangle products — primitives, chat, run, files, editor, markdown.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,7 +1,6 @@
1
1
  import {
2
2
  memo,
3
3
  type ReactNode,
4
- useCallback,
5
4
  useMemo,
6
5
  useRef,
7
6
  } from "react";
@@ -20,7 +19,6 @@ import {
20
19
  AgentTimeline,
21
20
  type AgentTimelineItem,
22
21
  } from "./agent-timeline";
23
- import { ChatInput, type PendingFile } from "./chat-input";
24
22
  import { InlineThinkingItem } from "../run/inline-thinking-item";
25
23
  import { getToolDisplayMetadata } from "../utils/tool-display";
26
24
  import {
@@ -29,27 +27,21 @@ import {
29
27
  type OpenUIComponentNode,
30
28
  } from "../openui/openui-artifact-renderer";
31
29
 
30
+ /**
31
+ * Transcript-only container: message list + auto-scroll. Composers are
32
+ * composed BELOW this by the app (the canonical one is `AgentComposer` in
33
+ * `@tangle-network/sandbox-ui`) — this component never renders an input.
34
+ */
32
35
  export interface ChatContainerProps {
33
36
  messages: SessionMessage[];
34
37
  partMap: Record<string, SessionPart[]>;
35
38
  isStreaming: boolean;
36
- onSend?: (text: string) => void;
37
- onCancel?: () => void;
38
39
  branding?: AgentBranding;
39
- placeholder?: string;
40
40
  className?: string;
41
- /** Hide the input area (useful for read-only views). */
42
- hideInput?: boolean;
43
41
  /** Custom renderer for tool details. Return ReactNode to override, null to use default. */
44
42
  renderToolDetail?: CustomToolRenderer;
45
43
  /** Presentation mode for the session view. */
46
44
  presentation?: "runs" | "timeline";
47
- modelLabel?: string;
48
- onModelClick?: () => void;
49
- pendingFiles?: PendingFile[];
50
- onRemoveFile?: (id: string) => void;
51
- onAttach?: (files: FileList) => void;
52
- disabled?: boolean;
53
45
  /** Callback when an OpenUI action button is pressed within inline OpenUI blocks. */
54
46
  onOpenUIAction?: (action: OpenUIAction) => void;
55
47
  /** Enable rendering OpenUI schemas inline in the chat timeline. Defaults to true. */
@@ -355,7 +347,7 @@ function buildTimelineItems(
355
347
  }
356
348
 
357
349
  /**
358
- * Full chat container: message list + auto-scroll + input area.
350
+ * Chat transcript container: message list + auto-scroll.
359
351
  * Orchestrates useRunGroups, useRunCollapseState, and useAutoScroll.
360
352
  */
361
353
  export const ChatContainer = memo(
@@ -363,20 +355,10 @@ export const ChatContainer = memo(
363
355
  messages,
364
356
  partMap,
365
357
  isStreaming,
366
- onSend,
367
- onCancel,
368
358
  branding,
369
- placeholder = "Type a message...",
370
359
  className,
371
- hideInput = false,
372
360
  renderToolDetail,
373
361
  presentation = "runs",
374
- modelLabel,
375
- onModelClick,
376
- pendingFiles,
377
- onRemoveFile,
378
- onAttach,
379
- disabled = false,
380
362
  onOpenUIAction,
381
363
  enableOpenUI = true,
382
364
  renderRunActions,
@@ -404,13 +386,6 @@ export const ChatContainer = memo(
404
386
  [messages, partMap, isStreaming, onOpenUIAction, enableOpenUI],
405
387
  );
406
388
 
407
- const handleSend = useCallback(
408
- (text: string) => {
409
- onSend?.(text);
410
- },
411
- [onSend],
412
- );
413
-
414
389
  return (
415
390
  <div className={cn("flex h-full flex-col", className)}>
416
391
  {/* Message area */}
@@ -462,23 +437,6 @@ export const ChatContainer = memo(
462
437
  </button>
463
438
  </div>
464
439
  )}
465
-
466
- {/* Input area */}
467
- {!hideInput && onSend && (
468
- <ChatInput
469
- onSend={handleSend}
470
- onCancel={onCancel}
471
- isStreaming={isStreaming}
472
- placeholder={placeholder}
473
- modelLabel={modelLabel}
474
- onModelClick={onModelClick}
475
- pendingFiles={pendingFiles}
476
- onRemoveFile={onRemoveFile}
477
- onAttach={onAttach}
478
- disabled={disabled}
479
- className="shrink-0 border-t border-border bg-background"
480
- />
481
- )}
482
440
  </div>
483
441
  );
484
442
  },
@@ -27,10 +27,6 @@ export interface ChatMessageProps {
27
27
  assistantLabel?: string;
28
28
  /** Hide the role label row entirely */
29
29
  hideRoleLabel?: boolean;
30
- /** @deprecated Avatars were removed from the bubble design; this prop is ignored. */
31
- hideAvatar?: boolean;
32
- /** @deprecated Avatars were removed from the bubble design; this prop is ignored. */
33
- avatar?: ReactNode;
34
30
  }
35
31
 
36
32
  export function ChatMessage({
package/src/chat/index.ts CHANGED
@@ -2,7 +2,6 @@ export { ChatContainer, type ChatContainerProps } from "./chat-container";
2
2
  export { MessageList, type MessageListProps } from "./message-list";
3
3
  export { UserMessage, type UserMessageProps } from "./user-message";
4
4
  export { ChatMessage, type ChatMessageProps, type MessageRole } from "./chat-message";
5
- export { ChatInput, type ChatInputProps, type PendingFile } from "./chat-input";
6
5
  export { ThinkingIndicator, type ThinkingIndicatorProps } from "./thinking-indicator";
7
6
  export {
8
7
  AgentTimeline,
@@ -39,7 +39,7 @@ pnpm add @tangle/sandbox-ui
39
39
  Import the components you need:
40
40
 
41
41
  \`\`\`tsx
42
- import { ChatInput, DropZone, UploadProgress } from '@tangle/sandbox-ui'
42
+ import { AgentComposer, DropZone, UploadProgress } from '@tangle-network/sandbox-ui'
43
43
  \`\`\`
44
44
 
45
45
  > **Note:** Components assume a Tailwind CSS v4 setup with the design tokens
package/src/run/index.ts CHANGED
@@ -9,5 +9,8 @@ export {
9
9
  type ExpandedToolDetailProps,
10
10
  } from "./expanded-tool-detail";
11
11
  export { LiveDuration } from "./run-item-primitives";
12
- export { ToolCallStep, ToolCallGroup, type ToolCallStepProps, type ToolCallGroupProps, type ToolCallType, type ToolCallStatus } from "./tool-call-step";
12
+ // ToolCallStep/ToolCallGroup are internal adapters over InlineToolItem (used by
13
+ // AgentTimeline + ToolCallFeed); only their status/type vocabulary is public
14
+ // because ToolCallData references it.
15
+ export { type ToolCallType, type ToolCallStatus } from "./tool-call-step";
13
16
  export { ToolCallFeed, parseToolEvent, type ToolCallFeedProps, type ToolCallData, type FeedSegment } from "./tool-call-feed";
@@ -1,11 +1,9 @@
1
1
  /**
2
- * ToolCallStep — a single agent tool invocation as a collapsible activity step.
3
- *
4
- * Now a thin adapter over the canonical `InlineToolItem`: it maps the flat
5
- * `ToolCallData`-style props (label / status / detail / output / duration) onto
6
- * a `ToolPart` and delegates rendering, so the timeline feed (`AgentTimeline`,
7
- * `ToolCallFeed`) and the run group share ONE row implementation and one look.
8
- * The bespoke row markup is gone; only the prop adapter remains.
2
+ * ToolCallStep — internal adapter over the canonical `InlineToolItem` row.
3
+ * Maps flat `ToolCallData`-style props (label / status / detail / output /
4
+ * duration) onto a `ToolPart` so `AgentTimeline` and `ToolCallFeed` share the
5
+ * one row implementation. Not exported publicly; only the `ToolCallType` /
6
+ * `ToolCallStatus` vocabulary is (via `ToolCallData`).
9
7
  */
10
8
 
11
9
  import { type ReactNode } from "react";
@@ -1,142 +0,0 @@
1
- import type { Meta, StoryObj } from '@storybook/react'
2
- import { ChatInput, type PendingFile } from './chat-input'
3
-
4
- const meta: Meta<typeof ChatInput> = {
5
- title: 'Chat/ChatInput',
6
- component: ChatInput,
7
- parameters: { layout: 'centered', backgrounds: { default: 'dark' } },
8
- decorators: [
9
- (Story) => (
10
- <div className="w-[680px]">
11
- <Story />
12
- </div>
13
- ),
14
- ],
15
- args: {
16
- onSend: (msg, files) => console.log('send', msg, files),
17
- onCancel: () => console.log('cancel'),
18
- },
19
- }
20
-
21
- export default meta
22
- type Story = StoryObj<typeof ChatInput>
23
-
24
- export const Empty: Story = {
25
- name: 'Empty — ready',
26
- }
27
-
28
- export const WithModelSelector: Story = {
29
- name: 'With model selector',
30
- args: {
31
- modelLabel: 'claude-sonnet-4-6',
32
- onModelClick: () => console.log('model click'),
33
- },
34
- }
35
-
36
- export const WithAttachButtons: Story = {
37
- name: 'With attach buttons',
38
- args: {
39
- onAttach: (files) => console.log('attach', files),
40
- onAttachFolder: (files) => console.log('attach folder', files),
41
- modelLabel: 'claude-sonnet-4-6',
42
- onModelClick: () => console.log('model click'),
43
- },
44
- }
45
-
46
- export const Streaming: Story = {
47
- name: 'Streaming — stop button active',
48
- args: {
49
- isStreaming: true,
50
- onCancel: () => console.log('cancel'),
51
- onAttach: (files) => console.log('attach', files),
52
- modelLabel: 'claude-sonnet-4-6',
53
- },
54
- }
55
-
56
- export const Disabled: Story = {
57
- name: 'Disabled',
58
- args: {
59
- disabled: true,
60
- onAttach: (files) => console.log('attach', files),
61
- modelLabel: 'claude-sonnet-4-6',
62
- },
63
- }
64
-
65
- const sampleFiles: PendingFile[] = [
66
- { id: 'f1', name: 'dataset.csv', size: 204800, type: 'file', status: 'ready' },
67
- { id: 'f2', name: 'report.pdf', size: 1572864, type: 'file', status: 'uploading' },
68
- ]
69
-
70
- export const WithFilesAttached: Story = {
71
- name: 'With file attachments',
72
- args: {
73
- onAttach: (files) => console.log('attach', files),
74
- pendingFiles: sampleFiles,
75
- onRemoveFile: (id) => console.log('remove', id),
76
- modelLabel: 'claude-sonnet-4-6',
77
- onModelClick: () => console.log('model click'),
78
- },
79
- }
80
-
81
- const folderFiles: PendingFile[] = [
82
- { id: 'd1', name: 'my-project', size: 0, type: 'folder', fileCount: 42, status: 'ready' },
83
- { id: 'f3', name: 'notes.txt', size: 1024, type: 'file', status: 'ready' },
84
- ]
85
-
86
- export const WithFolderAttached: Story = {
87
- name: 'With folder + file',
88
- args: {
89
- onAttach: (files) => console.log('attach', files),
90
- onAttachFolder: (files) => console.log('attach folder', files),
91
- pendingFiles: folderFiles,
92
- onRemoveFile: (id) => console.log('remove', id),
93
- modelLabel: 'claude-sonnet-4-6',
94
- },
95
- }
96
-
97
- export const WithErrorFile: Story = {
98
- name: 'With error attachment',
99
- args: {
100
- onAttach: (files) => console.log('attach', files),
101
- pendingFiles: [
102
- { id: 'e1', name: 'too-large.zip', size: 524288000, type: 'file', status: 'error' },
103
- { id: 'f4', name: 'config.json', size: 2048, type: 'file', status: 'ready' },
104
- ],
105
- onRemoveFile: (id) => console.log('remove', id),
106
- },
107
- }
108
-
109
- export const CustomPlaceholder: Story = {
110
- name: 'Custom placeholder',
111
- args: {
112
- placeholder: 'Describe the data transformation you need…',
113
- onAttach: (files) => console.log('attach', files),
114
- modelLabel: 'gpt-4o',
115
- },
116
- }
117
-
118
- /** Static drag-over overlay preview */
119
- export const DragOverPreview: Story = {
120
- name: 'Drag-over overlay (static preview)',
121
- render: (args) => (
122
- <div className="w-[680px] px-4 py-3 relative">
123
- {/* Drag overlay replica */}
124
- <div className="absolute inset-0 z-10 flex items-center justify-center rounded-[28px] border-2 border-dashed border-blue-400 bg-blue-500/8 backdrop-blur-sm pointer-events-none mx-4 my-3">
125
- <div className="text-center">
126
- <div className="mx-auto mb-3 flex h-12 w-12 items-center justify-center rounded-xl bg-blue-500/15">
127
- <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-blue-400" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={2}>
128
- <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
129
- <polyline points="17 8 12 3 7 8" />
130
- <line x1="12" y1="3" x2="12" y2="15" />
131
- </svg>
132
- </div>
133
- <p className="text-sm font-semibold text-white">Drop files to add context</p>
134
- <p className="mt-1 text-xs text-zinc-400">Files will be attached to your next message.</p>
135
- </div>
136
- </div>
137
- {/* Underlying input (blurred) */}
138
- <ChatInput {...args} onAttach={() => {}} />
139
- </div>
140
- ),
141
- args: {},
142
- }