Skip to content

Commit f0d83ef

Browse files
authored
Merge branch 'main' into tyler/beautiful-haslett-a95038
2 parents d53deb7 + dad0735 commit f0d83ef

24 files changed

Lines changed: 2185 additions & 616 deletions

File tree

docs/content/docs/(root)/generative-ui/a2ui.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ description: "Render declarative UI components using the A2UI specification."
55
hideTOC: true
66
---
77
import { IntegrationGrid } from "@/components/content/integration-grid";
8+
import { Callout } from "fumadocs-ui/components/callout";
89

910
## What is this?
1011

1112
A2UI (Agent-to-UI) is a declarative specification for generative UI. It allows agents to render structured UI components using a JSON-based schema, without requiring custom React components for every interaction.
1213

14+
<Callout type="info">
15+
**Free course:** See this pattern built end-to-end in [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
16+
</Callout>
17+
1318
## Choose your AI backend
1419

1520
<IntegrationGrid path="generative-ui/a2ui" />

docs/content/docs/(root)/generative-ui/mcp-apps.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ description: "Render interactive UI components from MCP servers directly in your
55
hideTOC: true
66
---
77
import { IntegrationGrid } from "@/components/content/integration-grid";
8+
import { Callout } from "fumadocs-ui/components/callout";
89

910
## What is this?
1011

1112
MCP Apps are MCP servers that expose tools with associated UI resources. When the agent calls one of these tools, CopilotKit automatically fetches and renders the UI component in the chat — no additional frontend code required.
1213

14+
<Callout type="info">
15+
**Free course:** See this pattern built end-to-end in [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
16+
</Callout>
17+
1318
Key benefits:
1419
- **Zero frontend code** — UI components are served by the MCP server
1520
- **Full interactivity** — Components can use HTML, CSS, and JavaScript

docs/content/docs/(root)/generative-ui/open-generative-ui.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ description: "Let agents generate fully interactive HTML/CSS/JS UIs that stream
55
---
66

77
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
8+
import { Callout } from "fumadocs-ui/components/callout";
89

910
## What is this?
1011

1112
Open Generative UI lets the agent generate complete, sandboxed UI on the fly — HTML, CSS, and JavaScript — and stream it live into the chat. The user sees the interface build in real time: styles apply first, then HTML streams in progressively, and finally JavaScript expressions execute one by one.
1213

14+
<Callout type="info">
15+
**Free course:** See this pattern built end-to-end in [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
16+
</Callout>
17+
1318
Key benefits:
1419
- **No predefined components** — the agent creates any UI it needs, on demand
1520
- **Live streaming** — HTML streams into a preview as it's generated

docs/content/docs/(root)/generative-ui/state-rendering.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ description: Render your agent's state with custom UI components in real-time.
55
hideTOC: true
66
---
77
import { IntegrationGrid } from "@/components/content/integration-grid";
8+
import { Callout } from "fumadocs-ui/components/callout";
89

910
## What is this?
1011

1112
State rendering lets you build UI that reflects your agent's state in real-time. As your agent progresses through nodes and emits state updates, your frontend renders those changes — showing progress, drafts, or intermediate results.
1213

14+
<Callout type="info">
15+
**Free course:** See this pattern built end-to-end in [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
16+
</Callout>
17+
1318
## When should I use this?
1419

1520
Use state rendering when you want to:

docs/content/docs/(root)/generative-ui/tool-rendering.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,16 @@ description: Render your agent's tool calls with custom UI components.
55
hideTOC: true
66
---
77
import { IntegrationGrid } from "@/components/content/integration-grid";
8+
import { Callout } from "fumadocs-ui/components/callout";
89

910
## What is this?
1011

1112
Tool rendering lets you customize how your agent's backend tool calls appear in the chat. Instead of showing raw tool execution, you can render custom React components that display tool arguments, progress, and results.
1213

14+
<Callout type="info">
15+
**Free course:** See this pattern built end-to-end in [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
16+
</Callout>
17+
1318
## When should I use this?
1419

1520
Use tool rendering when you want to:

docs/content/docs/(root)/generative-ui/your-components/display-only.mdx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,16 @@ hideTOC: true
66
---
77
import { IntegrationGrid } from "@/components/content/integration-grid";
88
import { Tabs, Tab } from "fumadocs-ui/components/tabs";
9+
import { Callout } from "fumadocs-ui/components/callout";
910

1011
## What is this?
1112

1213
Display-only generative UI lets you register React components as tools your agent can invoke. When the agent calls the tool, CopilotKit renders your component directly in the chat with the tool's arguments as props — no handler logic or user interaction required.
1314

15+
<Callout type="info">
16+
**Free course:** See this pattern built end-to-end in [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) — a free DeepLearning.AI short course taught by CopilotKit's CEO covering the full Generative UI spectrum (Controlled, Declarative, and Open-Ended).
17+
</Callout>
18+
1419
<Tabs items={['page.tsx', 'chart.tsx']}>
1520
<Tab value="page.tsx">
1621
```tsx

docs/content/docs/learn/generative-ui/index.mdx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ This page covers:
4141

4242
</TwoColumnSection>
4343

44+
<Callout type="info">
45+
**Prefer to learn by building?** [Build Interactive Agents with Generative UI](https://www.deeplearning.ai/short-courses/build-interactive-agents-with-generative-ui/) is a free DeepLearning.AI short course taught by CopilotKit's CEO. It walks through the Controlled, Declarative, and Open-Ended Generative UI patterns end-to-end with React, LangChain, and AG-UI.
46+
</Callout>
47+
4448
---
4549

4650
<div>

examples/v2/react/storybook/stories/CopilotSidebarView.stories.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,22 @@ export const Default: Story = {
3131
},
3232
};
3333

34+
export const RightPosition: Story = {
35+
args: {
36+
autoScroll: true,
37+
position: "right",
38+
width: 480,
39+
},
40+
};
41+
42+
export const LeftPosition: Story = {
43+
args: {
44+
autoScroll: true,
45+
position: "left",
46+
width: 480,
47+
},
48+
};
49+
3450
export const CustomHeader: Story = {
3551
args: {
3652
header: {

packages/react-core/src/v2/components/chat/CopilotSidebar.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@ export type CopilotSidebarProps = Omit<CopilotChatProps, "chatView"> & {
1414
toggleButton?: CopilotSidebarViewProps["toggleButton"];
1515
defaultOpen?: boolean;
1616
width?: number | string;
17+
position?: CopilotSidebarViewProps["position"];
1718
};
1819

1920
export function CopilotSidebar({
2021
header,
2122
toggleButton,
2223
defaultOpen,
2324
width,
25+
position,
2426
...chatProps
2527
}: CopilotSidebarProps) {
2628
const { checkFeature } = useLicenseContext();
@@ -41,6 +43,7 @@ export function CopilotSidebar({
4143
toggleButton: viewToggleButton,
4244
width: viewWidth,
4345
defaultOpen: viewDefaultOpen,
46+
position: viewPosition,
4447
...restProps
4548
} = viewProps as CopilotSidebarViewProps;
4649

@@ -51,12 +54,13 @@ export function CopilotSidebar({
5154
toggleButton={toggleButton ?? viewToggleButton}
5255
width={width ?? viewWidth}
5356
defaultOpen={defaultOpen ?? viewDefaultOpen}
57+
position={position ?? viewPosition}
5458
/>
5559
);
5660
};
5761

5862
return Object.assign(Component, CopilotChatView);
59-
}, [header, toggleButton, width, defaultOpen]);
63+
}, [header, toggleButton, width, defaultOpen, position]);
6064

6165
return (
6266
<>

packages/react-core/src/v2/components/chat/CopilotSidebarView.tsx

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,15 @@ export type CopilotSidebarViewProps = CopilotChatViewProps & {
2121
toggleButton?: SlotValue<typeof CopilotChatToggleButton>;
2222
width?: number | string;
2323
defaultOpen?: boolean;
24+
position?: "left" | "right";
2425
};
2526

2627
export function CopilotSidebarView({
2728
header,
2829
toggleButton,
2930
width,
3031
defaultOpen = true,
32+
position = "right",
3133
...props
3234
}: CopilotSidebarViewProps) {
3335
return (
@@ -36,6 +38,7 @@ export function CopilotSidebarView({
3638
header={header}
3739
toggleButton={toggleButton}
3840
width={width}
41+
position={position}
3942
{...props}
4043
/>
4144
</CopilotChatConfigurationProvider>
@@ -46,6 +49,7 @@ function CopilotSidebarViewInternal({
4649
header,
4750
toggleButton,
4851
width,
52+
position = "right",
4953
...props
5054
}: Omit<CopilotSidebarViewProps, "defaultOpen">) {
5155
const configuration = useCopilotChatConfiguration();
@@ -118,29 +122,34 @@ function CopilotSidebarViewInternal({
118122
return;
119123
if (!window.matchMedia("(min-width: 768px)").matches) return;
120124

125+
const marginStyleProp =
126+
position === "left" ? "marginInlineStart" : "marginInlineEnd";
127+
const transitionCssProp =
128+
position === "left" ? "margin-inline-start" : "margin-inline-end";
129+
121130
if (isSidebarOpen) {
122131
if (hasMounted.current) {
123-
document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
132+
document.body.style.transition = `${transitionCssProp} ${SIDEBAR_TRANSITION_MS}ms ease`;
124133
}
125-
document.body.style.marginInlineEnd = widthToMargin(sidebarWidth);
134+
document.body.style[marginStyleProp] = widthToMargin(sidebarWidth);
126135
} else if (hasMounted.current) {
127-
document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
128-
document.body.style.marginInlineEnd = "";
136+
document.body.style.transition = `${transitionCssProp} ${SIDEBAR_TRANSITION_MS}ms ease`;
137+
document.body.style[marginStyleProp] = "";
129138
}
130139

131140
hasMounted.current = true;
132141

133142
return () => {
134-
document.body.style.marginInlineEnd = "";
143+
document.body.style[marginStyleProp] = "";
135144
document.body.style.transition = "";
136145
};
137-
}, [isSidebarOpen, sidebarWidth]);
146+
}, [isSidebarOpen, sidebarWidth, position]);
138147

139148
const headerElement = renderSlot(header, CopilotModalHeader, {});
140149
const toggleButtonElement = renderSlot(
141150
toggleButton,
142151
CopilotChatToggleButton,
143-
{},
152+
position === "left" ? { className: "cpk:left-6 cpk:right-auto" } : {},
144153
);
145154

146155
return (
@@ -151,18 +160,23 @@ function CopilotSidebarViewInternal({
151160
data-copilotkit
152161
data-testid="copilot-sidebar"
153162
data-copilot-sidebar
163+
data-position={position}
154164
className={cn(
155165
"copilotKitSidebar copilotKitWindow",
156-
"cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex",
166+
"cpk:fixed cpk:top-0 cpk:z-[1200] cpk:flex",
167+
position === "left" ? "cpk:left-0" : "cpk:right-0",
157168
// Height with dvh fallback and safe area support
158169
"cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen",
159170
// Responsive width: full on mobile, custom on desktop
160171
"cpk:w-full",
161-
"cpk:border-l cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl",
172+
position === "left" ? "cpk:border-r" : "cpk:border-l",
173+
"cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl",
162174
"cpk:transition-transform cpk:duration-300 cpk:ease-out",
163175
isSidebarOpen
164176
? "cpk:translate-x-0"
165-
: "cpk:translate-x-full cpk:pointer-events-none",
177+
: position === "left"
178+
? "cpk:-translate-x-full cpk:pointer-events-none"
179+
: "cpk:translate-x-full cpk:pointer-events-none",
166180
)}
167181
style={
168182
{

0 commit comments

Comments
 (0)