ai-design-system 0.1.93 → 0.1.94

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.
@@ -2,9 +2,7 @@ import * as React from "react";
2
2
  import type { Meta, StoryObj } from "@storybook/react";
3
3
  import { TaskQueue } from "./TaskQueue";
4
4
  import type { TaskItem } from "./interfaces";
5
- import { PromptInput } from "@/components/composites/PromptInput";
6
5
  import { Button } from "@/components/primitives/Button";
7
- import { Icon } from "@/components/primitives/Icon";
8
6
 
9
7
  const meta: Meta<typeof TaskQueue> = {
10
8
  title: "Composites/TaskQueue",
@@ -90,41 +88,6 @@ export const MultipleTasks: Story = {
90
88
  },
91
89
  };
92
90
 
93
- /**
94
- * Docked with PromptInput — Exact recreation of the full antigravity bottom panel
95
- * seen in 2.1-jobs.png. Shows TaskQueue flush atop PromptInput.
96
- */
97
- export const DockedWithPromptInput: Story = {
98
- render: () => {
99
- return (
100
- <div className="max-w-2xl mx-auto w-full p-4 flex flex-col">
101
- <TaskQueue
102
- tasks={singleRunningTask}
103
- variant="docked"
104
- onStop={(id) => console.log(`Stopped task ${id}`)}
105
- />
106
- <PromptInput
107
- placeholder="Ask anything, @ to mention, / for actions"
108
- onSubmit={(message) => console.log("Submitted:", message)}
109
- tools={
110
- <div className="flex items-center gap-1.5 text-xs text-muted-foreground">
111
- <Button
112
- variant="ghost"
113
- size="sm"
114
- className="h-7 px-2 text-xs font-normal gap-1 hover:text-foreground"
115
- type="button"
116
- >
117
- <span>Gemini 3.8 Flash High</span>
118
- <Icon name="chevron-down" size="xs" />
119
- </Button>
120
- </div>
121
- }
122
- className="rounded-t-none rounded-b-2xl border-t-0 border border-neutral-600 bg-background shadow-sm"
123
- />
124
- </div>
125
- );
126
- },
127
- };
128
91
 
129
92
  /**
130
93
  * Collapsed state — Collapsed header showing the summary count and chevron.
@@ -10,6 +10,7 @@
10
10
  import type { RefinementMessage } from './ChatPanel'
11
11
  import type { FileChangeData } from '@/components/composites/FileQueue'
12
12
  import type { ActionRequest } from '@/components/composites/ApprovalCard'
13
+ import type { TaskItem } from '@/components/composites/TaskQueue'
13
14
 
14
15
  /**
15
16
  * Sample conversation history for input state
@@ -224,3 +225,30 @@ export const sampleFileChanges: FileChangeData[] = [
224
225
  path: 'src/components/primitives/Button/button-accessibility.test.tsx',
225
226
  },
226
227
  ]
228
+
229
+ export const sampleRunningTasks: TaskItem[] = [
230
+ {
231
+ id: 'task-1',
232
+ command: 'npm install',
233
+ status: 'running',
234
+ },
235
+ ]
236
+
237
+ export const sampleMultipleTasks: TaskItem[] = [
238
+ {
239
+ id: 'task-1',
240
+ command: 'npm install',
241
+ status: 'running',
242
+ },
243
+ {
244
+ id: 'task-2',
245
+ command: 'npm run build',
246
+ status: 'queued',
247
+ },
248
+ {
249
+ id: 'task-3',
250
+ command: 'git push origin main',
251
+ status: 'queued',
252
+ },
253
+ ]
254
+
@@ -8,6 +8,8 @@ import {
8
8
  sampleFileChanges,
9
9
  approvalQuestionRequest,
10
10
  approvalMultiQuestionRequest,
11
+ sampleRunningTasks,
12
+ sampleMultipleTasks,
11
13
  } from "./ChatPanel.mocks";
12
14
  import * as React from "react";
13
15
 
@@ -214,3 +216,60 @@ export const WithStateManagement: Story = {
214
216
  },
215
217
  },
216
218
  };
219
+
220
+ /**
221
+ * With Running Task — Recreates 2.1-jobs.png bottom panel with TaskQueue docked flush above PromptInput.
222
+ */
223
+ export const WithRunningTask: Story = {
224
+ args: {
225
+ messages: inputStateMessages,
226
+ tasks: sampleRunningTasks,
227
+ placeholder: "Ask anything, @ to mention, / for actions",
228
+ onSubmit: (message: PromptInputMessage) => {
229
+ console.log("Submitted:", message);
230
+ },
231
+ onTaskStop: (id: string) => {
232
+ console.log(`Stopped task ${id}`);
233
+ },
234
+ },
235
+ parameters: {
236
+ docs: {
237
+ description: {
238
+ story:
239
+ "ChatPanel displaying an active background running task (npm install) docked directly above PromptInput, reproducing the antigravity inspiration from 2.1-jobs.png.",
240
+ },
241
+ },
242
+ },
243
+ };
244
+
245
+ /**
246
+ * With Multiple Tasks — Running task and queued tasks docked above PromptInput.
247
+ */
248
+ export const WithMultipleTasks: Story = {
249
+ args: {
250
+ messages: inputStateMessages,
251
+ tasks: sampleMultipleTasks,
252
+ placeholder: "Ask anything, @ to mention, / for actions",
253
+ onSubmit: (message: PromptInputMessage) => {
254
+ console.log("Submitted:", message);
255
+ },
256
+ onTaskStop: (id: string) => {
257
+ console.log(`Stopped task ${id}`);
258
+ },
259
+ onTaskCancel: (id: string) => {
260
+ console.log(`Cancelled task ${id}`);
261
+ },
262
+ onTaskStopAll: () => {
263
+ console.log("Stopped all tasks");
264
+ },
265
+ },
266
+ parameters: {
267
+ docs: {
268
+ description: {
269
+ story:
270
+ "ChatPanel displaying multiple running and queued tasks docked directly above PromptInput.",
271
+ },
272
+ },
273
+ },
274
+ };
275
+
@@ -4,7 +4,9 @@ import * as React from "react";
4
4
  import { AIConversation } from "@/components/blocks/AIConversation";
5
5
  import { FileChangeQueue } from "@/components/blocks/FileChangeQueue";
6
6
  import { PromptInput, type PromptInputContextProps } from "@/components/composites/PromptInput";
7
+ import { TaskQueue, type TaskItem } from "@/components/composites/TaskQueue";
7
8
  import { ApprovalCard } from "@/components/composites/ApprovalCard";
9
+ import { cn } from "@/lib/utils";
8
10
  import type { ToolCall } from "@/components/composites/ToolCallDisplay";
9
11
  import type { SubAgent } from "@/components/composites/AgentIndicator";
10
12
  import type { FileChangeData } from "@/components/composites/FileQueue";
@@ -168,6 +170,30 @@ export interface ChatPanelProps {
168
170
  isSavingWorkspace?: boolean;
169
171
  /** Context window usage configuration for the prompt input */
170
172
  context?: PromptInputContextProps;
173
+ /**
174
+ * Background tasks or jobs currently running or queued
175
+ */
176
+ tasks?: TaskItem[];
177
+ /**
178
+ * Handler when a task is stopped
179
+ */
180
+ onTaskStop?: (taskId: string) => void;
181
+ /**
182
+ * Handler when a queued task is cancelled
183
+ */
184
+ onTaskCancel?: (taskId: string) => void;
185
+ /**
186
+ * Handler when a failed task is retried
187
+ */
188
+ onTaskRetry?: (taskId: string) => void;
189
+ /**
190
+ * Handler to stop all tasks
191
+ */
192
+ onTaskStopAll?: () => void;
193
+ /**
194
+ * Handler when a task item is clicked (e.g. to inspect terminal output or logs)
195
+ */
196
+ onTaskClick?: (task: TaskItem) => void;
171
197
  }
172
198
 
173
199
  /**
@@ -205,6 +231,12 @@ export const ChatPanel = React.memo<ChatPanelProps>(
205
231
  isCurrentVersionSaved,
206
232
  isSavingWorkspace,
207
233
  context,
234
+ tasks = [],
235
+ onTaskStop,
236
+ onTaskCancel,
237
+ onTaskRetry,
238
+ onTaskStopAll,
239
+ onTaskClick,
208
240
  }) => {
209
241
  // File change queue state
210
242
  const [fileChangeState, setFileChangeState] = React.useState<
@@ -379,7 +411,18 @@ export const ChatPanel = React.memo<ChatPanelProps>(
379
411
  isSavingWorkspace={isSavingWorkspace}
380
412
  className="flex-1 min-h-0"
381
413
  />
382
- <div className="sticky bottom-0 z-10 p-4 bg-gradient-to-t from-card via-card to-transparent pt-6">
414
+ <div className="sticky bottom-0 z-10 p-4 bg-gradient-to-t from-card via-card to-transparent pt-6 flex flex-col">
415
+ {tasks.length > 0 && !dialog && (
416
+ <TaskQueue
417
+ tasks={tasks}
418
+ variant="docked"
419
+ onStop={onTaskStop}
420
+ onCancel={onTaskCancel}
421
+ onRetry={onTaskRetry}
422
+ onStopAll={onTaskStopAll}
423
+ onTaskClick={onTaskClick}
424
+ />
425
+ )}
383
426
  <PromptInput
384
427
  dialog={dialog}
385
428
  placeholder={placeholder}
@@ -389,7 +432,12 @@ export const ChatPanel = React.memo<ChatPanelProps>(
389
432
  loading={isAgentRunning}
390
433
  onStop={onStop}
391
434
  context={context}
392
- className="rounded-2xl border border-neutral-600 bg-background shadow-sm overflow-hidden"
435
+ className={cn(
436
+ "border border-neutral-600 bg-background shadow-sm overflow-hidden",
437
+ tasks.length > 0 && !dialog
438
+ ? "rounded-t-none rounded-b-2xl border-t-0"
439
+ : "rounded-2xl"
440
+ )}
393
441
  />
394
442
  </div>
395
443
  </div>