Open, close, and feedback
Open and close the prebuilt chat from your UI, and capture assistant message feedback.
Two common controls for the prebuilt chat are opening it from your own UI and capturing thumbs-up / thumbs-down feedback on assistant messages.
Programmatically open or close the chat#
The modal/open state for <CopilotPopup> and <CopilotSidebar> lives in the
chat configuration context. Read it with useCopilotChatConfiguration() and
call setModalOpen(true | false) from anywhere inside the provider:
import { useCopilotChatConfiguration } from "@copilotkit/react-core/v2";
function OpenChatButton() {
const config = useCopilotChatConfiguration();
// setModalOpen is only present when a provider in the tree owns modal state
// (the prebuilt CopilotPopup / CopilotSidebar create it for you).
if (!config?.setModalOpen) return null;
return (
<button onClick={() => config.setModalOpen(true)}>
Ask the assistant
</button>
);
}To toggle, read config.isModalOpen and flip it:
<button onClick={() => config.setModalOpen(!config.isModalOpen)}>
{config.isModalOpen ? "Close chat" : "Open chat"}
</button>setModalOpen / isModalOpen are only defined when a provider in the tree owns
modal state. The prebuilt <CopilotPopup> and <CopilotSidebar> create it
automatically. If you compose chat yourself, wrap the relevant subtree in
<CopilotChatConfigurationProvider isModalDefaultOpen={false}> so the modal state
exists. See the
useCopilotChatConfiguration reference.
You can also set the initial open state declaratively. The prebuilt surfaces
accept a defaultOpen prop:
<CopilotSidebar defaultOpen />Capture message feedback (thumbs up / down)#
The assistant-message toolbar can show thumbs-up and thumbs-down buttons. In v2
you opt in by passing onThumbsUp / onThumbsDown to the assistant message
slot. The buttons only render when a handler is provided:
slot**. The buttons only render when a handler is provided:
import { CopilotChat } from "@copilotkit/react-core/v2";
<CopilotChat
messageView={{
assistantMessage: {
onThumbsUp: (message) => {
analytics.track("feedback", { messageId: message.id, value: "up" });
},
onThumbsDown: (message) => {
analytics.track("feedback", { messageId: message.id, value: "down" });
},
},
}}
/>;Each handler receives the assistant message, so you can record the feedback
against the specific response (message.id). The same messageView slot works on
<CopilotPopup> and <CopilotSidebar> since they wrap <CopilotChat>.
The button labels come from the chat labels (assistantMessageToolbarThumbsUpLabel
defaults to "Good response", assistantMessageToolbarThumbsDownLabel to
"Bad response"); override them via
chat labels.
Building a fully custom message component instead of using the slot? The
underlying CopilotChatAssistantMessage
exposes the same onThumbsUp / onThumbsDown props directly.
Related#
- CopilotPopup and CopilotSidebar: the prebuilt surfaces that own modal state.
useCopilotChatConfigurationreference: full context shape, modal state, and labels.- Slots: the
messageView/assistantMessageslot system used above. - Programmatic Control: driving agent runs from code without a chat UI.