#Custom sub-components in v2

1 messages · Page 1 of 1 (latest)

warm patrol
#

I am using CopilotChat from @copilotkit/react-core/v2
I have it working using v1 but want to migrate to v2.
Can you share some example on how to use custom sub components, the docs mention using slots but does not give the relevant example.

What I am trying atm using v2:
<CopilotChat input={ChatInput}...

`function ChatInput({
isVisible,
inProgress,
onSend,
onStop,
}: CopilotChatInputProps) {
// custom component

return(
<input>...

<button>)
}`

But TS complains about the types of ChatInput passed to CopilotChat

glad rivetBOT
#

This solution has been AI generated

Your custom input component needs to match the new v2 slot props. In v2, props like inProgress and onSend were renamed. Replace them with isRunning and onSubmitMessage, and wire value/onChange for the input state.

v2 input slot: correct props and example

import { CopilotChat } from "@copilotkit/react-core/v2";
import type { CopilotChatInputProps } from "@copilotkit/react-core/v2";

function ChatInput({
  isRunning,        // v1: inProgress
  onSubmitMessage,  // v1: onSend
  onStop,
  value,
  onChange,
}: CopilotChatInputProps) {
  return (
    <div className="custom-input">
      <input
        value={value}
        onChange={(e) => onChange?.(e.target.value)}
        disabled={isRunning}
        placeholder="Type a message..."
      />
      {isRunning ? (
        <button onClick={onStop}>Stop</button>
      ) : (
        <button onClick={() => onSubmitMessage?.(value || "")}>Send</button>
      )}
    </div>
  );
}

export default function App() {
  return (
    <CopilotChat input={ChatInput} />
  );
}

Why TS was complaining

  • You passed a component expecting v1 props (isVisible, inProgress, onSend).
  • The v2 input slot requires the CopilotChatInputProps shape (isRunning, onSubmitMessage, value, onChange, onStop). Aligning these fixes the type error.

Optional: render-prop composition

If you need full control over layout while keeping slots:

<CopilotChat>
  {({ input }) => (
    <div className="my-layout">
      {/* other UI */}
      {input}
    </div>
  )}
</CopilotChat>

Was this helpful?

If this solution worked for you, please click on the appropriate option below to help us improve:

#

Thank you for confirming that your issue has been resolved! ✅

warm patrol
#

But I cannot still use the ChatInput the way bot suggested.

glad rivetBOT
#

@warm patrol As far as I know, v2 expects input to match the default component's static properties, which is why a standard function component triggers a type error. I believe if you pass it as an object - input={{ component: ChatInput }} - it should resolve the TypeScript issue while handling the state for you.
Give that a try and let me know!

warm patrol
#

I update the Chat component to take props like this which seems to be doing the job:

`<CopilotChat
input={{
children: ChatInput,
disclaimer: Disclaimer,
showDisclaimer: true,
positioning: 'static',
}}
......
/>

type ChatInputProps = {
onSubmitMessage?: (value: string) => void;
onStop?: () => void;
isRunning?: boolean;
value?: string;
disclaimer?: ReactElement;
onChange?: (value: string) => void;
};`