ai-design-system 0.1.49 → 0.1.51

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.
Files changed (35) hide show
  1. package/components/blocks/WorkflowCanvas/WorkflowCanvas.tsx +1 -15
  2. package/components/composites/AdjustableLayout/AdjustableLayout.tsx +35 -17
  3. package/components/composites/AppHeader/AppHeader.tsx +16 -2
  4. package/components/composites/AppHeader/interfaces.ts +1 -0
  5. package/components/composites/ChatToggleButton/ChatToggleButton.stories.tsx +31 -0
  6. package/components/composites/ChatToggleButton/ChatToggleButton.tsx +26 -0
  7. package/components/composites/ChatToggleButton/index.ts +2 -0
  8. package/components/composites/DashboardChart/DashboardChart.stories.tsx +18 -0
  9. package/components/composites/DashboardHeader/DashboardHeader.stories.tsx +18 -0
  10. package/components/composites/FilePreviewDialog/FilePreviewDialog.stories.tsx +18 -0
  11. package/components/composites/FormReports/FormReports.stories.tsx +18 -0
  12. package/components/composites/LayoutProvider/LayoutProvider.stories.tsx +18 -0
  13. package/components/composites/LoadingShimmer/LoadingShimmer.stories.tsx +18 -0
  14. package/components/composites/ModeSwitcher/ModeSwitcher.stories.tsx +18 -0
  15. package/components/composites/OrchestratorMessage/OrchestratorMessage.tsx +15 -5
  16. package/components/composites/ProjectSwitcher/ProjectSwitcher.stories.tsx +18 -0
  17. package/components/composites/TriggerNode/TriggerNode.stories.tsx +18 -0
  18. package/components/composites/UserMessage/UserMessage.tsx +15 -5
  19. package/components/composites/WorkflowRunObservabilityPanel/WorkflowRunObservabilityPanel.stories.tsx +18 -0
  20. package/components/features/PageLayout/PageLayout.stories.tsx +75 -63
  21. package/components/features/PageLayout/PageLayout.tsx +73 -4
  22. package/components/features/PageLayout/usePageLayout.mock.ts +9 -0
  23. package/components/features/WorkflowObservabilityFeature/WorkflowObservabilityFeature.stories.tsx +18 -22
  24. package/components/index.ts +3 -0
  25. package/components/primitives/Toaster/Toaster.stories.tsx +366 -0
  26. package/components/primitives/Toaster/Toaster.tsx +6 -0
  27. package/components/primitives/Toaster/index.ts +6 -0
  28. package/components/primitives/index.ts +1 -0
  29. package/dist/index.cjs +1669 -1584
  30. package/dist/index.cjs.map +1 -1
  31. package/dist/index.css +6 -0
  32. package/dist/index.d.ts +43 -7
  33. package/dist/index.js +1660 -1583
  34. package/dist/index.js.map +1 -1
  35. package/package.json +1 -1
@@ -6,7 +6,7 @@ import {
6
6
  type Connection,
7
7
  useReactFlow,
8
8
  } from "@xyflow/react";
9
- import { useCallback, useEffect, useRef, useState } from "react";
9
+ import { useCallback, useEffect } from "react";
10
10
  import { Canvas } from "@/components/ai-elements/canvas";
11
11
  import { Connection as ConnectionLine } from "@/components/ai-elements/connection";
12
12
  import { Controls } from "@/components/ai-elements/controls";
@@ -47,18 +47,6 @@ function WorkflowCanvasInner({
47
47
  className,
48
48
  }: WorkflowCanvasProps) {
49
49
  const { fitView } = useReactFlow();
50
- const viewportInitialized = useRef(false);
51
- const [isCanvasReady, setIsCanvasReady] = useState(false);
52
-
53
- useEffect(() => {
54
- if (!viewportInitialized.current && nodes.length > 0) {
55
- setTimeout(() => {
56
- fitView({ maxZoom: 1, minZoom: 0.5, padding: 0.2, duration: 0 });
57
- viewportInitialized.current = true;
58
- setIsCanvasReady(true);
59
- }, 0);
60
- }
61
- }, [nodes.length, fitView]);
62
50
 
63
51
  useEffect(() => {
64
52
  const handleKeyDown = (event: KeyboardEvent) => {
@@ -85,8 +73,6 @@ function WorkflowCanvasInner({
85
73
  className={className}
86
74
  data-testid="workflow-canvas"
87
75
  style={{
88
- opacity: isCanvasReady ? 1 : 0,
89
- transition: "opacity 300ms",
90
76
  width: "100%",
91
77
  height: "100%",
92
78
  }}
@@ -121,26 +121,44 @@ export const AdjustableLayout = React.memo<AdjustableLayoutProps>(
121
121
  const deltaX = currentX - startX
122
122
 
123
123
  const deltaPercent = (deltaX / containerSize) * 100
124
- const newSizes = [...startSizes]
125
124
 
126
- // Adjust sizes of adjacent panels
127
- newSizes[draggingIndex] = Math.max(
128
- sections[draggingIndex].minSize ?? 10,
129
- Math.min(
130
- sections[draggingIndex].maxSize ?? 80,
131
- startSizes[draggingIndex] + deltaPercent
132
- )
133
- )
125
+ const p1 = sections[draggingIndex]
126
+ const p2 = sections[draggingIndex + 1]
134
127
 
135
- newSizes[draggingIndex + 1] = Math.max(
136
- sections[draggingIndex + 1].minSize ?? 10,
137
- Math.min(
138
- sections[draggingIndex + 1].maxSize ?? 80,
139
- startSizes[draggingIndex + 1] - deltaPercent
140
- )
141
- )
128
+ const p1Start = startSizes[draggingIndex]
129
+ const p2Start = startSizes[draggingIndex + 1]
130
+
131
+ const p1Min = p1.minSize ?? 10
132
+ const p1Max = p1.maxSize ?? 80
133
+ const p2Min = p2.minSize ?? 10
134
+ const p2Max = p2.maxSize ?? 80
135
+
136
+ // Calculate how much we can actually change panel 1
137
+ // If deltaPercent > 0, we are growing p1 and shrinking p2
138
+ const maxPositiveDelta = Math.max(0, Math.min(
139
+ p1Max - p1Start, // Space p1 has to grow
140
+ p2Start - p2Min // Space p2 has to shrink
141
+ ))
142
+
143
+ // If deltaPercent < 0, we are shrinking p1 and growing p2
144
+ const maxNegativeDelta = Math.min(0, Math.max(
145
+ p1Min - p1Start, // Space p1 has to shrink (negative)
146
+ p2Start - p2Max // Space p2 has to grow (negative)
147
+ ))
148
+
149
+ // Clamp the delta
150
+ let clampedDelta = deltaPercent
151
+ if (clampedDelta > 0) {
152
+ clampedDelta = Math.min(clampedDelta, maxPositiveDelta)
153
+ } else {
154
+ clampedDelta = Math.max(clampedDelta, maxNegativeDelta)
155
+ }
156
+
157
+ const newSizes = [...startSizes]
158
+ newSizes[draggingIndex] = p1Start + clampedDelta
159
+ newSizes[draggingIndex + 1] = p2Start - clampedDelta
142
160
 
143
- // Normalize to 100%
161
+ // Normalize to 100% just in case of floating point drift
144
162
  const total = newSizes.reduce((sum, size) => sum + size, 0)
145
163
  const normalizedSizes = newSizes.map(size => (size / total) * 100)
146
164
 
@@ -11,6 +11,7 @@ export const AppHeader = React.memo<AppHeaderProps>(({
11
11
  defaultTab,
12
12
  onTabChange,
13
13
  className,
14
+ tabsPosition = 'center',
14
15
  showSidebarToggle = true,
15
16
  showTitle = true
16
17
  }) => {
@@ -30,7 +31,7 @@ export const AppHeader = React.memo<AppHeaderProps>(({
30
31
  </div>
31
32
 
32
33
  <div className="justify-self-center">
33
- {tabs && tabs.length > 0 && (
34
+ {tabsPosition === 'center' && tabs && tabs.length > 0 && (
34
35
  <Tabs defaultValue={defaultTab || tabs[0]?.value} onValueChange={onTabChange}>
35
36
  <TabsList>
36
37
  {tabs.map((tab) => (
@@ -43,7 +44,20 @@ export const AppHeader = React.memo<AppHeaderProps>(({
43
44
  )}
44
45
  </div>
45
46
 
46
- <div className="flex min-w-0 items-center justify-end gap-2">{actions}</div>
47
+ <div className="flex min-w-0 items-center justify-end gap-2">
48
+ {tabsPosition === 'right' && tabs && tabs.length > 0 && (
49
+ <Tabs defaultValue={defaultTab || tabs[0]?.value} onValueChange={onTabChange}>
50
+ <TabsList>
51
+ {tabs.map((tab) => (
52
+ <TabsTrigger key={tab.value} value={tab.value}>
53
+ {tab.label}
54
+ </TabsTrigger>
55
+ ))}
56
+ </TabsList>
57
+ </Tabs>
58
+ )}
59
+ {actions}
60
+ </div>
47
61
  </div>
48
62
  </header>
49
63
  )
@@ -11,6 +11,7 @@ export interface AppHeaderProps {
11
11
  tabs?: TabItem[];
12
12
  defaultTab?: string;
13
13
  onTabChange?: (value: string) => void;
14
+ tabsPosition?: 'center' | 'right';
14
15
  className?: string;
15
16
  showSidebarToggle?: boolean;
16
17
  showTitle?: boolean;
@@ -0,0 +1,31 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { ChatToggleButton } from './ChatToggleButton'
3
+ import { fn } from '@storybook/test'
4
+
5
+ const meta = {
6
+ title: 'Composites/ChatToggleButton',
7
+ component: ChatToggleButton,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ layout: 'centered',
11
+ },
12
+ } satisfies Meta<typeof ChatToggleButton>
13
+
14
+ export default meta
15
+ type Story = StoryObj<typeof meta>
16
+
17
+ export const Default: Story = {
18
+ args: {
19
+ isOpen: true,
20
+ label: "Hide Chat",
21
+ onClick: fn(),
22
+ },
23
+ }
24
+
25
+ export const Closed: Story = {
26
+ args: {
27
+ isOpen: false,
28
+ label: "Show Chat",
29
+ onClick: fn(),
30
+ },
31
+ }
@@ -0,0 +1,26 @@
1
+ import { Button, type ButtonProps } from "@/components/primitives/Button"
2
+ import { Icon } from "@/components/primitives/Icon"
3
+ import * as React from "react"
4
+
5
+ export interface ChatToggleButtonProps extends Omit<ButtonProps, "children"> {
6
+ isOpen?: boolean
7
+ label?: string
8
+ }
9
+
10
+ export function ChatToggleButton({
11
+ isOpen = true,
12
+ label = "Hide Chat",
13
+ className,
14
+ ...props
15
+ }: ChatToggleButtonProps) {
16
+ return (
17
+ <Button
18
+ variant="ghost"
19
+ className={`-ml-2 h-8 text-muted-foreground hover:text-foreground ${className ?? ""}`}
20
+ {...props}
21
+ >
22
+ <Icon name="panel-left" size="sm" />
23
+ {label}
24
+ </Button>
25
+ )
26
+ }
@@ -0,0 +1,2 @@
1
+ export { ChatToggleButton } from "./ChatToggleButton"
2
+ export type { ChatToggleButtonProps } from "./ChatToggleButton"
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { DashboardChart } from './DashboardChart'
3
+
4
+ const meta = {
5
+ title: 'Composites/DashboardChart',
6
+ component: DashboardChart,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof DashboardChart>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { DashboardHeader } from './DashboardHeader'
3
+
4
+ const meta = {
5
+ title: 'Composites/DashboardHeader',
6
+ component: DashboardHeader,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof DashboardHeader>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { FilePreviewDialog } from './FilePreviewDialog'
3
+
4
+ const meta = {
5
+ title: 'Composites/FilePreviewDialog',
6
+ component: FilePreviewDialog,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof FilePreviewDialog>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { FormReports } from './FormReports'
3
+
4
+ const meta = {
5
+ title: 'Composites/FormReports',
6
+ component: FormReports,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof FormReports>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { LayoutProvider } from './LayoutProvider'
3
+
4
+ const meta = {
5
+ title: 'Composites/LayoutProvider',
6
+ component: LayoutProvider,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof LayoutProvider>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { LoadingShimmer } from './LoadingShimmer'
3
+
4
+ const meta = {
5
+ title: 'Composites/LoadingShimmer',
6
+ component: LoadingShimmer,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof LoadingShimmer>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { ModeSwitcher } from './ModeSwitcher'
3
+
4
+ const meta = {
5
+ title: 'Composites/ModeSwitcher',
6
+ component: ModeSwitcher,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof ModeSwitcher>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -1,4 +1,9 @@
1
1
  import * as React from "react"
2
+ import {
3
+ Avatar,
4
+ AvatarFallback,
5
+ } from "@/components/primitives/Avatar"
6
+ import { Icon } from "@/components/primitives/Icon"
2
7
  import {
3
8
  Message,
4
9
  MessageContent,
@@ -49,11 +54,16 @@ export const OrchestratorMessage = React.memo<OrchestratorMessageProps>(
49
54
 
50
55
  return (
51
56
  <Message from="assistant">
52
- {showAvatar && (
53
- <MessageAvatar
54
- src={message.avatarSrc || "/coordinator-avatar.png"}
55
- name={message.avatarName || "Coordinator"}
56
- />
57
+ {showAvatar && (message.avatarSrc
58
+ ? <MessageAvatar
59
+ src={message.avatarSrc}
60
+ name={message.avatarName || "Coordinator"}
61
+ />
62
+ : <Avatar className="size-8 ring-1 ring-border">
63
+ <AvatarFallback>
64
+ <Icon name="bot" />
65
+ </AvatarFallback>
66
+ </Avatar>
57
67
  )}
58
68
 
59
69
  <div className="flex-1 min-w-0">
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { ProjectSwitcher } from './ProjectSwitcher'
3
+
4
+ const meta = {
5
+ title: 'Composites/ProjectSwitcher',
6
+ component: ProjectSwitcher,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof ProjectSwitcher>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { TriggerNode } from './TriggerNode'
3
+
4
+ const meta = {
5
+ title: 'Composites/TriggerNode',
6
+ component: TriggerNode,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof TriggerNode>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -1,4 +1,9 @@
1
1
  import * as React from "react"
2
+ import {
3
+ Avatar,
4
+ AvatarFallback,
5
+ } from "@/components/primitives/Avatar"
6
+ import { Icon } from "@/components/primitives/Icon"
2
7
  import {
3
8
  Message,
4
9
  MessageContent,
@@ -37,11 +42,16 @@ export const UserMessage = React.memo<UserMessageProps>(
37
42
  ({ message, showAvatar = true }) => {
38
43
  return (
39
44
  <Message from="user">
40
- {showAvatar && (
41
- <MessageAvatar
42
- src={message.avatarSrc || "/user-avatar.png"}
43
- name={message.avatarName || "User"}
44
- />
45
+ {showAvatar && (message.avatarSrc
46
+ ? <MessageAvatar
47
+ src={message.avatarSrc}
48
+ name={message.avatarName || "User"}
49
+ />
50
+ : <Avatar className="size-8 ring-1 ring-border">
51
+ <AvatarFallback>
52
+ <Icon name="user" />
53
+ </AvatarFallback>
54
+ </Avatar>
45
55
  )}
46
56
  <MessageContent variant="contained">{message.content}</MessageContent>
47
57
  </Message>
@@ -0,0 +1,18 @@
1
+ import type { Meta, StoryObj } from '@storybook/react'
2
+ import { WorkflowRunObservabilityPanel } from './WorkflowRunObservabilityPanel'
3
+
4
+ const meta = {
5
+ title: 'Composites/WorkflowRunObservabilityPanel',
6
+ component: WorkflowRunObservabilityPanel,
7
+ tags: ['autodocs'],
8
+ parameters: {
9
+ layout: 'centered',
10
+ },
11
+ } satisfies Meta<typeof WorkflowRunObservabilityPanel>
12
+
13
+ export default meta
14
+ type Story = StoryObj<typeof meta>
15
+
16
+ export const Default: Story = {
17
+ args: {} as any,
18
+ }
@@ -1,3 +1,4 @@
1
+ import * as React from 'react'
1
2
  import type { Meta, StoryObj } from '@storybook/react'
2
3
  import { PageLayout } from './PageLayout'
3
4
  import { usePageLayoutMock, usePageLayoutStoryActionsMock } from './usePageLayout.mock'
@@ -12,7 +13,6 @@ import { WorkflowBuilder } from '../WorkflowBuilder/WorkflowBuilder'
12
13
  import { RefinementPanel } from '../RefinementPanel/RefinementPanel'
13
14
  import { mockEdges, mockNodes, mockVersions } from '../WorkflowBuilder/WorkflowBuilder.mocks'
14
15
  import { DashboardFeature } from '../DashboardFeature/DashboardFeature'
15
- import { ProjectSwitcher } from '@/components/composites/ProjectSwitcher'
16
16
  import { useDashboardIntegrationMock } from './useDashboardIntegration.mock'
17
17
 
18
18
  const meta = {
@@ -110,76 +110,88 @@ export const WithStateManagement: Story = {
110
110
  return (
111
111
  <PageLayout
112
112
  sidebar={mockSidebarConfig}
113
- header={{
114
- title: (
115
- <ProjectSwitcher
116
- projects={dashboardState.projects}
117
- selectedProjectId={dashboardState.selectedProjectId}
118
- onSelectProject={dashboardState.onSelectProject}
119
- onCreateProject={dashboardState.onCreateProjectClick}
120
- />
121
- ),
122
- actions: mockHeaderConfigWithTabs.actions,
123
- tabs: headerTabs,
124
- defaultTab: activeTab || undefined,
125
- onTabChange: dashboardState.onTabChange,
113
+ header={{ title: '' }} // Intercepted by projectSwitcherProps
114
+ projectSwitcherProps={{
115
+ projects: dashboardState.projects,
116
+ selectedProjectId: dashboardState.selectedProjectId,
117
+ onSelectProject: dashboardState.onSelectProject,
118
+ onCreateProject: dashboardState.onCreateProjectClick
119
+ }}
120
+ chatToggleProps={{
121
+ isOpen: actions.isChatOpen,
122
+ onClick: actions.toggleChat
126
123
  }}
127
124
  isLoading={layoutState.isLoading}
128
125
  loadingMessage={layoutState.loadingMessage}
129
126
  defaultSidebarOpen={layoutState.isSidebarOpen}
130
127
  layoutSections={
131
- activeTab === 'dashboard' || !hasProjects ? undefined : [
132
- {
133
- id: 'workflow-builder',
134
- content: (
135
- <WorkflowBuilder
136
- workflowName="Order Processing Workflow"
137
- currentVersionId="v4"
138
- versions={mockVersions}
139
- nodes={mockNodes}
140
- edges={mockEdges}
141
- onVersionSelect={actions.onVersionSelect}
142
- onSave={actions.onSave}
143
- onUndo={actions.onUndo}
144
- onRedo={actions.onRedo}
145
- hasUnsavedChanges={true}
146
- canUndo={true}
147
- canRedo={false}
148
- showMinimap={true}
149
- interactive={true}
150
- />
151
- ),
152
- defaultSize: 60,
153
- },
154
- {
155
- id: 'refinement-panel',
156
- content: (
157
- <RefinementPanel
158
- messages={mockPageLayoutRefinementMessages}
159
- fileChanges={mockPageLayoutFileChanges}
160
- onSubmit={actions.onSubmit}
161
- onApprove={actions.onApprove}
162
- onReject={actions.onReject}
163
- placeholder="Ask for workflow optimizations or describe changes..."
164
- />
165
- ),
166
- defaultSize: 40,
167
- header: {
168
- tabs: [
169
- { value: 'chat', label: 'Chat' },
170
- { value: 'changes', label: 'Changes' },
171
- { value: 'history', label: 'History' },
172
- ],
173
- defaultTab: 'chat',
174
- showSidebarToggle: false,
175
- showTitle: false,
128
+ !hasProjects ? undefined : [
129
+ ...(actions.isChatOpen ? [{
130
+ id: 'refinement-panel',
131
+ content: (
132
+ <RefinementPanel
133
+ messages={mockPageLayoutRefinementMessages}
134
+ fileChanges={mockPageLayoutFileChanges}
135
+ onSubmit={actions.onSubmit}
136
+ onApprove={actions.onApprove}
137
+ onReject={actions.onReject}
138
+ placeholder="Ask for workflow optimizations or describe changes..."
139
+ />
140
+ ),
141
+ defaultSize: 30,
142
+ minSize: 30,
143
+ maxSize: 40,
144
+ header: {
145
+ tabs: [
146
+ { value: 'chat', label: 'Chat' },
147
+ { value: 'changes', label: 'Changes' },
148
+ { value: 'history', label: 'History' },
149
+ ],
150
+ defaultTab: 'chat',
151
+ showSidebarToggle: false,
152
+ showTitle: false,
153
+ },
154
+ }] : []),
155
+ {
156
+ id: 'main-content',
157
+ content: activeTab === 'dashboard' ? (
158
+ <DashboardFeature {...dashboardState.dashboardProps} />
159
+ ) : (
160
+ <WorkflowBuilder
161
+ workflowName="Order Processing Workflow"
162
+ currentVersionId="v4"
163
+ versions={mockVersions}
164
+ nodes={mockNodes}
165
+ edges={mockEdges}
166
+ onVersionSelect={actions.onVersionSelect}
167
+ onSave={actions.onSave}
168
+ onUndo={actions.onUndo}
169
+ onRedo={actions.onRedo}
170
+ hasUnsavedChanges={true}
171
+ canUndo={true}
172
+ canRedo={false}
173
+ showMinimap={true}
174
+ interactive={true}
175
+ />
176
+ ),
177
+ defaultSize: actions.isChatOpen ? 70 : 100,
178
+ minSize: 60,
179
+ maxSize: 70,
180
+ header: {
181
+ // title is intercepted by chatToggleProps
182
+ showTitle: true,
183
+ showSidebarToggle: false,
184
+ tabs: headerTabs,
185
+ defaultTab: activeTab || undefined,
186
+ onTabChange: dashboardState.onTabChange,
187
+ tabsPosition: 'right',
188
+ actions: mockHeaderConfigWithTabs.actions,
189
+ }
176
190
  },
177
- },
178
- ]}
191
+ ]}
179
192
  layoutStorageKey="page-layout-workflow-refinement"
180
- dragHandleColor="primary"
181
193
  >
182
- {(activeTab === 'dashboard' || !hasProjects) && (
194
+ {!hasProjects && (
183
195
  <DashboardFeature {...dashboardState.dashboardProps} />
184
196
  )}
185
197
  </PageLayout>