@automattic/agenttic-ui 0.1.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/README.md +488 -0
- package/dist/index.css +1 -0
- package/dist/index.js +2275 -0
- package/package.json +101 -0
package/README.md
ADDED
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
# @automattic/agenttic-ui
|
|
2
|
+
|
|
3
|
+
React UI components for AI agent chat interfaces. A pure UI layer designed to work seamlessly with `@automattic/agenttic-client` hooks or any agent communication system.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @automattic/agenttic-ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Key Features
|
|
12
|
+
|
|
13
|
+
- Pure UI components with no agent communication logic
|
|
14
|
+
- Floating and embedded chat variants
|
|
15
|
+
- Smooth animations and drag-and-drop positioning
|
|
16
|
+
- Message actions and markdown rendering
|
|
17
|
+
- TypeScript support with comprehensive types
|
|
18
|
+
- Storybook component documentation
|
|
19
|
+
- Modular component architecture for custom layouts
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Complete Chat Interface
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { useAgentChat } from '@automattic/agenttic-client';
|
|
27
|
+
import { AgentUI } from '@automattic/agenttic-ui';
|
|
28
|
+
|
|
29
|
+
function ChatApplication() {
|
|
30
|
+
const {
|
|
31
|
+
messages,
|
|
32
|
+
isProcessing,
|
|
33
|
+
error,
|
|
34
|
+
onSubmit,
|
|
35
|
+
suggestions,
|
|
36
|
+
clearSuggestions,
|
|
37
|
+
messageRenderer
|
|
38
|
+
} = useAgentChat({
|
|
39
|
+
agentId: 'big-sky',
|
|
40
|
+
sessionId: 'my-session'
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<AgentUI
|
|
45
|
+
messages={messages}
|
|
46
|
+
isProcessing={isProcessing}
|
|
47
|
+
error={error}
|
|
48
|
+
onSubmit={onSubmit}
|
|
49
|
+
suggestions={suggestions}
|
|
50
|
+
clearSuggestions={clearSuggestions}
|
|
51
|
+
messageRenderer={messageRenderer}
|
|
52
|
+
variant="floating"
|
|
53
|
+
placeholder="Ask me anything..."
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Embedded Chat
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<AgentUI
|
|
63
|
+
messages={messages}
|
|
64
|
+
isProcessing={isProcessing}
|
|
65
|
+
error={error}
|
|
66
|
+
onSubmit={onSubmit}
|
|
67
|
+
variant="embedded"
|
|
68
|
+
placeholder="How can I help you?"
|
|
69
|
+
/>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Core Components
|
|
73
|
+
|
|
74
|
+
### AgentUI
|
|
75
|
+
|
|
76
|
+
The main component that provides a complete chat interface.
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
interface AgentUIProps {
|
|
80
|
+
// Core chat data
|
|
81
|
+
messages: Message[];
|
|
82
|
+
isProcessing: boolean;
|
|
83
|
+
error?: string | null;
|
|
84
|
+
onSubmit: (message: string) => void;
|
|
85
|
+
|
|
86
|
+
// UI configuration
|
|
87
|
+
variant?: 'floating' | 'embedded';
|
|
88
|
+
placeholder?: string;
|
|
89
|
+
triggerIcon?: React.ReactNode;
|
|
90
|
+
notice?: NoticeConfig;
|
|
91
|
+
emptyView?: React.ReactNode;
|
|
92
|
+
|
|
93
|
+
// Chat state management (floating variant)
|
|
94
|
+
floatingChatState?: ChatState;
|
|
95
|
+
onOpen?: () => void;
|
|
96
|
+
onExpand?: () => void;
|
|
97
|
+
onClose?: () => void;
|
|
98
|
+
|
|
99
|
+
// Suggestions
|
|
100
|
+
suggestions?: Suggestion[];
|
|
101
|
+
clearSuggestions?: () => void;
|
|
102
|
+
|
|
103
|
+
// Message rendering
|
|
104
|
+
messageRenderer?: ComponentType<{ children: string }>;
|
|
105
|
+
|
|
106
|
+
// Styling
|
|
107
|
+
className?: string;
|
|
108
|
+
style?: React.CSSProperties;
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Variants:**
|
|
113
|
+
- `floating` - Draggable chat widget with collapsed/compact/expanded states
|
|
114
|
+
- `embedded` - Fixed chat interface for integration in existing layouts
|
|
115
|
+
|
|
116
|
+
### Individual Components
|
|
117
|
+
|
|
118
|
+
For custom chat layouts, use individual components:
|
|
119
|
+
|
|
120
|
+
```tsx
|
|
121
|
+
import {
|
|
122
|
+
Chat,
|
|
123
|
+
Messages,
|
|
124
|
+
Message,
|
|
125
|
+
ChatInput,
|
|
126
|
+
Suggestions
|
|
127
|
+
} from '@automattic/agenttic-ui';
|
|
128
|
+
|
|
129
|
+
function CustomChat() {
|
|
130
|
+
return (
|
|
131
|
+
<div className="my-chat-container">
|
|
132
|
+
<Messages messages={messages} messageRenderer={messageRenderer} />
|
|
133
|
+
<Suggestions
|
|
134
|
+
suggestions={suggestions}
|
|
135
|
+
onSuggestionClick={onSubmit}
|
|
136
|
+
onClear={clearSuggestions}
|
|
137
|
+
/>
|
|
138
|
+
<ChatInput
|
|
139
|
+
value={inputValue}
|
|
140
|
+
onChange={setInputValue}
|
|
141
|
+
onSubmit={onSubmit}
|
|
142
|
+
placeholder="Type a message..."
|
|
143
|
+
isProcessing={isProcessing}
|
|
144
|
+
/>
|
|
145
|
+
</div>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Component APIs
|
|
151
|
+
|
|
152
|
+
### Chat
|
|
153
|
+
|
|
154
|
+
Main chat component supporting both floating and embedded variants.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
<Chat
|
|
158
|
+
messages={messages}
|
|
159
|
+
isProcessing={isProcessing}
|
|
160
|
+
error={error}
|
|
161
|
+
onSubmit={onSubmit}
|
|
162
|
+
variant="floating"
|
|
163
|
+
placeholder="Ask anything..."
|
|
164
|
+
suggestions={suggestions}
|
|
165
|
+
clearSuggestions={clearSuggestions}
|
|
166
|
+
messageRenderer={messageRenderer}
|
|
167
|
+
/>
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Messages
|
|
171
|
+
|
|
172
|
+
Container for displaying message history.
|
|
173
|
+
|
|
174
|
+
```tsx
|
|
175
|
+
<Messages
|
|
176
|
+
messages={messages}
|
|
177
|
+
messageRenderer={messageRenderer}
|
|
178
|
+
emptyView={<div>No messages yet</div>}
|
|
179
|
+
/>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Message
|
|
183
|
+
|
|
184
|
+
Individual message component with action support.
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<Message
|
|
188
|
+
message={message}
|
|
189
|
+
messageRenderer={messageRenderer}
|
|
190
|
+
showIcon={true}
|
|
191
|
+
/>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### ChatInput
|
|
195
|
+
|
|
196
|
+
Text input with auto-resize and submit handling.
|
|
197
|
+
|
|
198
|
+
```tsx
|
|
199
|
+
<ChatInput
|
|
200
|
+
value={value}
|
|
201
|
+
onChange={setValue}
|
|
202
|
+
onSubmit={handleSubmit}
|
|
203
|
+
onKeyDown={handleKeyDown}
|
|
204
|
+
placeholder="Type a message..."
|
|
205
|
+
isProcessing={false}
|
|
206
|
+
textareaRef={textareaRef}
|
|
207
|
+
/>
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Suggestions
|
|
211
|
+
|
|
212
|
+
Quick action suggestions for users.
|
|
213
|
+
|
|
214
|
+
```tsx
|
|
215
|
+
<Suggestions
|
|
216
|
+
suggestions={[
|
|
217
|
+
{ id: '1', label: 'Help me code', prompt: 'Can you help me write code?' },
|
|
218
|
+
{ id: '2', label: 'Explain concept', prompt: 'Explain this concept to me' }
|
|
219
|
+
]}
|
|
220
|
+
onSuggestionClick={onSubmit}
|
|
221
|
+
onClear={clearSuggestions}
|
|
222
|
+
/>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Hooks
|
|
226
|
+
|
|
227
|
+
### useChat
|
|
228
|
+
|
|
229
|
+
Manages chat state for floating variant.
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
const {
|
|
233
|
+
state, // 'collapsed' | 'compact' | 'expanded'
|
|
234
|
+
setState,
|
|
235
|
+
isOpen, // boolean
|
|
236
|
+
open, // () => void
|
|
237
|
+
close, // () => void
|
|
238
|
+
toggle // () => void
|
|
239
|
+
} = useChat(initialState);
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### useInput
|
|
243
|
+
|
|
244
|
+
Manages text input state with auto-resize and keyboard handling.
|
|
245
|
+
|
|
246
|
+
```tsx
|
|
247
|
+
const {
|
|
248
|
+
value,
|
|
249
|
+
setValue,
|
|
250
|
+
clear,
|
|
251
|
+
textareaRef,
|
|
252
|
+
handleKeyDown,
|
|
253
|
+
adjustHeight
|
|
254
|
+
} = useInput({
|
|
255
|
+
value: inputValue,
|
|
256
|
+
setValue: setInputValue,
|
|
257
|
+
onSubmit: handleSubmit,
|
|
258
|
+
isProcessing: false
|
|
259
|
+
});
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Icons
|
|
263
|
+
|
|
264
|
+
Pre-built icon components for consistent UI:
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
import {
|
|
268
|
+
ThumbsUpIcon,
|
|
269
|
+
ThumbsDownIcon,
|
|
270
|
+
CopyIcon,
|
|
271
|
+
StopIcon,
|
|
272
|
+
ArrowUpIcon,
|
|
273
|
+
XIcon,
|
|
274
|
+
BigSkyIcon,
|
|
275
|
+
StylesIcon
|
|
276
|
+
} from '@automattic/agenttic-ui';
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Type Definitions
|
|
280
|
+
|
|
281
|
+
```tsx
|
|
282
|
+
interface Message {
|
|
283
|
+
id: string;
|
|
284
|
+
role: 'user' | 'agent';
|
|
285
|
+
content: Array<{
|
|
286
|
+
type: 'text' | 'image_url' | 'component';
|
|
287
|
+
text?: string;
|
|
288
|
+
image_url?: string;
|
|
289
|
+
component?: React.ComponentType;
|
|
290
|
+
componentProps?: any;
|
|
291
|
+
}>;
|
|
292
|
+
timestamp: number;
|
|
293
|
+
archived: boolean;
|
|
294
|
+
showIcon: boolean;
|
|
295
|
+
icon?: string;
|
|
296
|
+
actions?: MessageAction[];
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
interface MessageAction {
|
|
300
|
+
id: string;
|
|
301
|
+
icon: React.ReactNode;
|
|
302
|
+
label: string;
|
|
303
|
+
onClick: (message: Message) => void | Promise<void>;
|
|
304
|
+
tooltip?: string;
|
|
305
|
+
disabled?: boolean;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
interface Suggestion {
|
|
309
|
+
id: string;
|
|
310
|
+
label: string;
|
|
311
|
+
prompt: string;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
interface NoticeConfig {
|
|
315
|
+
icon?: React.ReactNode;
|
|
316
|
+
message: string;
|
|
317
|
+
action?: {
|
|
318
|
+
label: string;
|
|
319
|
+
onClick: () => void;
|
|
320
|
+
};
|
|
321
|
+
dismissible?: boolean;
|
|
322
|
+
onDismiss?: () => void;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
type ChatState = 'collapsed' | 'compact' | 'expanded';
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Styling
|
|
329
|
+
|
|
330
|
+
### CSS Import
|
|
331
|
+
|
|
332
|
+
Components automatically import their styles. For manual control:
|
|
333
|
+
|
|
334
|
+
```css
|
|
335
|
+
/* In your CSS */
|
|
336
|
+
@import '@automattic/agenttic-ui/index.css';
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
```tsx
|
|
340
|
+
// In JavaScript/TypeScript
|
|
341
|
+
import '@automattic/agenttic-ui/index.css';
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Customization
|
|
345
|
+
|
|
346
|
+
Components use CSS Modules with design tokens. Override styles using CSS custom properties:
|
|
347
|
+
|
|
348
|
+
```css
|
|
349
|
+
:root {
|
|
350
|
+
--agenttic-primary-color: #your-brand-color;
|
|
351
|
+
--agenttic-border-radius: 8px;
|
|
352
|
+
--agenttic-spacing-unit: 16px;
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Advanced Usage
|
|
357
|
+
|
|
358
|
+
### Custom Message Renderer
|
|
359
|
+
|
|
360
|
+
Provide a custom markdown renderer:
|
|
361
|
+
|
|
362
|
+
```tsx
|
|
363
|
+
import { ReactMarkdown } from 'react-markdown';
|
|
364
|
+
|
|
365
|
+
const customRenderer = ({ children }: { children: string }) => (
|
|
366
|
+
<ReactMarkdown
|
|
367
|
+
remarkPlugins={[remarkGfm]}
|
|
368
|
+
components={{
|
|
369
|
+
code: ({ children }) => <code className="custom-code">{children}</code>
|
|
370
|
+
}}
|
|
371
|
+
>
|
|
372
|
+
{children}
|
|
373
|
+
</ReactMarkdown>
|
|
374
|
+
);
|
|
375
|
+
|
|
376
|
+
<AgentUI
|
|
377
|
+
messages={messages}
|
|
378
|
+
messageRenderer={customRenderer}
|
|
379
|
+
// ... other props
|
|
380
|
+
/>
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
### Message Actions
|
|
384
|
+
|
|
385
|
+
Messages can include interactive actions:
|
|
386
|
+
|
|
387
|
+
```tsx
|
|
388
|
+
const messagesWithActions = messages.map(message => ({
|
|
389
|
+
...message,
|
|
390
|
+
actions: message.role === 'agent' ? [
|
|
391
|
+
{
|
|
392
|
+
id: 'copy',
|
|
393
|
+
icon: <CopyIcon />,
|
|
394
|
+
label: 'Copy',
|
|
395
|
+
onClick: () => navigator.clipboard.writeText(message.content[0].text)
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
id: 'feedback',
|
|
399
|
+
icon: <ThumbsUpIcon />,
|
|
400
|
+
label: 'Good response',
|
|
401
|
+
onClick: () => console.log('Positive feedback')
|
|
402
|
+
}
|
|
403
|
+
] : []
|
|
404
|
+
}));
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
### Controlled Chat State
|
|
408
|
+
|
|
409
|
+
For floating variant, control the chat state externally:
|
|
410
|
+
|
|
411
|
+
```tsx
|
|
412
|
+
const [chatState, setChatState] = useState<ChatState>('collapsed');
|
|
413
|
+
|
|
414
|
+
<AgentUI
|
|
415
|
+
variant="floating"
|
|
416
|
+
floatingChatState={chatState}
|
|
417
|
+
onOpen={() => setChatState('compact')}
|
|
418
|
+
onExpand={() => setChatState('expanded')}
|
|
419
|
+
onClose={() => setChatState('collapsed')}
|
|
420
|
+
// ... other props
|
|
421
|
+
/>
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
### Custom Empty View
|
|
425
|
+
|
|
426
|
+
Provide custom content when there are no messages:
|
|
427
|
+
|
|
428
|
+
```tsx
|
|
429
|
+
<AgentUI
|
|
430
|
+
messages={[]}
|
|
431
|
+
emptyView={
|
|
432
|
+
<div className="welcome-message">
|
|
433
|
+
<h3>Welcome to AI Assistant</h3>
|
|
434
|
+
<p>I'm here to help you with any questions.</p>
|
|
435
|
+
</div>
|
|
436
|
+
}
|
|
437
|
+
// ... other props
|
|
438
|
+
/>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
## Development
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
# Build the package
|
|
445
|
+
pnpm build
|
|
446
|
+
|
|
447
|
+
# Run in development mode
|
|
448
|
+
pnpm dev
|
|
449
|
+
|
|
450
|
+
# Run tests
|
|
451
|
+
pnpm test
|
|
452
|
+
|
|
453
|
+
# Type checking
|
|
454
|
+
pnpm type-check
|
|
455
|
+
|
|
456
|
+
# Start Storybook
|
|
457
|
+
pnpm storybook
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Storybook Documentation
|
|
461
|
+
|
|
462
|
+
Interactive component documentation is available via Storybook:
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
pnpm storybook
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
Visit `http://localhost:6006` to explore component examples and documentation.
|
|
469
|
+
|
|
470
|
+
## Integration with agenttic-client
|
|
471
|
+
|
|
472
|
+
This UI package is designed to work seamlessly with `@automattic/agenttic-client`:
|
|
473
|
+
|
|
474
|
+
```tsx
|
|
475
|
+
import { useAgentChat } from '@automattic/agenttic-client';
|
|
476
|
+
import { AgentUI } from '@automattic/agenttic-ui';
|
|
477
|
+
|
|
478
|
+
function App() {
|
|
479
|
+
const agentProps = useAgentChat({
|
|
480
|
+
agentId: 'big-sky',
|
|
481
|
+
// ... configuration
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
return <AgentUI {...agentProps} variant="floating" />;
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
The `useAgentChat` hook returns props that match the `AgentUI` interface perfectly, making integration seamless.
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--color-background: oklch(.99 0 0);--color-foreground: oklch(.241 0 0);--color-primary: oklch(.53 .22 268.05);--color-primary-foreground: oklch(1 0 0);--color-ring: var(--color-primary);--color-destructive: oklch(.492 .2095 28.09);--color-muted: color-mix(in srgb, var(--color-foreground) 10%, var(--color-background));--color-muted-foreground: color-mix(in srgb, var(--color-background) 40%, var(--color-foreground));--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-weight-medium: 450;--text-sm: .875rem;--text-sm--line-height: 1.65;--text-base: .9375rem;--text-base--line-height: 1.625;--text-base--tracking: -.01em;--spacing: .25rem;--spacing-1: var(--spacing);--spacing-1\.5: calc(var(--spacing) * 1.5);--spacing-2: calc(var(--spacing) * 2);--spacing-3: calc(var(--spacing) * 3);--spacing-4: calc(var(--spacing) * 4);--spacing-5: calc(var(--spacing) * 5);--spacing-6: calc(var(--spacing) * 6);--spacing-7: calc(var(--spacing) * 7);--spacing-8: calc(var(--spacing) * 8);--spacing-9: calc(var(--spacing) * 9);--spacing-10: calc(var(--spacing) * 10);--spacing-20: calc(var(--spacing) * 20);--radius: 1rem;--radius-xs: calc(var(--radius) - 10px);--radius-sm: calc(var(--radius) - 8px);--radius-md: calc(var(--radius) - 2px);--radius-lg: var(--radius);--radius-xl: calc(var(--radius) + 8px);--radius-full: 9999px;--shadow-sm: 0 0 0 1px color-mix(in srgb, var(--color-foreground) 10%, transparent), 0 0 6px color-mix(in srgb, var(--color-foreground) 5%, transparent);--shadow-lg: 0 0 0 1px rgba(0, 0, 0, .075), 0 2px 24px rgba(0, 0, 0, .075);--shadow-outline: 0 0 0 1px rgba(0, 0, 0, .1);--transition-colors: color, background-color, border-color, text-decoration-color, fill, stroke .15s cubic-bezier(.4, 0, .2, 1)}@layer base{*,:before,:after,::backdrop,::file-selector-button{box-sizing:border-box;margin:0;padding:0;border:0 solid}*{outline-color:var(--color-ring)}button,input,select,optgroup,textarea,::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;background-color:transparent;opacity:1}input,select,optgroup,textarea,::file-selector-button{color:inherit;border-radius:0}}.button-module_button{align-items:center;border-radius:var(--radius-sm);border:1px solid transparent;cursor:pointer;display:inline-flex;flex-shrink:0;font-weight:var(--font-weight-medium);font-size:var(--text-sm);gap:calc(var(--spacing) * .5);justify-content:center;outline:none;transition-duration:.1s;transition:var(--transition-colors);letter-spacing:var(--text-base--tracking);white-space:nowrap;height:var(--spacing-8);padding:var(--spacing-2) var(--spacing-3)}.button-module_button:disabled{pointer-events:none;background-color:var(--color-muted);color:var(--color-muted-foreground)}.button-module_button:focus-visible{outline:2px solid var(--color-ring);outline-offset:1.5px}.button-module_primary{background-color:var(--color-primary);color:var(--color-primary-foreground)}.button-module_primary:hover:not(:disabled){background-color:color-mix(in srgb,var(--color-primary) 85%,#000)}.button-module_ghost{background-color:transparent;color:var(--color-foreground)}.button-module_ghost svg{color:var(--color-muted-foreground)}.button-module_ghost:hover:not(:disabled){background:transparent;color:var(--color-primary)}.button-module_ghost:hover:not(:disabled) svg{color:var(--color-foreground)}.button-module_ghost:focus-visible{outline-offset:0}.button-module_outline{box-shadow:var(--shadow-outline);background-color:var(--color-background);height:calc(var(--spacing-8) - 1px)}.button-module_outline:hover:not(:disabled){color:var(--color-primary)}.button-module_outline:focus-visible{outline-offset:2.5px}.button-module_link{background-color:transparent;color:var(--color-primary);font-weight:var(--font-weight-medium)}.button-module_link:hover:not(:disabled){color:color-mix(in srgb,var(--color-primary) 85%,#000)}.button-module_icon{border-radius:var(--radius-xs);height:var(--spacing-8);width:var(--spacing-8);padding:0}.button-module_sm{height:var(--spacing-6);width:var(--spacing-6);padding:0}.button-module_withTextAndIcon{padding-left:var(--spacing-1)}.button-module_button svg{flex-shrink:0;pointer-events:none;height:var(--spacing-6);width:var(--spacing-6)}.CollapsedView-module_button{border-radius:var(--radius-lg);height:var(--spacing-10);width:var(--spacing-10)}.Textarea-module_textarea{display:flex;width:100%;border-radius:var(--radius-md);border:0;background-color:transparent;min-height:var(--spacing-10);padding-left:var(--spacing-3);padding-right:var(--spacing-3);padding-top:var(--spacing-2);padding-bottom:var(--spacing-2);scrollbar-width:none;resize:none}.Textarea-module_textarea::-moz-placeholder{color:var(--color-muted-foreground);font-weight:var(--font-weight-medium)}.Textarea-module_textarea::placeholder{color:var(--color-muted-foreground);font-weight:var(--font-weight-medium)}.Textarea-module_textarea:focus-visible{outline:none}.Textarea-module_textarea:disabled{cursor:not-allowed;opacity:.5}.ChatInput-module_container{display:flex;align-items:end;gap:var(--spacing)}.ChatInput-module_textareaContainer{flex:1;width:100%}.ChatInput-module_actions{display:flex;flex-direction:row;padding-left:var(--spacing);padding-right:var(--spacing);height:var(--spacing-10);gap:var(--spacing);align-items:center}.ChatInput-module_button{border-radius:var(--radius-full)}.ChatHeader-module_container{display:flex;align-items:center;justify-content:flex-end;gap:var(--spacing);cursor:grab}.ChatHeader-module_container:active{cursor:grabbing}.MessageActions-module_container{display:flex;gap:var(--spacing-1);align-items:center;margin-top:var(--spacing-2)}.MessageActions-module_container button[aria-hidden=true]{display:none}.Message-module_message{display:flex;align-items:flex-start;padding:0 var(--spacing-3);color:var(--color-foreground)}.Message-module_message.Message-module_user .Message-module_bubble{background-color:var(--color-muted);max-width:85%;padding:var(--spacing-3) var(--spacing-4);border-radius:var(--radius-xl);border-bottom-right-radius:var(--radius-sm)}.Message-module_message.Message-module_error{color:var(--color-destructive)}.Message-module_content{flex:1;text-align:start;word-break:break-word;white-space:normal}.Message-module_message.Message-module_user .Message-module_content{display:flex;justify-content:flex-end}.Message-module_message p{text-wrap-style:pretty;margin-bottom:var(--spacing-3)}.Message-module_message a{color:var(--color-primary)}.Message-module_message p:last-child{margin-bottom:0}.Message-module_message strong{font-weight:550}.Message-module_message ol,.Message-module_message ul{margin-bottom:var(--spacing-3);padding-left:var(--spacing-5)}.Message-module_message p+:where(ol,ul){margin-top:0}.Message-module_message li{margin-bottom:var(--spacing-2)}.Message-module_message li::marker{font-size:var(--text-sm)}.Message-module_message table{width:100%;margin:12px 0;border-collapse:collapse}.Message-module_message th,.Message-module_message td{padding:8px 12px;border:1px solid #ddd;text-align:left}.Message-module_message th{background-color:var(--color-muted);font-weight:600}.Messages-module_container{display:flex;flex-direction:column;flex:1;padding-top:var(--spacing-2);padding-bottom:var(--spacing-20);gap:var(--spacing-8);overflow-y:auto;height:100%;position:relative;z-index:10}.Messages-module_container [data-role=user]:has(+[data-role=user]),.Messages-module_container [data-role=agent]:has(+[data-role=agent]){margin-bottom:calc(-1 * var(--spacing-6))}.Messages-module_emptyState{display:flex;flex-direction:column;align-items:center;justify-content:center}.Thinking-module_container{display:flex;align-items:center;gap:var(--spacing-2);padding-left:var(--spacing-3);padding-right:var(--spacing-3);color:var(--color-muted-foreground);font-size:var(--text-sm)}.Thinking-module_icon{display:flex;align-items:center;justify-content:center}.Thinking-module_icon svg{width:var(--spacing-4);height:var(--spacing-4)}.Thinking-module_content{background:linear-gradient(90deg,color-mix(in srgb,currentColor 30%,transparent),currentColor,color-mix(in srgb,currentColor 30%,transparent));background-size:200% 100%;background-clip:text;-webkit-background-clip:text;-webkit-text-fill-color:transparent;animation:Thinking-module_shimmer 2s infinite linear 0ms}@keyframes Thinking-module_shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}.Notice-module_container{position:relative;display:flex;align-items:center;min-height:var(--spacing-10);padding:var(--spacing) var(--spacing) var(--spacing) var(--spacing-4);gap:var(--spacing-3);background-color:var(--color-muted);border-radius:var(--radius-sm);color:var(--color-foreground);font-size:var(--text-sm);font-weight:var(--font-weight-medium);line-height:var(--text-sm--line-height)}.Notice-module_containerWithIcon{padding-left:var(--spacing-3)}.Notice-module_content{align-items:center;display:flex;flex:1;gap:var(--spacing);min-width:0}.Notice-module_actions{align-items:center;display:flex;flex-shrink:0;gap:var(--spacing)}.Notice-module_icon{align-items:center;display:flex;flex-shrink:0;justify-content:center}.Notice-module_icon svg{display:block;height:var(--spacing-5);width:var(--spacing-5)}.Notice-module_dismissible{position:absolute;top:calc(var(--spacing) * -1.5);right:calc(var(--spacing) * -1.5);opacity:0;transform:scale(.9);border-radius:var(--radius-full);transition:all .15s ease}.Notice-module_dismissible:focus,.Notice-module_dismissible:focus-visible,.Notice-module_container:hover .Notice-module_dismissible{opacity:1;transform:scale(1)}.Notice-module_dismissible svg{display:block;width:var(--spacing-4);height:var(--spacing-4);background-color:var(--color-muted-foreground);color:var(--color-background);border-radius:inherit;box-shadow:0 0 0 2.5px var(--color-background);opacity:.8}.Notice-module_dismissible:hover svg{opacity:1}.Suggestions-module_container{position:absolute;top:0;left:0;right:0;display:flex;flex-wrap:nowrap;gap:var(--spacing-2);padding:var(--spacing-2) var(--spacing-1\.5);overflow-x:auto;overflow-y:hidden;scrollbar-width:none;-ms-overflow-style:none}.Suggestions-module_container::-webkit-scrollbar{display:none}.ConversationView-module_container{display:flex;flex-direction:column;height:100%;justify-content:flex-end}.ConversationView-module_container.ConversationView-module_withHeader{justify-content:space-between}.ConversationView-module_inputWrapper{position:relative}.ConversationView-module_inputContainer{box-shadow:var(--shadow-sm);padding:var(--spacing-2);background-color:var(--color-background);border-radius:calc(var(--radius-lg) + 1px);color:var(--color-foreground);position:relative;z-index:10;filter:brightness(1.1)}.ConversationView-module_inputContainerInner{display:flex;flex-direction:column;gap:var(--spacing-2)}.Chat-module_container{font-size:var(--text-base);line-height:var(--text-base--line-height);font-weight:400;font-family:var(--font-sans);letter-spacing:var(--text-base--tracking);text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}.Chat-module_container.Chat-module_embedded{height:100%}.Chat-module_container.Chat-module_floating{position:fixed;z-index:50}.Chat-module_container.Chat-module_floating .Chat-module_content{background-color:var(--color-background);color:var(--color-foreground);overflow:hidden;min-height:56px;padding:var(--spacing-2);box-shadow:var(--shadow-lg)}
|