Bug: input and header slots reject plain FCs (same defect as #7126)
Summary
#7126 fixed the chatView slot (PR #7156), but the same defect remains on two sibling slots. Any slot typed SlotValue<typeof X> where X carries namespace statics rejects a plain function component, even though the statics are never used at runtime.
Two slots are still affected:
| Slot | Declared as | Where |
|---|---|---|
input |
SlotValue<typeof CopilotChatInput> |
CopilotChatViewProps slot map, re-exposed on <CopilotChat> |
header |
SlotValue<typeof CopilotModalHeader> |
CopilotSidebarView.tsx:24, CopilotPopupView.tsx:24 |
CopilotChatView, CopilotChatInput and CopilotModalHeader are the three slot targets in react-core/src/v2 that carry statics. Only the first is fixed.
Why it is wrong
renderSlot never reads the statics. It calls React.createElement(slot, props) (packages/react-core/src/v2/lib/slots.tsx). The type demands something the runtime does not use, which forces callers into Object.assign(MyInput, CopilotChatInput) or a cast — exactly the workaround #7126 reported.
Reproduction
Add this as a .test-d.ts under packages/react-core/src/v2/components/chat/__tests__/ and run nx run @copilotkit/react-core:check-types. Both assertions fail on current main.
import { expectTypeOf } from "vitest";
import type React from "react";
import type { CopilotChatProps } from "../CopilotChat";
import type { CopilotChatInputProps } from "../CopilotChatInput";
import type { CopilotModalHeaderProps } from "../CopilotModalHeader";
import type { CopilotSidebarViewProps } from "../CopilotSidebarView";
type InputSlot = NonNullable<CopilotChatProps["input"]>;
type HeaderSlot = NonNullable<CopilotSidebarViewProps["header"]>;
expectTypeOf<React.FC<CopilotChatInputProps>>().toExtend<InputSlot>();
expectTypeOf<React.FC<CopilotModalHeaderProps>>().toExtend<HeaderSlot>();Suggested fix
Follow the shape PR #7156 landed — widen each declaration to the props-based form:
input?: SlotValue<React.ComponentType<CopilotChatInputProps>>;
header?: SlotValue<React.ComponentType<CopilotModalHeaderProps>>;I verified on #7156 that this widening keeps prop checking intact: it still rejects a component demanding a prop the parent never passes, a component with a conflicting prop type, and a non-component object.
Do not fix it generically in SlotValue
This looks like it wants one fix in SlotValue itself, and #7156's first commit tried exactly that. It does not work. Adding ComponentType<ComponentProps<C>> as a union arm puts C in a circular inference position and degrades renderSlot's inference — I measured three new type errors in renderSlot.test.tsx (lines 93, 533, 574). #7156 narrowed to a single slot for this reason. Per-slot widening is the supported path unless someone finds a formulation that preserves inference.
Notes
- Purely a type-level fix. No runtime change.
check-typesenforces.test-d.tsfiles, so please add assertions alongside, as #7156 did.- The internal
Object.assignworkarounds inCopilotSidebar.tsxandCopilotPopup.tsxare now unnecessary forchatViewand can be cleaned up separately.
Source: CopilotKit/CopilotKit