@copilotkit/react-ui 1.66.4 → 1.67.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@copilotkit/react-ui",
3
- "version": "1.66.4",
3
+ "version": "1.67.1",
4
4
  "private": false,
5
5
  "keywords": [
6
6
  "ai",
@@ -49,9 +49,9 @@
49
49
  "rehype-sanitize": "^6.0.0",
50
50
  "remark-gfm": "^4.0.1",
51
51
  "remark-math": "^6.0.0",
52
- "@copilotkit/react-core": "1.66.4",
53
- "@copilotkit/shared": "1.66.4",
54
- "@copilotkit/runtime-client-gql": "1.66.4"
52
+ "@copilotkit/runtime-client-gql": "1.67.1",
53
+ "@copilotkit/shared": "1.67.1",
54
+ "@copilotkit/react-core": "1.67.1"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/react": "^19.1.0",
@@ -64,8 +64,8 @@
64
64
  "tsdown": "^0.20.3",
65
65
  "typescript": "^5.2.3",
66
66
  "vitest": "^3.2.4",
67
- "tsconfig": "1.4.12",
68
- "tailwind-config": "1.4.12"
67
+ "tailwind-config": "1.4.12",
68
+ "tsconfig": "1.4.12"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "react": "^18 || ^19 || ^19.0.0-rc"
@@ -72,7 +72,27 @@ import React, { useState } from "react";
72
72
  import type { CopilotModalProps } from "./Modal";
73
73
  import { CopilotModal } from "./Modal";
74
74
 
75
- export function CopilotSidebar(props: CopilotModalProps) {
75
+ export interface CopilotSidebarProps extends CopilotModalProps {
76
+ /**
77
+ * Make the sidebar's content wrapper exactly one viewport tall, so children
78
+ * can use `height: 100%` (or `flex: 1`) to fill the screen.
79
+ *
80
+ * Off by default: the wrappers are auto-height, so page content flows
81
+ * normally and percentage heights on children collapse to content height.
82
+ *
83
+ * ```tsx
84
+ * <CopilotSidebar fullHeightChildren>
85
+ * <div style={{ height: "100%" }}>...</div>
86
+ * </CopilotSidebar>
87
+ * ```
88
+ */
89
+ fullHeightChildren?: boolean;
90
+ }
91
+
92
+ export function CopilotSidebar({
93
+ fullHeightChildren = false,
94
+ ...props
95
+ }: CopilotSidebarProps) {
76
96
  props = {
77
97
  ...props,
78
98
  className: props.className
@@ -88,8 +108,16 @@ export function CopilotSidebar(props: CopilotModalProps) {
88
108
  setExpandedClassName(open ? "sidebarExpanded" : "");
89
109
  };
90
110
 
111
+ const contentWrapperClassName = [
112
+ "copilotKitSidebarContentWrapper",
113
+ expandedClassName,
114
+ fullHeightChildren ? "copilotKitSidebarFullHeightChildren" : "",
115
+ ]
116
+ .filter(Boolean)
117
+ .join(" ");
118
+
91
119
  return (
92
- <div className={`copilotKitSidebarContentWrapper ${expandedClassName}`}>
120
+ <div className={contentWrapperClassName}>
93
121
  <CopilotModal {...props} {...{ onSetOpen }}>
94
122
  {props.children}
95
123
  </CopilotModal>
@@ -1,6 +1,7 @@
1
1
  export * from "./props";
2
2
  export { CopilotPopup } from "./Popup";
3
3
  export { CopilotSidebar } from "./Sidebar";
4
+ export type { CopilotSidebarProps } from "./Sidebar";
4
5
  export { CopilotChat } from "./Chat";
5
6
  export { CopilotModal } from "./Modal";
6
7
  export type { CopilotModalProps } from "./Modal";
@@ -0,0 +1,59 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import * as fs from "node:fs";
3
+ import * as path from "node:path";
4
+
5
+ const sidebarCss = fs.readFileSync(
6
+ path.resolve(__dirname, "sidebar.css"),
7
+ "utf-8",
8
+ );
9
+ const sidebarTsx = fs.readFileSync(
10
+ path.resolve(__dirname, "../components/chat/Sidebar.tsx"),
11
+ "utf-8",
12
+ );
13
+
14
+ /**
15
+ * Regression guard for #261: children of `CopilotSidebar` could not use
16
+ * `height: 100%`, because both wrappers around them are auto-height blocks.
17
+ * The fix is opt-in, so the guard has two halves — the escape hatch works,
18
+ * and it stays off for everyone who didn't ask for it.
19
+ */
20
+ describe("sidebar full-height children opt-in", () => {
21
+ const fullHeightRule =
22
+ /\.copilotKitSidebarContentWrapper\.copilotKitSidebarFullHeightChildren\s*\{([^}]*)\}/;
23
+ const childrenWrapperRule =
24
+ /\.copilotKitSidebarContentWrapper\.copilotKitSidebarFullHeightChildren\s*>\s*\.copilotKitModalChildrenWrapper\s*\{([^}]*)\}/;
25
+
26
+ it("gives the content wrapper a definite height children can resolve against", () => {
27
+ const [, body] = sidebarCss.match(fullHeightRule) ?? [];
28
+ expect(body).toBeDefined();
29
+ expect(body).toContain("display: flex");
30
+ expect(body).toContain("flex-direction: column");
31
+ // A viewport unit, not `100%` — `100%` would silently no-op in any app
32
+ // that doesn't declare a height on html/body/#root.
33
+ expect(body).toContain("height: 100dvh");
34
+ expect(body).toContain("height: 100vh");
35
+ expect(body).not.toMatch(/height:\s*100%/);
36
+ });
37
+
38
+ it("lets the children wrapper fill that height without a flex min-height floor", () => {
39
+ const [, body] = sidebarCss.match(childrenWrapperRule) ?? [];
40
+ expect(body).toBeDefined();
41
+ expect(body).toContain("flex: 1 1 auto");
42
+ expect(body).toContain("min-height: 0");
43
+ });
44
+
45
+ it("leaves the default content wrapper auto-height", () => {
46
+ const [, base] =
47
+ sidebarCss.match(/\.copilotKitSidebarContentWrapper\s*\{([^}]*)\}/) ?? [];
48
+ expect(base).toBeDefined();
49
+ expect(base).not.toContain("height");
50
+ expect(base).not.toContain("display");
51
+ });
52
+
53
+ it("applies the modifier class only when fullHeightChildren is set", () => {
54
+ expect(sidebarTsx).toContain("fullHeightChildren = false");
55
+ expect(sidebarTsx).toMatch(
56
+ /fullHeightChildren\s*\?\s*"copilotKitSidebarFullHeightChildren"\s*:\s*""/,
57
+ );
58
+ });
59
+ });
@@ -44,3 +44,30 @@
44
44
  margin-right: 28rem;
45
45
  }
46
46
  }
47
+
48
+ /*
49
+ * Opt-in (via the `fullHeightChildren` prop on `CopilotSidebar`): let children
50
+ * of the sidebar use `height: 100%`.
51
+ *
52
+ * By default both wrappers CopilotSidebar puts around your app are auto-height
53
+ * blocks, so a percentage height on a child has no definite containing block to
54
+ * resolve against and collapses to content height.
55
+ *
56
+ * The viewport unit is deliberate: `height: 100%` here would only resolve if
57
+ * every ancestor (html/body/#root) also declared a height, which react-ui
58
+ * neither sets nor can guarantee. `min-height: 0` on the children wrapper
59
+ * overrides the flex-item `min-height: auto` default so tall content scrolls
60
+ * inside the child instead of stretching the wrapper past the viewport.
61
+ */
62
+ .copilotKitSidebarContentWrapper.copilotKitSidebarFullHeightChildren {
63
+ display: flex;
64
+ flex-direction: column;
65
+ height: 100vh;
66
+ height: 100dvh;
67
+ }
68
+
69
+ .copilotKitSidebarContentWrapper.copilotKitSidebarFullHeightChildren
70
+ > .copilotKitModalChildrenWrapper {
71
+ flex: 1 1 auto;
72
+ min-height: 0;
73
+ }